11e72d8d2Sderaadt /* sighandle.c -- Library routines for manipulating chains of signal handlers
21e72d8d2Sderaadt Copyright (C) 1992 Free Software Foundation, Inc.
31e72d8d2Sderaadt
41e72d8d2Sderaadt This program is free software; you can redistribute it and/or modify
51e72d8d2Sderaadt it under the terms of the GNU General Public License as published by
61e72d8d2Sderaadt the Free Software Foundation; either version 2, or (at your option)
71e72d8d2Sderaadt any later version.
81e72d8d2Sderaadt
91e72d8d2Sderaadt This program is distributed in the hope that it will be useful,
101e72d8d2Sderaadt but WITHOUT ANY WARRANTY; without even the implied warranty of
111e72d8d2Sderaadt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12461cc63eStholo GNU General Public License for more details. */
131e72d8d2Sderaadt
141e72d8d2Sderaadt /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
151e72d8d2Sderaadt Brian Berliner <berliner@Sun.COM> added POSIX support */
161e72d8d2Sderaadt
171e72d8d2Sderaadt /*************************************************************************
181e72d8d2Sderaadt *
191e72d8d2Sderaadt * signal.c -- This file contains code that manipulates chains of signal
201e72d8d2Sderaadt * handlers.
211e72d8d2Sderaadt *
221e72d8d2Sderaadt * Facilities are provided to register a signal handler for
231e72d8d2Sderaadt * any specific signal. When a signal is received, all of the
241e72d8d2Sderaadt * registered signal handlers are invoked in the reverse order
251e72d8d2Sderaadt * in which they are registered. Note that the signal handlers
261e72d8d2Sderaadt * must not themselves make calls to the signal handling
271e72d8d2Sderaadt * facilities.
281e72d8d2Sderaadt *
291e72d8d2Sderaadt *************************************************************************/
301e72d8d2Sderaadt
311e72d8d2Sderaadt #ifdef HAVE_CONFIG_H
321e72d8d2Sderaadt #include "config.h"
331e72d8d2Sderaadt #endif
3413571821Stholo #include "system.h"
351e72d8d2Sderaadt
361e72d8d2Sderaadt #include <sys/types.h>
371e72d8d2Sderaadt #include <stdio.h>
381e72d8d2Sderaadt #include <signal.h>
391e72d8d2Sderaadt
4013571821Stholo /* Add prototype support. */
4113571821Stholo #ifndef PROTO
4213571821Stholo #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
4313571821Stholo #define PROTO(ARGS) ARGS
4413571821Stholo #else
4513571821Stholo #define PROTO(ARGS) ()
4613571821Stholo #endif
4713571821Stholo #endif
4813571821Stholo
491e72d8d2Sderaadt #ifdef STDC_HEADERS
501e72d8d2Sderaadt #include <stdlib.h>
511e72d8d2Sderaadt #else
521e72d8d2Sderaadt #if __STDC__
531e72d8d2Sderaadt char *calloc(unsigned nelem, unsigned size);
541e72d8d2Sderaadt char *malloc(unsigned size);
551e72d8d2Sderaadt #else
561e72d8d2Sderaadt char *calloc();
571e72d8d2Sderaadt char *malloc();
581e72d8d2Sderaadt #endif /* __STDC__ */
591e72d8d2Sderaadt #endif /* STDC_HEADERS */
601e72d8d2Sderaadt
611e72d8d2Sderaadt /* Define the highest signal number (usually) */
621e72d8d2Sderaadt #ifndef SIGMAX
631e72d8d2Sderaadt #define SIGMAX 64
641e72d8d2Sderaadt #endif
651e72d8d2Sderaadt
661e72d8d2Sderaadt /* Define linked list of signal handlers structure */
671e72d8d2Sderaadt struct SIG_hlist {
681e72d8d2Sderaadt RETSIGTYPE (*handler)();
691e72d8d2Sderaadt struct SIG_hlist *next;
701e72d8d2Sderaadt };
711e72d8d2Sderaadt
721e72d8d2Sderaadt /*
731e72d8d2Sderaadt * Define array of lists of signal handlers. Note that this depends on
741e72d8d2Sderaadt * the implementation to initialize each element to a null pointer.
751e72d8d2Sderaadt */
761e72d8d2Sderaadt
771e72d8d2Sderaadt static struct SIG_hlist **SIG_handlers;
781e72d8d2Sderaadt
791e72d8d2Sderaadt /* Define array of default signal vectors */
801e72d8d2Sderaadt
8113571821Stholo #ifdef POSIX_SIGNALS
821e72d8d2Sderaadt static struct sigaction *SIG_defaults;
831e72d8d2Sderaadt #else
841e72d8d2Sderaadt #ifdef BSD_SIGNALS
851e72d8d2Sderaadt static struct sigvec *SIG_defaults;
861e72d8d2Sderaadt #else
8713571821Stholo static RETSIGTYPE (**SIG_defaults) PROTO ((int));
881e72d8d2Sderaadt #endif
891e72d8d2Sderaadt #endif
901e72d8d2Sderaadt
911e72d8d2Sderaadt /* Critical section housekeeping */
921e72d8d2Sderaadt static int SIG_crSectNest = 0; /* Nesting level */
9313571821Stholo #ifdef POSIX_SIGNALS
941e72d8d2Sderaadt static sigset_t SIG_crSectMask; /* Signal mask */
951e72d8d2Sderaadt #else
961e72d8d2Sderaadt static int SIG_crSectMask; /* Signal mask */
971e72d8d2Sderaadt #endif
981e72d8d2Sderaadt
991e72d8d2Sderaadt /*
1001e72d8d2Sderaadt * Initialize the signal handler arrays
1011e72d8d2Sderaadt */
1021e72d8d2Sderaadt
SIG_init()1031e72d8d2Sderaadt static int SIG_init()
1041e72d8d2Sderaadt {
1051e72d8d2Sderaadt int i;
10613571821Stholo #ifdef POSIX_SIGNALS
1071e72d8d2Sderaadt sigset_t sigset_test;
1081e72d8d2Sderaadt #endif
1091e72d8d2Sderaadt
1101e72d8d2Sderaadt if (SIG_defaults && SIG_handlers) /* already allocated */
1111e72d8d2Sderaadt return (0);
1121e72d8d2Sderaadt
11313571821Stholo #ifdef POSIX_SIGNALS
1141e72d8d2Sderaadt (void) sigfillset(&sigset_test);
1151e72d8d2Sderaadt for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
1161e72d8d2Sderaadt ;
1171e72d8d2Sderaadt if (i < SIGMAX)
1181e72d8d2Sderaadt i = SIGMAX;
1191e72d8d2Sderaadt i++;
1201e72d8d2Sderaadt if (!SIG_defaults)
1211e72d8d2Sderaadt SIG_defaults = (struct sigaction *)
1221e72d8d2Sderaadt calloc(i, sizeof(struct sigaction));
1231e72d8d2Sderaadt (void) sigemptyset(&SIG_crSectMask);
1241e72d8d2Sderaadt #else
1251e72d8d2Sderaadt i = SIGMAX+1;
1261e72d8d2Sderaadt #ifdef BSD_SIGNALS
1271e72d8d2Sderaadt if (!SIG_defaults)
1281e72d8d2Sderaadt SIG_defaults = (struct sigvec *)
1291e72d8d2Sderaadt calloc(i, sizeof(struct sigvec));
1301e72d8d2Sderaadt #else
1311e72d8d2Sderaadt if (!SIG_defaults)
13213571821Stholo SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) )
13313571821Stholo calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) ));
1341e72d8d2Sderaadt #endif
1351e72d8d2Sderaadt SIG_crSectMask = 0;
1361e72d8d2Sderaadt #endif
1371e72d8d2Sderaadt if (!SIG_handlers)
1381e72d8d2Sderaadt SIG_handlers = (struct SIG_hlist **)
1391e72d8d2Sderaadt calloc(i, sizeof(struct SIG_hlist *));
1401e72d8d2Sderaadt return (!SIG_defaults || !SIG_handlers);
1411e72d8d2Sderaadt }
1421e72d8d2Sderaadt
1431e72d8d2Sderaadt /*
1441e72d8d2Sderaadt * The following invokes each signal handler in the reverse order in which
1451e72d8d2Sderaadt * they were registered.
1461e72d8d2Sderaadt */
14713571821Stholo static RETSIGTYPE SIG_handle PROTO ((int));
1481e72d8d2Sderaadt
SIG_handle(sig)1491e72d8d2Sderaadt static RETSIGTYPE SIG_handle(sig)
1501e72d8d2Sderaadt int sig;
1511e72d8d2Sderaadt {
1521e72d8d2Sderaadt struct SIG_hlist *this;
1531e72d8d2Sderaadt
1541e72d8d2Sderaadt /* Dispatch signal handlers */
1551e72d8d2Sderaadt this = SIG_handlers[sig];
1561e72d8d2Sderaadt while (this != (struct SIG_hlist *) NULL)
1571e72d8d2Sderaadt {
158*204548aeSotto /* handler may free this (and thus clobber this->next) */
159*204548aeSotto struct SIG_hlist *current = this;
1601e72d8d2Sderaadt this = this->next;
161*204548aeSotto (*current->handler)(sig);
1621e72d8d2Sderaadt }
1631e72d8d2Sderaadt
1641e72d8d2Sderaadt return;
1651e72d8d2Sderaadt }
1661e72d8d2Sderaadt
1671e72d8d2Sderaadt /*
1681e72d8d2Sderaadt * The following registers a signal handler. If the handler is already
1691e72d8d2Sderaadt * registered, it is not registered twice, nor is the order in which signal
1701e72d8d2Sderaadt * handlers are invoked changed. If this is the first signal handler
1711e72d8d2Sderaadt * registered for a given signal, the old sigvec structure is saved for
1721e72d8d2Sderaadt * restoration later.
1731e72d8d2Sderaadt */
1741e72d8d2Sderaadt
SIG_register(sig,fn)1751e72d8d2Sderaadt int SIG_register(sig,fn)
1761e72d8d2Sderaadt int sig;
1771e72d8d2Sderaadt RETSIGTYPE (*fn)();
1781e72d8d2Sderaadt {
1791e72d8d2Sderaadt int val;
1801e72d8d2Sderaadt struct SIG_hlist *this;
18113571821Stholo #ifdef POSIX_SIGNALS
1821e72d8d2Sderaadt struct sigaction act;
1831e72d8d2Sderaadt sigset_t sigset_mask, sigset_omask;
1841e72d8d2Sderaadt #else
1851e72d8d2Sderaadt #ifdef BSD_SIGNALS
1861e72d8d2Sderaadt struct sigvec vec;
1871e72d8d2Sderaadt int mask;
1881e72d8d2Sderaadt #endif
1891e72d8d2Sderaadt #endif
1901e72d8d2Sderaadt
1911e72d8d2Sderaadt /* Initialize */
1921e72d8d2Sderaadt if (SIG_init() != 0)
1931e72d8d2Sderaadt return (-1);
1941e72d8d2Sderaadt val = 0;
1951e72d8d2Sderaadt
1961e72d8d2Sderaadt /* Block this signal while we look at handler chain */
19713571821Stholo #ifdef POSIX_SIGNALS
1981e72d8d2Sderaadt (void) sigemptyset(&sigset_mask);
1991e72d8d2Sderaadt (void) sigaddset(&sigset_mask, sig);
2001e72d8d2Sderaadt (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
2011e72d8d2Sderaadt #else
2021e72d8d2Sderaadt #ifdef BSD_SIGNALS
2031e72d8d2Sderaadt mask = sigblock(sigmask(sig));
2041e72d8d2Sderaadt #endif
2051e72d8d2Sderaadt #endif
2061e72d8d2Sderaadt
2071e72d8d2Sderaadt /* See if this handler was already registered */
2081e72d8d2Sderaadt this = SIG_handlers[sig];
2091e72d8d2Sderaadt while (this != (struct SIG_hlist *) NULL)
2101e72d8d2Sderaadt {
2111e72d8d2Sderaadt if (this->handler == fn) break;
2121e72d8d2Sderaadt this = this->next;
2131e72d8d2Sderaadt }
2141e72d8d2Sderaadt
2151e72d8d2Sderaadt /* Register the new handler only if it is not already registered. */
2161e72d8d2Sderaadt if (this == (struct SIG_hlist *) NULL)
2171e72d8d2Sderaadt {
2181e72d8d2Sderaadt
2191e72d8d2Sderaadt /*
2201e72d8d2Sderaadt * If this is the first handler registered for this signal,
2211e72d8d2Sderaadt * set up the signal handler dispatcher
2221e72d8d2Sderaadt */
2231e72d8d2Sderaadt
2241e72d8d2Sderaadt if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
2251e72d8d2Sderaadt {
22613571821Stholo #ifdef POSIX_SIGNALS
22764fbf2d7Sderaadt memset(&act, 0, sizeof act);
2281e72d8d2Sderaadt act.sa_handler = SIG_handle;
2291e72d8d2Sderaadt (void) sigemptyset(&act.sa_mask);
2301e72d8d2Sderaadt act.sa_flags = 0;
2311e72d8d2Sderaadt val = sigaction(sig, &act, &SIG_defaults[sig]);
2321e72d8d2Sderaadt #else
2331e72d8d2Sderaadt #ifdef BSD_SIGNALS
23413571821Stholo memset (&vec, 0, sizeof (vec));
2351e72d8d2Sderaadt vec.sv_handler = SIG_handle;
2361e72d8d2Sderaadt val = sigvec(sig, &vec, &SIG_defaults[sig]);
2371e72d8d2Sderaadt #else
23813571821Stholo if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
2391e72d8d2Sderaadt val = -1;
2401e72d8d2Sderaadt #endif
2411e72d8d2Sderaadt #endif
2421e72d8d2Sderaadt }
2431e72d8d2Sderaadt
2441e72d8d2Sderaadt /* If not, register it */
2451e72d8d2Sderaadt if ((val == 0) && (this == (struct SIG_hlist *) NULL))
2461e72d8d2Sderaadt {
2471e72d8d2Sderaadt this = (struct SIG_hlist *)
2481e72d8d2Sderaadt malloc(sizeof(struct SIG_hlist));
2491e72d8d2Sderaadt if (this == NULL)
2501e72d8d2Sderaadt {
2511e72d8d2Sderaadt val = -1;
2521e72d8d2Sderaadt }
2531e72d8d2Sderaadt else
2541e72d8d2Sderaadt {
2551e72d8d2Sderaadt this->handler = fn;
2561e72d8d2Sderaadt this->next = SIG_handlers[sig];
2571e72d8d2Sderaadt SIG_handlers[sig] = this;
2581e72d8d2Sderaadt }
2591e72d8d2Sderaadt }
2601e72d8d2Sderaadt }
2611e72d8d2Sderaadt
2621e72d8d2Sderaadt /* Unblock the signal */
26313571821Stholo #ifdef POSIX_SIGNALS
2641e72d8d2Sderaadt (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
2651e72d8d2Sderaadt #else
2661e72d8d2Sderaadt #ifdef BSD_SIGNALS
2671e72d8d2Sderaadt (void) sigsetmask(mask);
2681e72d8d2Sderaadt #endif
2691e72d8d2Sderaadt #endif
2701e72d8d2Sderaadt
2711e72d8d2Sderaadt return val;
2721e72d8d2Sderaadt }
2731e72d8d2Sderaadt
2741e72d8d2Sderaadt /*
2751e72d8d2Sderaadt * The following deregisters a signal handler. If the last signal handler for
2761e72d8d2Sderaadt * a given signal is deregistered, the default sigvec information is restored.
2771e72d8d2Sderaadt */
2781e72d8d2Sderaadt
SIG_deregister(sig,fn)2791e72d8d2Sderaadt int SIG_deregister(sig,fn)
2801e72d8d2Sderaadt int sig;
2811e72d8d2Sderaadt RETSIGTYPE (*fn)();
2821e72d8d2Sderaadt {
2831e72d8d2Sderaadt int val;
2841e72d8d2Sderaadt struct SIG_hlist *this;
2851e72d8d2Sderaadt struct SIG_hlist *last;
28613571821Stholo #ifdef POSIX_SIGNALS
2871e72d8d2Sderaadt sigset_t sigset_mask, sigset_omask;
2881e72d8d2Sderaadt #else
2891e72d8d2Sderaadt #ifdef BSD_SIGNALS
2901e72d8d2Sderaadt int mask;
2911e72d8d2Sderaadt #endif
2921e72d8d2Sderaadt #endif
2931e72d8d2Sderaadt
2941e72d8d2Sderaadt /* Initialize */
2951e72d8d2Sderaadt if (SIG_init() != 0)
2961e72d8d2Sderaadt return (-1);
2971e72d8d2Sderaadt val = 0;
2981e72d8d2Sderaadt last = (struct SIG_hlist *) NULL;
2991e72d8d2Sderaadt
3001e72d8d2Sderaadt /* Block this signal while we look at handler chain */
30113571821Stholo #ifdef POSIX_SIGNALS
3021e72d8d2Sderaadt (void) sigemptyset(&sigset_mask);
3031e72d8d2Sderaadt (void) sigaddset(&sigset_mask, sig);
3041e72d8d2Sderaadt (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
3051e72d8d2Sderaadt #else
3061e72d8d2Sderaadt #ifdef BSD_SIGNALS
3071e72d8d2Sderaadt mask = sigblock(sigmask(sig));
3081e72d8d2Sderaadt #endif
3091e72d8d2Sderaadt #endif
3101e72d8d2Sderaadt
3111e72d8d2Sderaadt /* Search for the signal handler */
3121e72d8d2Sderaadt this = SIG_handlers[sig];
3131e72d8d2Sderaadt while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
3141e72d8d2Sderaadt {
3151e72d8d2Sderaadt last = this;
3161e72d8d2Sderaadt this = this->next;
3171e72d8d2Sderaadt }
3181e72d8d2Sderaadt
3191e72d8d2Sderaadt /* If it was registered, remove it */
3201e72d8d2Sderaadt if (this != (struct SIG_hlist *) NULL)
3211e72d8d2Sderaadt {
3221e72d8d2Sderaadt if (last == (struct SIG_hlist *) NULL)
3231e72d8d2Sderaadt {
3241e72d8d2Sderaadt SIG_handlers[sig] = this->next;
3251e72d8d2Sderaadt }
3261e72d8d2Sderaadt else
3271e72d8d2Sderaadt {
3281e72d8d2Sderaadt last->next = this->next;
3291e72d8d2Sderaadt }
3301e72d8d2Sderaadt free((char *) this);
3311e72d8d2Sderaadt }
3321e72d8d2Sderaadt
3331e72d8d2Sderaadt /* Restore default behavior if there are no registered handlers */
3341e72d8d2Sderaadt if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
3351e72d8d2Sderaadt {
33613571821Stholo #ifdef POSIX_SIGNALS
3371e72d8d2Sderaadt val = sigaction(sig, &SIG_defaults[sig],
3381e72d8d2Sderaadt (struct sigaction *) NULL);
3391e72d8d2Sderaadt #else
3401e72d8d2Sderaadt #ifdef BSD_SIGNALS
3411e72d8d2Sderaadt val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
3421e72d8d2Sderaadt #else
34313571821Stholo if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
3441e72d8d2Sderaadt val = -1;
3451e72d8d2Sderaadt #endif
3461e72d8d2Sderaadt #endif
3471e72d8d2Sderaadt }
3481e72d8d2Sderaadt
3491e72d8d2Sderaadt /* Unblock the signal */
35013571821Stholo #ifdef POSIX_SIGNALS
3511e72d8d2Sderaadt (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
3521e72d8d2Sderaadt #else
3531e72d8d2Sderaadt #ifdef BSD_SIGNALS
3541e72d8d2Sderaadt (void) sigsetmask(mask);
3551e72d8d2Sderaadt #endif
3561e72d8d2Sderaadt #endif
3571e72d8d2Sderaadt
3581e72d8d2Sderaadt return val;
3591e72d8d2Sderaadt }
3601e72d8d2Sderaadt
3611e72d8d2Sderaadt /*
3621e72d8d2Sderaadt * The following begins a critical section.
3631e72d8d2Sderaadt */
3641e72d8d2Sderaadt
SIG_beginCrSect()3651e72d8d2Sderaadt void SIG_beginCrSect()
3661e72d8d2Sderaadt {
3671e72d8d2Sderaadt if (SIG_init() == 0)
3681e72d8d2Sderaadt {
3691e72d8d2Sderaadt if (SIG_crSectNest == 0)
3701e72d8d2Sderaadt {
37113571821Stholo #ifdef POSIX_SIGNALS
3721e72d8d2Sderaadt sigset_t sigset_mask;
3731e72d8d2Sderaadt
3741e72d8d2Sderaadt (void) sigfillset(&sigset_mask);
3751e72d8d2Sderaadt (void) sigprocmask(SIG_SETMASK,
3761e72d8d2Sderaadt &sigset_mask, &SIG_crSectMask);
3771e72d8d2Sderaadt #else
3781e72d8d2Sderaadt #ifdef BSD_SIGNALS
3791e72d8d2Sderaadt SIG_crSectMask = sigblock(~0);
3801e72d8d2Sderaadt #else
3811e72d8d2Sderaadt /* TBD */
3821e72d8d2Sderaadt #endif
3831e72d8d2Sderaadt #endif
3841e72d8d2Sderaadt }
3851e72d8d2Sderaadt SIG_crSectNest++;
3861e72d8d2Sderaadt }
3871e72d8d2Sderaadt }
3881e72d8d2Sderaadt
3891e72d8d2Sderaadt /*
390bde78045Stholo * Return nonzero if currently in a critical section.
391bde78045Stholo * Otherwise return zero.
392bde78045Stholo */
393bde78045Stholo
SIG_inCrSect()394bde78045Stholo int SIG_inCrSect()
395bde78045Stholo {
396bde78045Stholo return SIG_crSectNest > 0;
397bde78045Stholo }
398bde78045Stholo
399bde78045Stholo /*
4001e72d8d2Sderaadt * The following ends a critical section.
4011e72d8d2Sderaadt */
4021e72d8d2Sderaadt
SIG_endCrSect()4031e72d8d2Sderaadt void SIG_endCrSect()
4041e72d8d2Sderaadt {
4051e72d8d2Sderaadt if (SIG_init() == 0)
4061e72d8d2Sderaadt {
4071e72d8d2Sderaadt SIG_crSectNest--;
4081e72d8d2Sderaadt if (SIG_crSectNest == 0)
4091e72d8d2Sderaadt {
41013571821Stholo #ifdef POSIX_SIGNALS
4111e72d8d2Sderaadt (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
4121e72d8d2Sderaadt #else
4131e72d8d2Sderaadt #ifdef BSD_SIGNALS
4141e72d8d2Sderaadt (void) sigsetmask(SIG_crSectMask);
4151e72d8d2Sderaadt #else
4161e72d8d2Sderaadt /* TBD */
4171e72d8d2Sderaadt #endif
4181e72d8d2Sderaadt #endif
4191e72d8d2Sderaadt }
4201e72d8d2Sderaadt }
4211e72d8d2Sderaadt }
422