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