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