Annotation of 43BSD/ucb/Mail/sigretro.c, revision 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.