/* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.sig.c,v 3.0 1991/07/04 23:34:26 christos Exp $ */ /* * sh.sig.c: Signal routine emulations */ /*- * Copyright (c) 1980, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #if !defined(lint) && !defined(pdp11) static char *rcsid() { return "$Id: tc.sig.c,v 3.0 1991/07/04 23:34:26 christos Exp $"; } #endif #include "sh.h" /* * a little complicated #include ! :-( */ #if SVID > 0 # ifdef hpux # ifndef __hpux # include "tc.wait.h" /* 6.5 broke */ # else # ifndef POSIX # define _BSD # endif # ifndef _CLASSIC_POSIX_TYPES # define _CLASSIC_POSIX_TYPES # endif # include /* 7.0 fixed it again */ # endif /* __hpux */ # else /* hpux */ # if defined(OREO) || defined(IRIS4D) || defined(POSIX) # include # else /* OREO || IRIS4D || POSIX */ # include "tc.wait.h" # endif /* OREO || IRIS4D || POSIX */ # endif /* hpux */ #else /* SVID == 0 */ # include #endif /* SVID == 0 */ #ifndef BSDSIGS /* libc.a contains these functions in SVID >= 3. */ #if SVID < 3 || defined(UNIXPC) sigret_t (*sigset(a, b)) () int a; int (*b) (); { return (signal(a, b)); } /* release signal * release all queued signals and * set the default signal handler */ void sigrelse(what) int what; { if (what == SIGCHLD) sig_ch_rel(); } /* hold signal * only works with child and interrupt */ void sighold(what) int what; { int sig_ch_queue(); if (what == SIGCHLD) (void) signal(SIGCHLD, sig_ch_queue); } /* ignore signal */ void sigignore(a) int a; { (void) signal(a, SIG_IGN); } #endif /* SVID < 3 || (UNIXPC) */ /* this stack is used to queue signals * we can handle up to MAX_CHLD outstanding children now; */ #define MAX_CHLD 50 static struct mysigstack { int s_w; /* wait report */ int s_errno; /* errno returned; */ int s_pid; /* pid returned */ } stk[MAX_CHLD]; static int stk_ptr = -1; /* return either awaiting processes or do a wait now */ int ourwait(w) int *w; { int pid; #ifdef JOBDEBUG xprintf("our wait %d\n", stk_ptr); flush(); #endif /* JOBDEBUG */ if (stk_ptr == -1) { /* stack empty return signal from stack */ pid = wait(w); #ifdef JOBDEBUG xprintf("signal(SIGCHLD, pchild);\n"); #endif /* JOBDEBUG */ (void) signal(SIGCHLD, pchild); return (pid); } else { /* return signal from stack */ errno = stk[stk_ptr].s_errno; *w = stk[stk_ptr].s_w; stk_ptr--; return (stk[stk_ptr + 1].s_pid); } } /* end ourwait */ /* queue child signals * */ static void sig_ch_queue() { #ifdef JOBDEBUG xprintf("queue SIGCHLD\n"); flush(); #endif /* JOBDEBUG */ stk_ptr++; stk[stk_ptr].s_pid = wait(&stk[stk_ptr].s_w); stk[stk_ptr].s_errno = errno; (void) signal(SIGCHLD, sig_ch_queue); } /* process all awaiting child signals */ static void sig_ch_rel() { while (stk_ptr > -1) pchild(SIGCHLD); #ifdef JOBDEBUG xprintf("signal(SIGCHLD, pchild);\n"); #endif /* JOBDEBUG */ (void) signal(SIGCHLD, pchild); } /* libc.a contains sigpause.o in SVID >= 3. */ #if SVID < 3 || defined(UNIXPC) /* atomically release one signal */ void sigpause(what) int what; { #ifdef notdef if (what == SIGCHLD) { if (stk_ptr > -1) { pchild(SIGCHLD); } else { (void) sleep(1); } } #endif /* From: Jim Mattson */ if (what == SIGCHLD) pchild(SIGCHLD); } #endif /* SVID < 3 || (UNIXPC) */ #ifdef SXA /* * SX/A is SVID3 but does not have sys5-sigpause(). * I've heard that sigpause() is not defined in SVID3. */ /* This is not need if you make tcsh by BSD option's cc. */ void sigpause(what) { if (what == SIGCHLD) { b_sigpause(b_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD)); } else if (what == 0) { pause(); } else { xprintf("sigpause(%d)\n", what); pause(); } } #endif /* SXA */ #endif /* BSDSIGS */ #ifdef NEEDsignal /* turn into bsd signals */ sigret_t(* xsignal(s, a)) () int s; sigret_t(*a) (); { sigvec_t osv, sv; (void) mysigvec(s, NULL, &osv); sv = osv; sv.sv_handler = a; #ifdef SIG_STK sv.sv_onstack = SIG_STK; #endif #if defined(SV_BSDSIG) && defined(SV_ONSTACK) sv.sv_flags = SV_BSDSIG | SV_ONSTACK; #endif if (mysigvec(s, &sv, NULL) < 0) return (BADSIG); return (osv.sv_handler); } #endif /* NEEDsignal */ #ifdef _SEQUENT_ /* * Support for signals. */ extern int errno; /* Set and test a bit. Bits numbered 1 to 32 */ #define SETBIT(x, y) x |= sigmask(y) #define ISSET(x, y) ((x & sigmask(y)) != 0) #ifdef DEBUG # define SHOW_SIGNALS 1 /* to assist in debugging signals */ #endif #ifdef SHOW_SIGNALS char *show_sig_mask(); #endif int debug_signals = 0; /* * igsetmask(mask) * * Set a new signal mask. Return old mask. */ sigmask_t sigsetmask(mask) sigmask_t mask; { sigset_t set, oset; int m; register int i; sigemptyset(&set); sigemptyset(&oset); for (i = 1; i <= MAXSIG; i++) if (ISSET(mask, i)) sigaddset(&set, i); if (sigprocmask(SIG_SETMASK, &set, &oset)) xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d", mask, errno); m = 0; for (i = 1; i < MAXSIG; i++) if (sigismember(&oset, i)) SETBIT(m, i); return (m); } /* * sigblock(mask) * * Add "mask" set of signals to the present signal mask. * Return old mask. */ sigmask_t sigblock(mask) sigmask_t mask; { sigset_t set, oset; int m; register int i; set = 0; oset = 0; /* Get present set of signals. */ if (sigprocmask(SIG_SETMASK, NULL, &set)) xprintf("sigblock(0x%x) - sigprocmask failed, errno %d", mask, errno); /* Add in signals from mask. */ for (i = 1; i <= MAXSIG; i++) if (ISSET(mask, i)) sigaddset(&set, i); sigprocmask(SIG_SETMASK, &set, &oset); /* Return old mask to user. */ m = 0; for (i = 1; i < MAXSIG; i++) if (sigismember(&oset, i)) SETBIT(m, i); return (m); } /* * b_sigpause(mask) * * Set new signal mask and wait for signal; * Old mask is restored on signal. */ void b_sigpause(mask) sigmask_t mask; { sigset_t set; register int i; sigemptyset(&set); for (i = 1; i <= MAXSIG; i++) if (ISSET(mask, i)) sigaddset(&set, i); sigsuspend(&set); } #endif /* _SEQUENT_ */ #ifdef SIGSYNCH static long Synch_Cnt = 0; sigret_t synch_handler(sno) int sno; { if (sno != SIGSYNCH) abort(); Synch_Cnt++; } #endif /* SIGSYNCH */