source: trunk/third/sendmail/libsm/signal.c @ 19204

Revision 19204, 7.0 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
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.
8 */
9
10#include <sm/gen.h>
11SM_RCSID("@(#)$Id: signal.c,v 1.1.1.1 2003-04-08 15:06:05 zacheiss Exp $")
12
13#if SM_CONF_SETITIMER
14# include <sys/time.h>
15#endif /* SM_CONF_SETITIMER */
16#include <errno.h>
17#include <stdlib.h>
18#include <time.h>
19#include <unistd.h>
20#include <sm/clock.h>
21#include <sm/signal.h>
22#include <signal.h>
23#include <sm/string.h>
24
25unsigned int    volatile InCriticalSection; /* >0 if inside critical section */
26int             volatile PendingSignal; /* pending signal to resend */
27
28/*
29**  SM_SIGNAL -- set a signal handler
30**
31**      This is essentially old BSD "signal(3)".
32**
33**      NOTE:   THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
34**              ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
35**              DOING.
36*/
37
38sigfunc_t
39sm_signal(sig, handler)
40        int sig;
41        sigfunc_t handler;
42{
43# if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3))
44        struct sigaction n, o;
45# endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */
46
47        /*
48        **  First, try for modern signal calls
49        **  and restartable syscalls
50        */
51
52# ifdef SA_RESTART
53        (void) memset(&n, '\0', sizeof n);
54#  if USE_SA_SIGACTION
55        n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
56        n.sa_flags = SA_RESTART|SA_SIGINFO;
57#  else /* USE_SA_SIGACTION */
58        n.sa_handler = handler;
59        n.sa_flags = SA_RESTART;
60#  endif /* USE_SA_SIGACTION */
61        if (sigaction(sig, &n, &o) < 0)
62                return SIG_ERR;
63        return o.sa_handler;
64# else /* SA_RESTART */
65
66        /*
67        **  Else check for SYS5SIGNALS or
68        **  BSD4_3 signals
69        */
70
71#  if defined(SYS5SIGNALS) || defined(BSD4_3)
72#   ifdef BSD4_3
73        return signal(sig, handler);
74#   else /* BSD4_3 */
75        return sigset(sig, handler);
76#   endif /* BSD4_3 */
77#  else /* defined(SYS5SIGNALS) || defined(BSD4_3) */
78
79        /*
80        **  Finally, if nothing else is available,
81        **  go for a default
82        */
83
84        (void) memset(&n, '\0', sizeof n);
85        n.sa_handler = handler;
86        if (sigaction(sig, &n, &o) < 0)
87                return SIG_ERR;
88        return o.sa_handler;
89#  endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */
90# endif /* SA_RESTART */
91}
92/*
93**  SM_BLOCKSIGNAL -- hold a signal to prevent delivery
94**
95**      Parameters:
96**              sig -- the signal to block.
97**
98**      Returns:
99**              1 signal was previously blocked
100**              0 signal was not previously blocked
101**              -1 on failure.
102*/
103
104int
105sm_blocksignal(sig)
106        int sig;
107{
108# ifdef BSD4_3
109#  ifndef sigmask
110#   define sigmask(s)   (1 << ((s) - 1))
111#  endif /* ! sigmask */
112        return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
113# else /* BSD4_3 */
114#  ifdef ALTOS_SYSTEM_V
115        sigfunc_t handler;
116
117        handler = sigset(sig, SIG_HOLD);
118        if (handler == SIG_ERR)
119                return -1;
120        else
121                return handler == SIG_HOLD;
122#  else /* ALTOS_SYSTEM_V */
123        sigset_t sset, oset;
124
125        (void) sigemptyset(&sset);
126        (void) sigaddset(&sset, sig);
127        if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
128                return -1;
129        else
130                return sigismember(&oset, sig);
131#  endif /* ALTOS_SYSTEM_V */
132# endif /* BSD4_3 */
133}
134/*
135**  SM_RELEASESIGNAL -- release a held signal
136**
137**      Parameters:
138**              sig -- the signal to release.
139**
140**      Returns:
141**              1 signal was previously blocked
142**              0 signal was not previously blocked
143**              -1 on failure.
144*/
145
146int
147sm_releasesignal(sig)
148        int sig;
149{
150# ifdef BSD4_3
151        return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
152# else /* BSD4_3 */
153#  ifdef ALTOS_SYSTEM_V
154        sigfunc_t handler;
155
156        handler = sigset(sig, SIG_HOLD);
157        if (sigrelse(sig) < 0)
158                return -1;
159        else
160                return handler == SIG_HOLD;
161#  else /* ALTOS_SYSTEM_V */
162        sigset_t sset, oset;
163
164        (void) sigemptyset(&sset);
165        (void) sigaddset(&sset, sig);
166        if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
167                return -1;
168        else
169                return sigismember(&oset, sig);
170#  endif /* ALTOS_SYSTEM_V */
171# endif /* BSD4_3 */
172}
173/*
174**  PEND_SIGNAL -- Add a signal to the pending signal list
175**
176**      Parameters:
177**              sig -- signal to add
178**
179**      Returns:
180**              none.
181**
182**      NOTE:   THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
183**              ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
184**              DOING.
185*/
186
187void
188pend_signal(sig)
189        int sig;
190{
191        int sigbit;
192        int save_errno = errno;
193#if SM_CONF_SETITIMER
194        struct itimerval clr;
195#endif /* SM_CONF_SETITIMER */
196
197        /*
198        **  Don't want to interrupt something critical, hence delay
199        **  the alarm for one second.  Hopefully, by then we
200        **  will be out of the critical section.  If not, then
201        **  we will just delay again.  The events to be run will
202        **  still all be run, maybe just a little bit late.
203        */
204
205        switch (sig)
206        {
207          case SIGHUP:
208                sigbit = PEND_SIGHUP;
209                break;
210
211          case SIGINT:
212                sigbit = PEND_SIGINT;
213                break;
214
215          case SIGTERM:
216                sigbit = PEND_SIGTERM;
217                break;
218
219          case SIGUSR1:
220                sigbit = PEND_SIGUSR1;
221                break;
222
223          case SIGALRM:
224                /* don't have to pend these */
225                sigbit = 0;
226                break;
227
228          default:
229                /* If we get here, we are in trouble */
230                abort();
231
232                /* NOTREACHED */
233                /* shut up stupid compiler warning on HP-UX 11 */
234                sigbit = 0;
235                break;
236        }
237
238        if (sigbit != 0)
239                PendingSignal |= sigbit;
240        (void) sm_signal(SIGALRM, sm_tick);
241#if SM_CONF_SETITIMER
242        clr.it_interval.tv_sec = 0;
243        clr.it_interval.tv_usec = 0;
244        clr.it_value.tv_sec = 1;
245        clr.it_value.tv_usec = 0;
246        (void) setitimer(ITIMER_REAL, &clr, NULL);
247#else /* SM_CONF_SETITIMER */
248        (void) alarm(1);
249#endif /* SM_CONF_SETITIMER */
250        errno = save_errno;
251}
252/*
253**  SM_ALLSIGNALS -- act on all signals
254**
255**      Parameters:
256**              block -- whether to block or release all signals.
257**
258**      Returns:
259**              none.
260*/
261
262void
263sm_allsignals(block)
264        bool block;
265{
266# ifdef BSD4_3
267#  ifndef sigmask
268#   define sigmask(s)   (1 << ((s) - 1))
269#  endif /* ! sigmask */
270        if (block)
271        {
272                int mask = 0;
273
274                mask |= sigmask(SIGALRM);
275                mask |= sigmask(SIGCHLD);
276                mask |= sigmask(SIGHUP);
277                mask |= sigmask(SIGINT);
278                mask |= sigmask(SIGTERM);
279                mask |= sigmask(SIGUSR1);
280
281                (void) sigblock(mask);
282        }
283        else
284                sigsetmask(0);
285# else /* BSD4_3 */
286#  ifdef ALTOS_SYSTEM_V
287        if (block)
288        {
289                (void) sigset(SIGALRM, SIG_HOLD);
290                (void) sigset(SIGCHLD, SIG_HOLD);
291                (void) sigset(SIGHUP, SIG_HOLD);
292                (void) sigset(SIGINT, SIG_HOLD);
293                (void) sigset(SIGTERM, SIG_HOLD);
294                (void) sigset(SIGUSR1, SIG_HOLD);
295        }
296        else
297        {
298                (void) sigset(SIGALRM, SIG_DFL);
299                (void) sigset(SIGCHLD, SIG_DFL);
300                (void) sigset(SIGHUP, SIG_DFL);
301                (void) sigset(SIGINT, SIG_DFL);
302                (void) sigset(SIGTERM, SIG_DFL);
303                (void) sigset(SIGUSR1, SIG_DFL);
304        }
305#  else /* ALTOS_SYSTEM_V */
306        sigset_t sset;
307
308        (void) sigemptyset(&sset);
309        (void) sigaddset(&sset, SIGALRM);
310        (void) sigaddset(&sset, SIGCHLD);
311        (void) sigaddset(&sset, SIGHUP);
312        (void) sigaddset(&sset, SIGINT);
313        (void) sigaddset(&sset, SIGTERM);
314        (void) sigaddset(&sset, SIGUSR1);
315        (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL);
316#  endif /* ALTOS_SYSTEM_V */
317# endif /* BSD4_3 */
318}
319/*
320**  SM_SIGNAL_NOOP -- A signal no-op function
321**
322**      Parameters:
323**              sig -- signal received
324**
325**      Returns:
326**              SIGFUNC_RETURN
327*/
328
329/* ARGSUSED */
330SIGFUNC_DECL
331sm_signal_noop(sig)
332        int sig;
333{
334        int save_errno = errno;
335
336        FIX_SYSV_SIGNAL(sig, sm_signal_noop);
337        errno = save_errno;
338        return SIGFUNC_RETURN;
339}
340
Note: See TracBrowser for help on using the repository browser.