Annotation of researchv10no/lbin/Mail/sigretro.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *sccsid = "@(#)sigretro.c  4.1 (Berkeley) 8/11/83";
                      3: #endif
                      4: 
                      5: #include <signal.h>
                      6: #include <errno.h>
                      7: #include <setjmp.h>
                      8: #include "sigretro.h"
                      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.