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 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 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 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 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 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 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