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

Defined functions

_sigtramp defined in line 266; used 8 times
sigchild defined in line 219; never used
sigdisp defined in line 233; used 5 times
sighold defined in line 125; used 8 times
sigignore defined in line 183; used 1 times
  • in line 27
sigpause defined in line 199; never used

Defined variables

SccsID defined in line 8; never used
_pause defined in line 47; used 2 times
sigtable defined in line 37; used 29 times

Defined struct's

sigtable defined in line 34; never used

Defined macros

SDEFER defined in line 43; used 6 times
SHELD defined in line 42; used 10 times
SPAUSE defined in line 45; used 3 times
SSET defined in line 44; used 4 times
Last modified: 1982-07-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1007
Valid CSS Valid XHTML 1.0 Strict