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: }

Defined functions

_sigtramp defined in line 272; used 8 times
sigchild defined in line 225; never used
sigdisp defined in line 239; used 5 times
sighold defined in line 131; used 2 times
sigignore defined in line 189; used 1 times
  • in line 33
sigpause defined in line 205; never used
sigrelse defined in line 160; never used
sigset defined in line 79; used 1 times
sigsys defined in line 63; never used

Defined variables

_pause defined in line 53; used 2 times
sccsid defined in line 8; never used
sigtable defined in line 43; used 29 times

Defined struct's

sigtable defined in line 40; never used

Defined macros

SDEFER defined in line 49; used 6 times
SHELD defined in line 48; used 10 times
SPAUSE defined in line 51; used 3 times
SSET defined in line 50; used 4 times
Last modified: 1985-06-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1289
Valid CSS Valid XHTML 1.0 Strict