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

unix.superglobalmegacorp.com

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