Annotation of 43BSDTahoe/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.
        !             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.