Annotation of 43BSD/ucb/Mail/sigretro.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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