#include <sm/gen.h>
SM_RCSID("@(#)$Id: signal.c,v 1.17 2005/06/14 23:07:20 ca Exp $")
#if SM_CONF_SETITIMER
# include <sm/time.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sm/clock.h>
#include <sm/signal.h>
#include <signal.h>
#include <sm/string.h>
unsigned int volatile InCriticalSection;
int volatile PendingSignal;
sigfunc_t
sm_signal(sig, handler)
int sig;
sigfunc_t handler;
{
# if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3))
struct sigaction n, o;
# endif
# ifdef SA_RESTART
(void) memset(&n, '\0', sizeof n);
# if USE_SA_SIGACTION
n.sa_sigaction = (void(*)(int, siginfo_t *, void *))(uintptr_t) handler;
n.sa_flags = SA_RESTART|SA_SIGINFO;
# else
n.sa_handler = handler;
n.sa_flags = SA_RESTART;
# endif
if (sigaction(sig, &n, &o) < 0)
return SIG_ERR;
return o.sa_handler;
# else
# if defined(SYS5SIGNALS) || defined(BSD4_3)
# ifdef BSD4_3
return signal(sig, handler);
# else
return sigset(sig, handler);
# endif
# else
(void) memset(&n, '\0', sizeof n);
n.sa_handler = handler;
if (sigaction(sig, &n, &o) < 0)
return SIG_ERR;
return o.sa_handler;
# endif
# endif
}
int
sm_blocksignal(sig)
int sig;
{
# ifdef BSD4_3
# ifndef sigmask
# define sigmask(s) (1 << ((s) - 1))
# endif
return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
# else
# ifdef ALTOS_SYSTEM_V
sigfunc_t handler;
handler = sigset(sig, SIG_HOLD);
if (handler == SIG_ERR)
return -1;
else
return handler == SIG_HOLD;
# else
sigset_t sset, oset;
(void) sigemptyset(&sset);
(void) sigaddset(&sset, sig);
if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
return -1;
else
return sigismember(&oset, sig);
# endif
# endif
}
int
sm_releasesignal(sig)
int sig;
{
# ifdef BSD4_3
return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
# else
# ifdef ALTOS_SYSTEM_V
sigfunc_t handler;
handler = sigset(sig, SIG_HOLD);
if (sigrelse(sig) < 0)
return -1;
else
return handler == SIG_HOLD;
# else
sigset_t sset, oset;
(void) sigemptyset(&sset);
(void) sigaddset(&sset, sig);
if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
return -1;
else
return sigismember(&oset, sig);
# endif
# endif
}
void
pend_signal(sig)
int sig;
{
int sigbit;
int save_errno = errno;
#if SM_CONF_SETITIMER
struct itimerval clr;
#endif
switch (sig)
{
case SIGHUP:
sigbit = PEND_SIGHUP;
break;
case SIGINT:
sigbit = PEND_SIGINT;
break;
case SIGTERM:
sigbit = PEND_SIGTERM;
break;
case SIGUSR1:
sigbit = PEND_SIGUSR1;
break;
case SIGALRM:
sigbit = 0;
break;
default:
abort();
sigbit = 0;
break;
}
if (sigbit != 0)
PendingSignal |= sigbit;
(void) sm_signal(SIGALRM, sm_tick);
#if SM_CONF_SETITIMER
clr.it_interval.tv_sec = 0;
clr.it_interval.tv_usec = 0;
clr.it_value.tv_sec = 1;
clr.it_value.tv_usec = 0;
(void) setitimer(ITIMER_REAL, &clr, NULL);
#else
(void) alarm(1);
#endif
errno = save_errno;
}
void
sm_allsignals(block)
bool block;
{
# ifdef BSD4_3
# ifndef sigmask
# define sigmask(s) (1 << ((s) - 1))
# endif
if (block)
{
int mask = 0;
mask |= sigmask(SIGALRM);
mask |= sigmask(SIGCHLD);
mask |= sigmask(SIGHUP);
mask |= sigmask(SIGINT);
mask |= sigmask(SIGTERM);
mask |= sigmask(SIGUSR1);
(void) sigblock(mask);
}
else
sigsetmask(0);
# else
# ifdef ALTOS_SYSTEM_V
if (block)
{
(void) sigset(SIGALRM, SIG_HOLD);
(void) sigset(SIGCHLD, SIG_HOLD);
(void) sigset(SIGHUP, SIG_HOLD);
(void) sigset(SIGINT, SIG_HOLD);
(void) sigset(SIGTERM, SIG_HOLD);
(void) sigset(SIGUSR1, SIG_HOLD);
}
else
{
(void) sigset(SIGALRM, SIG_DFL);
(void) sigset(SIGCHLD, SIG_DFL);
(void) sigset(SIGHUP, SIG_DFL);
(void) sigset(SIGINT, SIG_DFL);
(void) sigset(SIGTERM, SIG_DFL);
(void) sigset(SIGUSR1, SIG_DFL);
}
# else
sigset_t sset;
(void) sigemptyset(&sset);
(void) sigaddset(&sset, SIGALRM);
(void) sigaddset(&sset, SIGCHLD);
(void) sigaddset(&sset, SIGHUP);
(void) sigaddset(&sset, SIGINT);
(void) sigaddset(&sset, SIGTERM);
(void) sigaddset(&sset, SIGUSR1);
(void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL);
# endif
# endif
}
SIGFUNC_DECL
sm_signal_noop(sig)
int sig;
{
int save_errno = errno;
FIX_SYSV_SIGNAL(sig, sm_signal_noop);
errno = save_errno;
return SIGFUNC_RETURN;
}