1: /* $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 $ */ 2: /* 3: * sh.sig.c: Signal routine emulations 4: */ 5: /*- 6: * Copyright (c) 1980, 1991 The Regents of the University of California. 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by the University of 20: * California, Berkeley and its contributors. 21: * 4. Neither the name of the University nor the names of its contributors 22: * may be used to endorse or promote products derived from this software 23: * without specific prior written permission. 24: * 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35: * SUCH DAMAGE. 36: */ 37: #include "config.h" 38: #if !defined(lint) && !defined(pdp11) 39: static char *rcsid() 40: { return "$Id: tc.sig.c,v 3.0 1991/07/04 23:34:26 christos Exp $"; } 41: #endif 42: 43: #include "sh.h" 44: /* 45: * a little complicated #include <sys/wait.h>! :-( 46: */ 47: #if SVID > 0 48: # ifdef hpux 49: # ifndef __hpux 50: # include "tc.wait.h" /* 6.5 broke <sys/wait.h> */ 51: # else 52: # ifndef POSIX 53: # define _BSD 54: # endif 55: # ifndef _CLASSIC_POSIX_TYPES 56: # define _CLASSIC_POSIX_TYPES 57: # endif 58: # include <sys/wait.h> /* 7.0 fixed it again */ 59: # endif /* __hpux */ 60: # else /* hpux */ 61: # if defined(OREO) || defined(IRIS4D) || defined(POSIX) 62: # include <sys/wait.h> 63: # else /* OREO || IRIS4D || POSIX */ 64: # include "tc.wait.h" 65: # endif /* OREO || IRIS4D || POSIX */ 66: # endif /* hpux */ 67: #else /* SVID == 0 */ 68: # include <sys/wait.h> 69: #endif /* SVID == 0 */ 70: 71: #ifndef BSDSIGS 72: /* libc.a contains these functions in SVID >= 3. */ 73: #if SVID < 3 || defined(UNIXPC) 74: sigret_t 75: (*sigset(a, b)) () 76: int a; 77: int (*b) (); 78: { 79: return (signal(a, b)); 80: } 81: 82: /* release signal 83: * release all queued signals and 84: * set the default signal handler 85: */ 86: void 87: sigrelse(what) 88: int what; 89: { 90: if (what == SIGCHLD) 91: sig_ch_rel(); 92: } 93: 94: /* hold signal 95: * only works with child and interrupt 96: */ 97: void 98: sighold(what) 99: int what; 100: { 101: int sig_ch_queue(); 102: 103: if (what == SIGCHLD) 104: (void) signal(SIGCHLD, sig_ch_queue); 105: } 106: 107: /* ignore signal 108: */ 109: void 110: sigignore(a) 111: int a; 112: { 113: (void) signal(a, SIG_IGN); 114: } 115: 116: #endif /* SVID < 3 || (UNIXPC) */ 117: 118: /* this stack is used to queue signals 119: * we can handle up to MAX_CHLD outstanding children now; 120: */ 121: #define MAX_CHLD 50 122: static struct mysigstack { 123: int s_w; /* wait report */ 124: int s_errno; /* errno returned; */ 125: int s_pid; /* pid returned */ 126: } stk[MAX_CHLD]; 127: static int stk_ptr = -1; 128: 129: 130: /* return either awaiting processes or do a wait now 131: */ 132: int 133: ourwait(w) 134: int *w; 135: { 136: int pid; 137: 138: #ifdef JOBDEBUG 139: xprintf("our wait %d\n", stk_ptr); 140: flush(); 141: #endif /* JOBDEBUG */ 142: 143: if (stk_ptr == -1) { 144: /* stack empty return signal from stack */ 145: pid = wait(w); 146: #ifdef JOBDEBUG 147: xprintf("signal(SIGCHLD, pchild);\n"); 148: #endif /* JOBDEBUG */ 149: (void) signal(SIGCHLD, pchild); 150: return (pid); 151: } 152: else { 153: /* return signal from stack */ 154: errno = stk[stk_ptr].s_errno; 155: *w = stk[stk_ptr].s_w; 156: stk_ptr--; 157: return (stk[stk_ptr + 1].s_pid); 158: } 159: } /* end ourwait */ 160: 161: /* queue child signals 162: * 163: */ 164: static void 165: sig_ch_queue() 166: { 167: #ifdef JOBDEBUG 168: xprintf("queue SIGCHLD\n"); 169: flush(); 170: #endif /* JOBDEBUG */ 171: stk_ptr++; 172: stk[stk_ptr].s_pid = wait(&stk[stk_ptr].s_w); 173: stk[stk_ptr].s_errno = errno; 174: (void) signal(SIGCHLD, sig_ch_queue); 175: } 176: 177: 178: 179: 180: /* process all awaiting child signals 181: */ 182: static void 183: sig_ch_rel() 184: { 185: while (stk_ptr > -1) 186: pchild(SIGCHLD); 187: #ifdef JOBDEBUG 188: xprintf("signal(SIGCHLD, pchild);\n"); 189: #endif /* JOBDEBUG */ 190: (void) signal(SIGCHLD, pchild); 191: } 192: 193: /* libc.a contains sigpause.o in SVID >= 3. */ 194: #if SVID < 3 || defined(UNIXPC) 195: 196: /* atomically release one signal 197: */ 198: void 199: sigpause(what) 200: int what; 201: { 202: #ifdef notdef 203: if (what == SIGCHLD) { 204: if (stk_ptr > -1) { 205: pchild(SIGCHLD); 206: } 207: else { 208: (void) sleep(1); 209: } 210: } 211: #endif 212: /* From: Jim Mattson <mattson%cs@ucsd.edu> */ 213: if (what == SIGCHLD) 214: pchild(SIGCHLD); 215: 216: } 217: 218: #endif /* SVID < 3 || (UNIXPC) */ 219: 220: #ifdef SXA 221: /* 222: * SX/A is SVID3 but does not have sys5-sigpause(). 223: * I've heard that sigpause() is not defined in SVID3. 224: */ 225: /* This is not need if you make tcsh by BSD option's cc. */ 226: void 227: sigpause(what) 228: { 229: if (what == SIGCHLD) { 230: b_sigpause(b_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD)); 231: } 232: else if (what == 0) { 233: pause(); 234: } 235: else { 236: xprintf("sigpause(%d)\n", what); 237: pause(); 238: } 239: } 240: 241: #endif /* SXA */ 242: #endif /* BSDSIGS */ 243: 244: #ifdef NEEDsignal 245: /* turn into bsd signals */ 246: sigret_t(* 247: xsignal(s, a)) () 248: int s; 249: 250: sigret_t(*a) (); 251: { 252: sigvec_t osv, sv; 253: 254: (void) mysigvec(s, NULL, &osv); 255: sv = osv; 256: sv.sv_handler = a; 257: #ifdef SIG_STK 258: sv.sv_onstack = SIG_STK; 259: #endif 260: #if defined(SV_BSDSIG) && defined(SV_ONSTACK) 261: sv.sv_flags = SV_BSDSIG | SV_ONSTACK; 262: #endif 263: 264: if (mysigvec(s, &sv, NULL) < 0) 265: return (BADSIG); 266: return (osv.sv_handler); 267: } 268: 269: #endif /* NEEDsignal */ 270: 271: #ifdef _SEQUENT_ 272: /* 273: * Support for signals. 274: */ 275: 276: extern int errno; 277: 278: /* Set and test a bit. Bits numbered 1 to 32 */ 279: 280: #define SETBIT(x, y) x |= sigmask(y) 281: #define ISSET(x, y) ((x & sigmask(y)) != 0) 282: 283: #ifdef DEBUG 284: # define SHOW_SIGNALS 1 /* to assist in debugging signals */ 285: #endif 286: 287: #ifdef SHOW_SIGNALS 288: char *show_sig_mask(); 289: #endif 290: 291: int debug_signals = 0; 292: 293: /* 294: * igsetmask(mask) 295: * 296: * Set a new signal mask. Return old mask. 297: */ 298: sigmask_t 299: sigsetmask(mask) 300: sigmask_t mask; 301: { 302: sigset_t set, oset; 303: int m; 304: register int i; 305: 306: sigemptyset(&set); 307: sigemptyset(&oset); 308: 309: for (i = 1; i <= MAXSIG; i++) 310: if (ISSET(mask, i)) 311: sigaddset(&set, i); 312: 313: if (sigprocmask(SIG_SETMASK, &set, &oset)) 314: xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d", 315: mask, errno); 316: 317: m = 0; 318: for (i = 1; i < MAXSIG; i++) 319: if (sigismember(&oset, i)) 320: SETBIT(m, i); 321: 322: return (m); 323: } 324: 325: /* 326: * sigblock(mask) 327: * 328: * Add "mask" set of signals to the present signal mask. 329: * Return old mask. 330: */ 331: sigmask_t 332: sigblock(mask) 333: sigmask_t mask; 334: { 335: sigset_t set, oset; 336: int m; 337: register int i; 338: 339: set = 0; 340: oset = 0; 341: 342: /* Get present set of signals. */ 343: if (sigprocmask(SIG_SETMASK, NULL, &set)) 344: xprintf("sigblock(0x%x) - sigprocmask failed, errno %d", 345: mask, errno); 346: 347: /* Add in signals from mask. */ 348: for (i = 1; i <= MAXSIG; i++) 349: if (ISSET(mask, i)) 350: sigaddset(&set, i); 351: 352: sigprocmask(SIG_SETMASK, &set, &oset); 353: 354: /* Return old mask to user. */ 355: m = 0; 356: for (i = 1; i < MAXSIG; i++) 357: if (sigismember(&oset, i)) 358: SETBIT(m, i); 359: 360: return (m); 361: } 362: 363: 364: /* 365: * b_sigpause(mask) 366: * 367: * Set new signal mask and wait for signal; 368: * Old mask is restored on signal. 369: */ 370: void 371: b_sigpause(mask) 372: sigmask_t mask; 373: { 374: sigset_t set; 375: register int i; 376: 377: sigemptyset(&set); 378: 379: for (i = 1; i <= MAXSIG; i++) 380: if (ISSET(mask, i)) 381: sigaddset(&set, i); 382: sigsuspend(&set); 383: } 384: 385: #endif /* _SEQUENT_ */ 386: 387: 388: #ifdef SIGSYNCH 389: static long Synch_Cnt = 0; 390: 391: sigret_t 392: synch_handler(sno) 393: int sno; 394: { 395: if (sno != SIGSYNCH) 396: abort(); 397: Synch_Cnt++; 398: } 399: 400: #endif /* SIGSYNCH */