140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro * All rights reserved.
440266059SGregory Neil Shapiro *
540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro * the sendmail distribution.
840266059SGregory Neil Shapiro */
940266059SGregory Neil Shapiro
1040266059SGregory Neil Shapiro #include <sm/gen.h>
114313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: signal.c,v 1.18 2013-11-22 20:51:43 ca Exp $")
1240266059SGregory Neil Shapiro
1340266059SGregory Neil Shapiro #if SM_CONF_SETITIMER
144e4196cbSGregory Neil Shapiro # include <sm/time.h>
15*5b0945b5SGregory Neil Shapiro #endif
1640266059SGregory Neil Shapiro #include <errno.h>
1740266059SGregory Neil Shapiro #include <stdlib.h>
1840266059SGregory Neil Shapiro #include <time.h>
1940266059SGregory Neil Shapiro #include <unistd.h>
2040266059SGregory Neil Shapiro #include <sm/clock.h>
2140266059SGregory Neil Shapiro #include <sm/signal.h>
2240266059SGregory Neil Shapiro #include <signal.h>
2340266059SGregory Neil Shapiro #include <sm/string.h>
2440266059SGregory Neil Shapiro
2540266059SGregory Neil Shapiro unsigned int volatile InCriticalSection; /* >0 if inside critical section */
2640266059SGregory Neil Shapiro int volatile PendingSignal; /* pending signal to resend */
2740266059SGregory Neil Shapiro
2840266059SGregory Neil Shapiro /*
2940266059SGregory Neil Shapiro ** SM_SIGNAL -- set a signal handler
3040266059SGregory Neil Shapiro **
3140266059SGregory Neil Shapiro ** This is essentially old BSD "signal(3)".
3240266059SGregory Neil Shapiro **
3340266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
3440266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3540266059SGregory Neil Shapiro ** DOING.
3640266059SGregory Neil Shapiro */
3740266059SGregory Neil Shapiro
3840266059SGregory Neil Shapiro sigfunc_t
sm_signal(sig,handler)3940266059SGregory Neil Shapiro sm_signal(sig, handler)
4040266059SGregory Neil Shapiro int sig;
4140266059SGregory Neil Shapiro sigfunc_t handler;
4240266059SGregory Neil Shapiro {
4340266059SGregory Neil Shapiro #if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3))
4440266059SGregory Neil Shapiro struct sigaction n, o;
45*5b0945b5SGregory Neil Shapiro #endif
4640266059SGregory Neil Shapiro
4740266059SGregory Neil Shapiro /*
4840266059SGregory Neil Shapiro ** First, try for modern signal calls
4940266059SGregory Neil Shapiro ** and restartable syscalls
5040266059SGregory Neil Shapiro */
5140266059SGregory Neil Shapiro
5240266059SGregory Neil Shapiro #ifdef SA_RESTART
5340266059SGregory Neil Shapiro (void) memset(&n, '\0', sizeof n);
5440266059SGregory Neil Shapiro # if USE_SA_SIGACTION
5540266059SGregory Neil Shapiro n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
5640266059SGregory Neil Shapiro n.sa_flags = SA_RESTART|SA_SIGINFO;
57*5b0945b5SGregory Neil Shapiro # else
5840266059SGregory Neil Shapiro n.sa_handler = handler;
5940266059SGregory Neil Shapiro n.sa_flags = SA_RESTART;
60*5b0945b5SGregory Neil Shapiro # endif
6140266059SGregory Neil Shapiro if (sigaction(sig, &n, &o) < 0)
6240266059SGregory Neil Shapiro return SIG_ERR;
6340266059SGregory Neil Shapiro return o.sa_handler;
6440266059SGregory Neil Shapiro #else /* SA_RESTART */
6540266059SGregory Neil Shapiro
6640266059SGregory Neil Shapiro /*
6740266059SGregory Neil Shapiro ** Else check for SYS5SIGNALS or
6840266059SGregory Neil Shapiro ** BSD4_3 signals
6940266059SGregory Neil Shapiro */
7040266059SGregory Neil Shapiro
7140266059SGregory Neil Shapiro # if defined(SYS5SIGNALS) || defined(BSD4_3)
7240266059SGregory Neil Shapiro # ifdef BSD4_3
7340266059SGregory Neil Shapiro return signal(sig, handler);
74*5b0945b5SGregory Neil Shapiro # else
7540266059SGregory Neil Shapiro return sigset(sig, handler);
76*5b0945b5SGregory Neil Shapiro # endif
7740266059SGregory Neil Shapiro # else /* defined(SYS5SIGNALS) || defined(BSD4_3) */
7840266059SGregory Neil Shapiro
7940266059SGregory Neil Shapiro /*
8040266059SGregory Neil Shapiro ** Finally, if nothing else is available,
8140266059SGregory Neil Shapiro ** go for a default
8240266059SGregory Neil Shapiro */
8340266059SGregory Neil Shapiro
8440266059SGregory Neil Shapiro (void) memset(&n, '\0', sizeof n);
8540266059SGregory Neil Shapiro n.sa_handler = handler;
8640266059SGregory Neil Shapiro if (sigaction(sig, &n, &o) < 0)
8740266059SGregory Neil Shapiro return SIG_ERR;
8840266059SGregory Neil Shapiro return o.sa_handler;
8940266059SGregory Neil Shapiro # endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */
9040266059SGregory Neil Shapiro #endif /* SA_RESTART */
9140266059SGregory Neil Shapiro }
9240266059SGregory Neil Shapiro /*
9340266059SGregory Neil Shapiro ** SM_BLOCKSIGNAL -- hold a signal to prevent delivery
9440266059SGregory Neil Shapiro **
9540266059SGregory Neil Shapiro ** Parameters:
9640266059SGregory Neil Shapiro ** sig -- the signal to block.
9740266059SGregory Neil Shapiro **
9840266059SGregory Neil Shapiro ** Returns:
9940266059SGregory Neil Shapiro ** 1 signal was previously blocked
10040266059SGregory Neil Shapiro ** 0 signal was not previously blocked
10140266059SGregory Neil Shapiro ** -1 on failure.
10240266059SGregory Neil Shapiro */
10340266059SGregory Neil Shapiro
10440266059SGregory Neil Shapiro int
sm_blocksignal(sig)10540266059SGregory Neil Shapiro sm_blocksignal(sig)
10640266059SGregory Neil Shapiro int sig;
10740266059SGregory Neil Shapiro {
10840266059SGregory Neil Shapiro #ifdef BSD4_3
10940266059SGregory Neil Shapiro # ifndef sigmask
11040266059SGregory Neil Shapiro # define sigmask(s) (1 << ((s) - 1))
111*5b0945b5SGregory Neil Shapiro # endif
11240266059SGregory Neil Shapiro return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
11340266059SGregory Neil Shapiro #else /* BSD4_3 */
11440266059SGregory Neil Shapiro # ifdef ALTOS_SYSTEM_V
11540266059SGregory Neil Shapiro sigfunc_t handler;
11640266059SGregory Neil Shapiro
11740266059SGregory Neil Shapiro handler = sigset(sig, SIG_HOLD);
11840266059SGregory Neil Shapiro if (handler == SIG_ERR)
11940266059SGregory Neil Shapiro return -1;
12040266059SGregory Neil Shapiro else
12140266059SGregory Neil Shapiro return handler == SIG_HOLD;
12240266059SGregory Neil Shapiro # else /* ALTOS_SYSTEM_V */
12340266059SGregory Neil Shapiro sigset_t sset, oset;
12440266059SGregory Neil Shapiro
12540266059SGregory Neil Shapiro (void) sigemptyset(&sset);
12640266059SGregory Neil Shapiro (void) sigaddset(&sset, sig);
12740266059SGregory Neil Shapiro if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
12840266059SGregory Neil Shapiro return -1;
12940266059SGregory Neil Shapiro else
13040266059SGregory Neil Shapiro return sigismember(&oset, sig);
13140266059SGregory Neil Shapiro # endif /* ALTOS_SYSTEM_V */
13240266059SGregory Neil Shapiro #endif /* BSD4_3 */
13340266059SGregory Neil Shapiro }
13440266059SGregory Neil Shapiro /*
13540266059SGregory Neil Shapiro ** SM_RELEASESIGNAL -- release a held signal
13640266059SGregory Neil Shapiro **
13740266059SGregory Neil Shapiro ** Parameters:
13840266059SGregory Neil Shapiro ** sig -- the signal to release.
13940266059SGregory Neil Shapiro **
14040266059SGregory Neil Shapiro ** Returns:
14140266059SGregory Neil Shapiro ** 1 signal was previously blocked
14240266059SGregory Neil Shapiro ** 0 signal was not previously blocked
14340266059SGregory Neil Shapiro ** -1 on failure.
14440266059SGregory Neil Shapiro */
14540266059SGregory Neil Shapiro
14640266059SGregory Neil Shapiro int
sm_releasesignal(sig)14740266059SGregory Neil Shapiro sm_releasesignal(sig)
14840266059SGregory Neil Shapiro int sig;
14940266059SGregory Neil Shapiro {
15040266059SGregory Neil Shapiro #ifdef BSD4_3
15140266059SGregory Neil Shapiro return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
15240266059SGregory Neil Shapiro #else /* BSD4_3 */
15340266059SGregory Neil Shapiro # ifdef ALTOS_SYSTEM_V
15440266059SGregory Neil Shapiro sigfunc_t handler;
15540266059SGregory Neil Shapiro
15640266059SGregory Neil Shapiro handler = sigset(sig, SIG_HOLD);
15740266059SGregory Neil Shapiro if (sigrelse(sig) < 0)
15840266059SGregory Neil Shapiro return -1;
15940266059SGregory Neil Shapiro else
16040266059SGregory Neil Shapiro return handler == SIG_HOLD;
16140266059SGregory Neil Shapiro # else /* ALTOS_SYSTEM_V */
16240266059SGregory Neil Shapiro sigset_t sset, oset;
16340266059SGregory Neil Shapiro
16440266059SGregory Neil Shapiro (void) sigemptyset(&sset);
16540266059SGregory Neil Shapiro (void) sigaddset(&sset, sig);
16640266059SGregory Neil Shapiro if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
16740266059SGregory Neil Shapiro return -1;
16840266059SGregory Neil Shapiro else
16940266059SGregory Neil Shapiro return sigismember(&oset, sig);
17040266059SGregory Neil Shapiro # endif /* ALTOS_SYSTEM_V */
17140266059SGregory Neil Shapiro #endif /* BSD4_3 */
17240266059SGregory Neil Shapiro }
17340266059SGregory Neil Shapiro /*
17440266059SGregory Neil Shapiro ** PEND_SIGNAL -- Add a signal to the pending signal list
17540266059SGregory Neil Shapiro **
17640266059SGregory Neil Shapiro ** Parameters:
17740266059SGregory Neil Shapiro ** sig -- signal to add
17840266059SGregory Neil Shapiro **
17940266059SGregory Neil Shapiro ** Returns:
18040266059SGregory Neil Shapiro ** none.
18140266059SGregory Neil Shapiro **
18240266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
18340266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
18440266059SGregory Neil Shapiro ** DOING.
18540266059SGregory Neil Shapiro */
18640266059SGregory Neil Shapiro
18740266059SGregory Neil Shapiro void
pend_signal(sig)18840266059SGregory Neil Shapiro pend_signal(sig)
18940266059SGregory Neil Shapiro int sig;
19040266059SGregory Neil Shapiro {
19140266059SGregory Neil Shapiro int sigbit;
19240266059SGregory Neil Shapiro int save_errno = errno;
19340266059SGregory Neil Shapiro #if SM_CONF_SETITIMER
19440266059SGregory Neil Shapiro struct itimerval clr;
195*5b0945b5SGregory Neil Shapiro #endif
19640266059SGregory Neil Shapiro
19740266059SGregory Neil Shapiro /*
19840266059SGregory Neil Shapiro ** Don't want to interrupt something critical, hence delay
19940266059SGregory Neil Shapiro ** the alarm for one second. Hopefully, by then we
20040266059SGregory Neil Shapiro ** will be out of the critical section. If not, then
20140266059SGregory Neil Shapiro ** we will just delay again. The events to be run will
20240266059SGregory Neil Shapiro ** still all be run, maybe just a little bit late.
20340266059SGregory Neil Shapiro */
20440266059SGregory Neil Shapiro
20540266059SGregory Neil Shapiro switch (sig)
20640266059SGregory Neil Shapiro {
20740266059SGregory Neil Shapiro case SIGHUP:
20840266059SGregory Neil Shapiro sigbit = PEND_SIGHUP;
20940266059SGregory Neil Shapiro break;
21040266059SGregory Neil Shapiro
21140266059SGregory Neil Shapiro case SIGINT:
21240266059SGregory Neil Shapiro sigbit = PEND_SIGINT;
21340266059SGregory Neil Shapiro break;
21440266059SGregory Neil Shapiro
21540266059SGregory Neil Shapiro case SIGTERM:
21640266059SGregory Neil Shapiro sigbit = PEND_SIGTERM;
21740266059SGregory Neil Shapiro break;
21840266059SGregory Neil Shapiro
21940266059SGregory Neil Shapiro case SIGUSR1:
22040266059SGregory Neil Shapiro sigbit = PEND_SIGUSR1;
22140266059SGregory Neil Shapiro break;
22240266059SGregory Neil Shapiro
22340266059SGregory Neil Shapiro case SIGALRM:
22440266059SGregory Neil Shapiro /* don't have to pend these */
22540266059SGregory Neil Shapiro sigbit = 0;
22640266059SGregory Neil Shapiro break;
22740266059SGregory Neil Shapiro
22840266059SGregory Neil Shapiro default:
22940266059SGregory Neil Shapiro /* If we get here, we are in trouble */
23040266059SGregory Neil Shapiro abort();
23140266059SGregory Neil Shapiro
23240266059SGregory Neil Shapiro /* NOTREACHED */
23340266059SGregory Neil Shapiro /* shut up stupid compiler warning on HP-UX 11 */
23440266059SGregory Neil Shapiro sigbit = 0;
23540266059SGregory Neil Shapiro break;
23640266059SGregory Neil Shapiro }
23740266059SGregory Neil Shapiro
23840266059SGregory Neil Shapiro if (sigbit != 0)
23940266059SGregory Neil Shapiro PendingSignal |= sigbit;
24040266059SGregory Neil Shapiro (void) sm_signal(SIGALRM, sm_tick);
24140266059SGregory Neil Shapiro #if SM_CONF_SETITIMER
24240266059SGregory Neil Shapiro clr.it_interval.tv_sec = 0;
24340266059SGregory Neil Shapiro clr.it_interval.tv_usec = 0;
24440266059SGregory Neil Shapiro clr.it_value.tv_sec = 1;
24540266059SGregory Neil Shapiro clr.it_value.tv_usec = 0;
24640266059SGregory Neil Shapiro (void) setitimer(ITIMER_REAL, &clr, NULL);
24740266059SGregory Neil Shapiro #else /* SM_CONF_SETITIMER */
24840266059SGregory Neil Shapiro (void) alarm(1);
24940266059SGregory Neil Shapiro #endif /* SM_CONF_SETITIMER */
25040266059SGregory Neil Shapiro errno = save_errno;
25140266059SGregory Neil Shapiro }
25240266059SGregory Neil Shapiro /*
25340266059SGregory Neil Shapiro ** SM_ALLSIGNALS -- act on all signals
25440266059SGregory Neil Shapiro **
25540266059SGregory Neil Shapiro ** Parameters:
25640266059SGregory Neil Shapiro ** block -- whether to block or release all signals.
25740266059SGregory Neil Shapiro **
25840266059SGregory Neil Shapiro ** Returns:
25940266059SGregory Neil Shapiro ** none.
26040266059SGregory Neil Shapiro */
26140266059SGregory Neil Shapiro
26240266059SGregory Neil Shapiro void
sm_allsignals(block)26340266059SGregory Neil Shapiro sm_allsignals(block)
26440266059SGregory Neil Shapiro bool block;
26540266059SGregory Neil Shapiro {
26640266059SGregory Neil Shapiro #ifdef BSD4_3
26740266059SGregory Neil Shapiro # ifndef sigmask
26840266059SGregory Neil Shapiro # define sigmask(s) (1 << ((s) - 1))
269*5b0945b5SGregory Neil Shapiro # endif
27040266059SGregory Neil Shapiro if (block)
27140266059SGregory Neil Shapiro {
27240266059SGregory Neil Shapiro int mask = 0;
27340266059SGregory Neil Shapiro
27440266059SGregory Neil Shapiro mask |= sigmask(SIGALRM);
27540266059SGregory Neil Shapiro mask |= sigmask(SIGCHLD);
27640266059SGregory Neil Shapiro mask |= sigmask(SIGHUP);
27740266059SGregory Neil Shapiro mask |= sigmask(SIGINT);
27840266059SGregory Neil Shapiro mask |= sigmask(SIGTERM);
27940266059SGregory Neil Shapiro mask |= sigmask(SIGUSR1);
28040266059SGregory Neil Shapiro
28140266059SGregory Neil Shapiro (void) sigblock(mask);
28240266059SGregory Neil Shapiro }
28340266059SGregory Neil Shapiro else
28440266059SGregory Neil Shapiro sigsetmask(0);
28540266059SGregory Neil Shapiro #else /* BSD4_3 */
28640266059SGregory Neil Shapiro # ifdef ALTOS_SYSTEM_V
28740266059SGregory Neil Shapiro if (block)
28840266059SGregory Neil Shapiro {
28940266059SGregory Neil Shapiro (void) sigset(SIGALRM, SIG_HOLD);
29040266059SGregory Neil Shapiro (void) sigset(SIGCHLD, SIG_HOLD);
29140266059SGregory Neil Shapiro (void) sigset(SIGHUP, SIG_HOLD);
29240266059SGregory Neil Shapiro (void) sigset(SIGINT, SIG_HOLD);
29340266059SGregory Neil Shapiro (void) sigset(SIGTERM, SIG_HOLD);
29440266059SGregory Neil Shapiro (void) sigset(SIGUSR1, SIG_HOLD);
29540266059SGregory Neil Shapiro }
29640266059SGregory Neil Shapiro else
29740266059SGregory Neil Shapiro {
29840266059SGregory Neil Shapiro (void) sigset(SIGALRM, SIG_DFL);
29940266059SGregory Neil Shapiro (void) sigset(SIGCHLD, SIG_DFL);
30040266059SGregory Neil Shapiro (void) sigset(SIGHUP, SIG_DFL);
30140266059SGregory Neil Shapiro (void) sigset(SIGINT, SIG_DFL);
30240266059SGregory Neil Shapiro (void) sigset(SIGTERM, SIG_DFL);
30340266059SGregory Neil Shapiro (void) sigset(SIGUSR1, SIG_DFL);
30440266059SGregory Neil Shapiro }
30540266059SGregory Neil Shapiro # else /* ALTOS_SYSTEM_V */
30640266059SGregory Neil Shapiro sigset_t sset;
30740266059SGregory Neil Shapiro
30840266059SGregory Neil Shapiro (void) sigemptyset(&sset);
30940266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGALRM);
31040266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGCHLD);
31140266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGHUP);
31240266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGINT);
31340266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGTERM);
31440266059SGregory Neil Shapiro (void) sigaddset(&sset, SIGUSR1);
31540266059SGregory Neil Shapiro (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL);
31640266059SGregory Neil Shapiro # endif /* ALTOS_SYSTEM_V */
31740266059SGregory Neil Shapiro #endif /* BSD4_3 */
31840266059SGregory Neil Shapiro }
31940266059SGregory Neil Shapiro /*
32040266059SGregory Neil Shapiro ** SM_SIGNAL_NOOP -- A signal no-op function
32140266059SGregory Neil Shapiro **
32240266059SGregory Neil Shapiro ** Parameters:
32340266059SGregory Neil Shapiro ** sig -- signal received
32440266059SGregory Neil Shapiro **
32540266059SGregory Neil Shapiro ** Returns:
32640266059SGregory Neil Shapiro ** SIGFUNC_RETURN
32740266059SGregory Neil Shapiro */
32840266059SGregory Neil Shapiro
32940266059SGregory Neil Shapiro /* ARGSUSED */
33040266059SGregory Neil Shapiro SIGFUNC_DECL
sm_signal_noop(sig)33140266059SGregory Neil Shapiro sm_signal_noop(sig)
33240266059SGregory Neil Shapiro int sig;
33340266059SGregory Neil Shapiro {
33440266059SGregory Neil Shapiro int save_errno = errno;
33540266059SGregory Neil Shapiro
33640266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sm_signal_noop);
33740266059SGregory Neil Shapiro errno = save_errno;
33840266059SGregory Neil Shapiro return SIGFUNC_RETURN;
33940266059SGregory Neil Shapiro }
34040266059SGregory Neil Shapiro
341