2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
10 #pragma ident "%Z%%M% %I% %E% SMI"
13 SM_RCSID("@(#)$Id: signal.c,v 1.17 2005/06/14 23:07:20 ca Exp $")
17 #endif /* SM_CONF_SETITIMER */
23 #include <sm/signal.h>
25 #include <sm/string.h>
27 unsigned int volatile InCriticalSection
; /* >0 if inside critical section */
28 int volatile PendingSignal
; /* pending signal to resend */
31 ** SM_SIGNAL -- set a signal handler
33 ** This is essentially old BSD "signal(3)".
35 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
36 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
41 sm_signal(sig
, handler
)
45 # if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3))
46 struct sigaction n
, o
;
47 # endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */
50 ** First, try for modern signal calls
51 ** and restartable syscalls
55 (void) memset(&n
, '\0', sizeof n
);
57 n
.sa_sigaction
= (void(*)(int, siginfo_t
*, void *)) handler
;
58 n
.sa_flags
= SA_RESTART
|SA_SIGINFO
;
59 # else /* USE_SA_SIGACTION */
60 n
.sa_handler
= handler
;
61 n
.sa_flags
= SA_RESTART
;
62 # endif /* USE_SA_SIGACTION */
63 if (sigaction(sig
, &n
, &o
) < 0)
66 # else /* SA_RESTART */
69 ** Else check for SYS5SIGNALS or
73 # if defined(SYS5SIGNALS) || defined(BSD4_3)
75 return signal(sig
, handler
);
77 return sigset(sig
, handler
);
79 # else /* defined(SYS5SIGNALS) || defined(BSD4_3) */
82 ** Finally, if nothing else is available,
86 (void) memset(&n
, '\0', sizeof n
);
87 n
.sa_handler
= handler
;
88 if (sigaction(sig
, &n
, &o
) < 0)
91 # endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */
92 # endif /* SA_RESTART */
95 ** SM_BLOCKSIGNAL -- hold a signal to prevent delivery
98 ** sig -- the signal to block.
101 ** 1 signal was previously blocked
102 ** 0 signal was not previously blocked
112 # define sigmask(s) (1 << ((s) - 1))
113 # endif /* ! sigmask */
114 return (sigblock(sigmask(sig
)) & sigmask(sig
)) != 0;
116 # ifdef ALTOS_SYSTEM_V
119 handler
= sigset(sig
, SIG_HOLD
);
120 if (handler
== SIG_ERR
)
123 return handler
== SIG_HOLD
;
124 # else /* ALTOS_SYSTEM_V */
127 (void) sigemptyset(&sset
);
128 (void) sigaddset(&sset
, sig
);
129 if (sigprocmask(SIG_BLOCK
, &sset
, &oset
) < 0)
132 return sigismember(&oset
, sig
);
133 # endif /* ALTOS_SYSTEM_V */
137 ** SM_RELEASESIGNAL -- release a held signal
140 ** sig -- the signal to release.
143 ** 1 signal was previously blocked
144 ** 0 signal was not previously blocked
149 sm_releasesignal(sig
)
153 return (sigsetmask(sigblock(0) & ~sigmask(sig
)) & sigmask(sig
)) != 0;
155 # ifdef ALTOS_SYSTEM_V
158 handler
= sigset(sig
, SIG_HOLD
);
159 if (sigrelse(sig
) < 0)
162 return handler
== SIG_HOLD
;
163 # else /* ALTOS_SYSTEM_V */
166 (void) sigemptyset(&sset
);
167 (void) sigaddset(&sset
, sig
);
168 if (sigprocmask(SIG_UNBLOCK
, &sset
, &oset
) < 0)
171 return sigismember(&oset
, sig
);
172 # endif /* ALTOS_SYSTEM_V */
176 ** PEND_SIGNAL -- Add a signal to the pending signal list
179 ** sig -- signal to add
184 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
185 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
194 int save_errno
= errno
;
195 #if SM_CONF_SETITIMER
196 struct itimerval clr
;
197 #endif /* SM_CONF_SETITIMER */
200 ** Don't want to interrupt something critical, hence delay
201 ** the alarm for one second. Hopefully, by then we
202 ** will be out of the critical section. If not, then
203 ** we will just delay again. The events to be run will
204 ** still all be run, maybe just a little bit late.
210 sigbit
= PEND_SIGHUP
;
214 sigbit
= PEND_SIGINT
;
218 sigbit
= PEND_SIGTERM
;
222 sigbit
= PEND_SIGUSR1
;
226 /* don't have to pend these */
231 /* If we get here, we are in trouble */
235 /* shut up stupid compiler warning on HP-UX 11 */
241 PendingSignal
|= sigbit
;
242 (void) sm_signal(SIGALRM
, sm_tick
);
243 #if SM_CONF_SETITIMER
244 clr
.it_interval
.tv_sec
= 0;
245 clr
.it_interval
.tv_usec
= 0;
246 clr
.it_value
.tv_sec
= 1;
247 clr
.it_value
.tv_usec
= 0;
248 (void) setitimer(ITIMER_REAL
, &clr
, NULL
);
249 #else /* SM_CONF_SETITIMER */
251 #endif /* SM_CONF_SETITIMER */
255 ** SM_ALLSIGNALS -- act on all signals
258 ** block -- whether to block or release all signals.
270 # define sigmask(s) (1 << ((s) - 1))
271 # endif /* ! sigmask */
276 mask
|= sigmask(SIGALRM
);
277 mask
|= sigmask(SIGCHLD
);
278 mask
|= sigmask(SIGHUP
);
279 mask
|= sigmask(SIGINT
);
280 mask
|= sigmask(SIGTERM
);
281 mask
|= sigmask(SIGUSR1
);
283 (void) sigblock(mask
);
288 # ifdef ALTOS_SYSTEM_V
291 (void) sigset(SIGALRM
, SIG_HOLD
);
292 (void) sigset(SIGCHLD
, SIG_HOLD
);
293 (void) sigset(SIGHUP
, SIG_HOLD
);
294 (void) sigset(SIGINT
, SIG_HOLD
);
295 (void) sigset(SIGTERM
, SIG_HOLD
);
296 (void) sigset(SIGUSR1
, SIG_HOLD
);
300 (void) sigset(SIGALRM
, SIG_DFL
);
301 (void) sigset(SIGCHLD
, SIG_DFL
);
302 (void) sigset(SIGHUP
, SIG_DFL
);
303 (void) sigset(SIGINT
, SIG_DFL
);
304 (void) sigset(SIGTERM
, SIG_DFL
);
305 (void) sigset(SIGUSR1
, SIG_DFL
);
307 # else /* ALTOS_SYSTEM_V */
310 (void) sigemptyset(&sset
);
311 (void) sigaddset(&sset
, SIGALRM
);
312 (void) sigaddset(&sset
, SIGCHLD
);
313 (void) sigaddset(&sset
, SIGHUP
);
314 (void) sigaddset(&sset
, SIGINT
);
315 (void) sigaddset(&sset
, SIGTERM
);
316 (void) sigaddset(&sset
, SIGUSR1
);
317 (void) sigprocmask(block
? SIG_BLOCK
: SIG_UNBLOCK
, &sset
, NULL
);
318 # endif /* ALTOS_SYSTEM_V */
322 ** SM_SIGNAL_NOOP -- A signal no-op function
325 ** sig -- signal received
336 int save_errno
= errno
;
338 FIX_SYSV_SIGNAL(sig
, sm_signal_noop
);
340 return SIGFUNC_RETURN
;