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

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

unix.superglobalmegacorp.com

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