|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid = "@(#)sigretro.c 5.2 (Berkeley) 6/21/85"; ! 9: #endif not lint ! 10: ! 11: #include <signal.h> ! 12: #include <errno.h> ! 13: #include <setjmp.h> ! 14: #include "sigretro.h" ! 15: ! 16: /* ! 17: * Retrofit new signal interface to old signal primitives. ! 18: * Supported routines: ! 19: * sigsys(sig, func) ! 20: * sigset(sig, func) ! 21: * sighold(sig) ! 22: * sigrelse(sig) ! 23: * sigignore(sig) ! 24: * sigpause(sig) ! 25: * Also, ! 26: * sigchild() ! 27: * to set all held signals to ignored signals in the ! 28: * child process after fork(2) ! 29: */ ! 30: ! 31: typedef int (*sigtype)(); ! 32: ! 33: sigtype sigdisp(), sighold(), sigignore(); ! 34: ! 35: /* ! 36: * The following helps us keep the extended signal semantics together. ! 37: * We remember for each signal the address of the function we're ! 38: * supposed to call. s_func is SIG_DFL / SIG_IGN if appropriate. ! 39: */ ! 40: struct sigtable { ! 41: sigtype s_func; /* What to call */ ! 42: int s_flag; /* Signal flags; see below */ ! 43: } sigtable[NSIG + 1]; ! 44: ! 45: /* ! 46: * Signal flag values. ! 47: */ ! 48: #define SHELD 1 /* Signal is being held */ ! 49: #define SDEFER 2 /* Signal occured while held */ ! 50: #define SSET 4 /* s_func is believable */ ! 51: #define SPAUSE 8 /* are pausing, waiting for sig */ ! 52: ! 53: jmp_buf _pause; /* For doing sigpause() */ ! 54: ! 55: /* ! 56: * Approximate sigsys() system call ! 57: * This is almost useless since one only calls sigsys() ! 58: * in the child of a vfork(). If you have vfork(), you have new signals ! 59: * anyway. The real sigsys() does all the stuff needed to support ! 60: * the real sigset() library. We don't bother here, assuming that ! 61: * you are either ignoring or defaulting a signal in the child. ! 62: */ ! 63: sigtype ! 64: sigsys(sig, func) ! 65: sigtype func; ! 66: { ! 67: sigtype old; ! 68: ! 69: old = sigdisp(sig); ! 70: signal(sig, func); ! 71: return(old); ! 72: } ! 73: ! 74: /* ! 75: * Set the (permanent) disposition of a signal. ! 76: * If the signal is subsequently (or even now) held, ! 77: * the action you set here can be enabled using sigrelse(). ! 78: */ ! 79: sigtype ! 80: sigset(sig, func) ! 81: sigtype func; ! 82: { ! 83: sigtype old; ! 84: int _sigtramp(); ! 85: extern int errno; ! 86: ! 87: if (sig < 1 || sig > NSIG) { ! 88: errno = EINVAL; ! 89: return(BADSIG); ! 90: } ! 91: old = sigdisp(sig); ! 92: /* ! 93: * Does anyone actually call sigset with SIG_HOLD!? ! 94: */ ! 95: if (func == SIG_HOLD) { ! 96: sighold(sig); ! 97: return(old); ! 98: } ! 99: sigtable[sig].s_flag |= SSET; ! 100: sigtable[sig].s_func = func; ! 101: if (func == SIG_DFL) { ! 102: /* ! 103: * If signal has been held, must retain ! 104: * the catch so that we can note occurrance ! 105: * of signal. ! 106: */ ! 107: if ((sigtable[sig].s_flag & SHELD) == 0) ! 108: signal(sig, SIG_DFL); ! 109: else ! 110: signal(sig, _sigtramp); ! 111: return(old); ! 112: } ! 113: if (func == SIG_IGN) { ! 114: /* ! 115: * Clear pending signal ! 116: */ ! 117: signal(sig, SIG_IGN); ! 118: sigtable[sig].s_flag &= ~SDEFER; ! 119: return(old); ! 120: } ! 121: signal(sig, _sigtramp); ! 122: return(old); ! 123: } ! 124: ! 125: /* ! 126: * Hold a signal. ! 127: * This CAN be tricky if the signal's disposition is SIG_DFL. ! 128: * In that case, we still catch the signal so we can note it ! 129: * happened and do something crazy later. ! 130: */ ! 131: sigtype ! 132: sighold(sig) ! 133: { ! 134: sigtype old; ! 135: extern int errno; ! 136: ! 137: if (sig < 1 || sig > NSIG) { ! 138: errno = EINVAL; ! 139: return(BADSIG); ! 140: } ! 141: old = sigdisp(sig); ! 142: if (sigtable[sig].s_flag & SHELD) ! 143: return(old); ! 144: /* ! 145: * When the default action is required, we have to ! 146: * set up to catch the signal to note signal's occurrance. ! 147: */ ! 148: if (old == SIG_DFL) { ! 149: sigtable[sig].s_flag |= SSET; ! 150: signal(sig, _sigtramp); ! 151: } ! 152: sigtable[sig].s_flag |= SHELD; ! 153: return(old); ! 154: } ! 155: ! 156: /* ! 157: * Release a signal ! 158: * If the signal occurred while we had it held, cause the signal. ! 159: */ ! 160: sigtype ! 161: sigrelse(sig) ! 162: { ! 163: sigtype old; ! 164: extern int errno; ! 165: int _sigtramp(); ! 166: ! 167: if (sig < 1 || sig > NSIG) { ! 168: errno = EINVAL; ! 169: return(BADSIG); ! 170: } ! 171: old = sigdisp(sig); ! 172: if ((sigtable[sig].s_flag & SHELD) == 0) ! 173: return(old); ! 174: sigtable[sig].s_flag &= ~SHELD; ! 175: if (sigtable[sig].s_flag & SDEFER) ! 176: _sigtramp(sig); ! 177: /* ! 178: * If disposition was the default, then we can unset the ! 179: * catch to _sigtramp() and let the system do the work. ! 180: */ ! 181: if (sigtable[sig].s_func == SIG_DFL) ! 182: signal(sig, SIG_DFL); ! 183: return(old); ! 184: } ! 185: ! 186: /* ! 187: * Ignore a signal. ! 188: */ ! 189: sigtype ! 190: sigignore(sig) ! 191: { ! 192: ! 193: return(sigset(sig, SIG_IGN)); ! 194: } ! 195: ! 196: /* ! 197: * Pause, waiting for sig to occur. ! 198: * We assume LUSER called us with the signal held. ! 199: * When we got the signal, mark the signal as having ! 200: * occurred. It will actually cause something when ! 201: * the signal is released. ! 202: * ! 203: * This is probably useless without job control anyway. ! 204: */ ! 205: sigpause(sig) ! 206: { ! 207: extern int errno; ! 208: ! 209: if (sig < 1 || sig > NSIG) { ! 210: errno = EINVAL; ! 211: return; ! 212: } ! 213: sigtable[sig].s_flag |= SHELD|SPAUSE; ! 214: if (setjmp(_pause) == 0) ! 215: pause(); ! 216: sigtable[sig].s_flag &= ~SPAUSE; ! 217: sigtable[sig].s_flag |= SDEFER; ! 218: } ! 219: ! 220: /* ! 221: * In the child process after fork(2), set the disposition of all held ! 222: * signals to SIG_IGN. This is a new procedure not in the real sigset() ! 223: * package, provided for retrofitting purposes. ! 224: */ ! 225: sigchild() ! 226: { ! 227: register int i; ! 228: ! 229: for (i = 1; i <= NSIG; i++) ! 230: if (sigtable[i].s_flag & SHELD) ! 231: signal(i, SIG_IGN); ! 232: } ! 233: ! 234: /* ! 235: * Return the current disposition of a signal ! 236: * If we have not set this signal before, we have to ! 237: * ask the system ! 238: */ ! 239: sigtype ! 240: sigdisp(sig) ! 241: { ! 242: extern int errno; ! 243: sigtype old; ! 244: ! 245: if (sig < 1 || sig > NSIG) { ! 246: errno = EINVAL; ! 247: return(BADSIG); ! 248: } ! 249: /* ! 250: * If we have no knowledge of this signal, ! 251: * ask the system, then save the result for later. ! 252: */ ! 253: if ((sigtable[sig].s_flag & SSET) == 0) { ! 254: old = signal(sig, SIG_IGN); ! 255: sigtable[sig].s_func = old; ! 256: sigtable[sig].s_flag |= SSET; ! 257: signal(sig, old); ! 258: return(old); ! 259: } ! 260: /* ! 261: * If we have set this signal before, then sigset() ! 262: * will have been careful to leave something meaningful ! 263: * in s_func. ! 264: */ ! 265: return(sigtable[sig].s_func); ! 266: } ! 267: ! 268: /* ! 269: * The following routine gets called for any signal ! 270: * that is to be trapped to a user function. ! 271: */ ! 272: _sigtramp(sig) ! 273: { ! 274: extern int errno; ! 275: sigtype old; ! 276: ! 277: if (sig < 1 || sig > NSIG) { ! 278: errno = EINVAL; ! 279: return; ! 280: } ! 281: ! 282: top: ! 283: old = signal(sig, SIG_IGN); ! 284: /* ! 285: * If signal being paused on, wakeup sigpause() ! 286: */ ! 287: if (sigtable[sig].s_flag & SPAUSE) ! 288: longjmp(_pause, 1); ! 289: /* ! 290: * If signal being held, mark its table entry ! 291: * so we can trigger it when signal released. ! 292: * Then just return. ! 293: */ ! 294: if (sigtable[sig].s_flag & SHELD) { ! 295: sigtable[sig].s_flag |= SDEFER; ! 296: signal(sig, _sigtramp); ! 297: return; ! 298: } ! 299: /* ! 300: * If the signal is being ignored, just return. ! 301: * This would make SIGCONT more normal, but of course ! 302: * any system with SIGCONT also has the new signal pkg, so... ! 303: */ ! 304: if (sigtable[sig].s_func == SIG_IGN) ! 305: return; ! 306: /* ! 307: * If the signal is SIG_DFL, then we probably got here ! 308: * by holding the signal, having it happen, then releasing ! 309: * the signal. I wonder if a process is allowed to send ! 310: * a signal to itself? ! 311: */ ! 312: if (sigtable[sig].s_func == SIG_DFL) { ! 313: signal(sig, SIG_DFL); ! 314: kill(getpid(), sig); ! 315: /* Will we get back here? */ ! 316: return; ! 317: } ! 318: /* ! 319: * Looks like we should just cause the signal... ! 320: * We hold the signal for the duration of the user's ! 321: * code with the signal re-enabled. If the signal ! 322: * happens again while in user code, we will recursively ! 323: * trap here and mark that we had another occurance ! 324: * and return to the user's trap code. When we return ! 325: * from there, we can cause the signal again. ! 326: */ ! 327: sigtable[sig].s_flag &= ~SDEFER; ! 328: sigtable[sig].s_flag |= SHELD; ! 329: signal(sig, _sigtramp); ! 330: (*sigtable[sig].s_func)(sig); ! 331: /* ! 332: * If the signal re-occurred while in the user's routine, ! 333: * just go try it again... ! 334: */ ! 335: sigtable[sig].s_flag &= ~SHELD; ! 336: if (sigtable[sig].s_flag & SDEFER) ! 337: goto top; ! 338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.