BSD 4_1c_2 release
[unix-history] / usr / src / usr.lib / libjobs / sigset.c
/* @(#)sigset.c 4.1 (Berkeley) 12/28/82 */
#include <signal.h>
#include <errno.h>
/*
* signal system call interface package.
*/
extern errno;
#ifdef PDP11
#define BYTESPERVEC 4 /* size of machine language vector */
extern char mvectors[NSIG+1][BYTESPERVEC];
#endif
static int (*cactions[NSIG+1])(); /* saved callers signal actions */
static char setflg[NSIG+1]; /* =1 means action perm ``sigset'' */
int (*sigsys())();
int _sigcatch();
/*
* old signal protocol. when signal occurs, further
* instances of same signal are not blocked, so that
* recursive signals are possible. the action will
* not be re-enabled by these routines when return
* is made from the interrupt (compare sigset).
*/
int (*
signal(signum, action))()
register int signum;
register int (*action)();
{
register int (*retval)();
if (signum <= 0 || signum > NSIG) {
errno = EINVAL;
return (BADSIG);
}
retval = cactions[signum];
cactions[signum] = action;
if (action != SIG_IGN && action != SIG_DFL && action != SIG_HOLD)
if (SIGISDEFER(action))
#ifdef PDP11
action = DEFERSIG(mvectors[signum]);
else
action = (int (*)())(int)mvectors[signum];
#else
action = DEFERSIG(_sigcatch);
else
action = _sigcatch;
#endif
action = sigsys(signum, action);
if (action == SIG_IGN || action == SIG_DFL || action == SIG_HOLD)
retval = action;
setflg[signum] = 0; /* 'tis fleeting (madness may take its toll) */
return (retval);
}
/*
* set ``permanent'' action for this signal. if a function,
* it will be deferred when interupt occurs and enabled again
* when return occurs. after sigset, sighold and sigrelse can
* be used to protect signum signal critical sections.
*/
int (*
sigset(signum, action))()
register int signum;
register int (*action)();
{
register int (*retval)();
if (signum <= 0 || signum > NSIG) {
errno = EINVAL;
return (BADSIG);
}
retval = cactions[signum];
cactions[signum] = action;
if (action != SIG_IGN && action != SIG_DFL && action != SIG_HOLD)
action = DEFERSIG(_sigcatch);
action = sigsys(signum, action);
if (action == SIG_IGN || action == SIG_DFL || action == SIG_HOLD)
retval = action;
setflg[signum] = 1; /* don't want to lose control! */
return (retval);
}
/*
* temporarily hold a signal until further notice
* via sigpause or sigrelse
*/
sighold(signum)
register int signum;
{
if (signum <= 0 || signum > NSIG) {
errno = EINVAL;
return;
}
sigsys(signum, SIG_HOLD);
}
/*
* atomically release the signal and pause
* if no signals pending. signal will normally
* be held on return (unless an routine called at
* interrupt time resets it).
*/
sigpause(signum)
register signum;
{
if (signum <= 0 || signum > NSIG || setflg[signum] == 0) {
errno = EINVAL;
return;
}
#ifdef PDP11
sigsys(signum|SIGDOPAUSE, DEFERSIG(mvectors[signum]));
#else
sigsys(signum|SIGDOPAUSE, DEFERSIG(_sigcatch));
#endif
}
/*
* re-enable signals after sighold or possibly after sigpause
*/
sigrelse(signum)
register signum;
{
if (signum <= 0 || signum > NSIG || setflg[signum] == 0) {
errno = EINVAL;
return (-1);
}
#ifdef PDP11
sigsys(signum, DEFERSIG(mvectors[signum]));
#else
sigsys(signum, DEFERSIG(_sigcatch));
#endif
return (0);
}
/*
* ignore signal
*/
sigignore(signum)
int signum;
{
sigsys(signum, SIG_IGN);
}
#ifdef PDP11
/*
* called at interrupt time. on pdp11 assembly language
* routine resets signal catch to returned action, if
* returned action is not SIG_DFL.
*/
int (*
_sigcatch(signum))()
register signum;
{
(*cactions[signum])(signum); /* call the C routine */
if (setflg[signum])
return (DEFERSIG(mvectors[signum]);
else
return (SIG_DFL); /* old protocol */
}
#else
/*
* called at interrupt time. on vax, sigpeel will peel
* off the interrupt frames and reenable the signal with
* the argument action (cleanly). if the action is
* SIG_DFL sigpeel will do nothing, but we can as well
* return ourselves without its help.
*/
_sigcatch(signum, code, xx, ps, pc)
register signum;
int code;
{
register int (*act)() = cactions[signum];
{ asm("callg (ap),(r10)"); }
if (setflg[signum]) {
sigpeel(signum, DEFERSIG(_sigcatch));
/*NOTREACHED*/
}
/* old protocol, just return */
}
#endif