kernel - cleanup vfs_cache debugging
[dragonfly.git] / contrib / cvs-1.12 / lib / sighandle.c
blob79344616025079c0e3d029bef0da9b7bbdae53a3
1 /* sighandle.c -- Library routines for manipulating chains of signal handlers
2 Copyright (C) 1992 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details. */
14 /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
15 Brian Berliner <berliner@Sun.COM> added POSIX support */
17 /*************************************************************************
19 * signal.c -- This file contains code that manipulates chains of signal
20 * handlers.
22 * Facilities are provided to register a signal handler for
23 * any specific signal. When a signal is received, all of the
24 * registered signal handlers are invoked in the reverse order
25 * in which they are registered. Note that the signal handlers
26 * must not themselves make calls to the signal handling
27 * facilities.
29 *************************************************************************/
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #include "system.h"
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <signal.h>
40 #ifdef STDC_HEADERS
41 #include <stdlib.h>
42 #else
43 #if __STDC__
44 char *calloc(unsigned nelem, unsigned size);
45 char *malloc(unsigned size);
46 #else
47 char *calloc();
48 char *malloc();
49 #endif /* __STDC__ */
50 #endif /* STDC_HEADERS */
52 /* Define the highest signal number (usually) */
53 #ifndef SIGMAX
54 #define SIGMAX 64
55 #endif
57 /* Define linked list of signal handlers structure */
58 struct SIG_hlist {
59 RETSIGTYPE (*handler)();
60 struct SIG_hlist *next;
64 * Define array of lists of signal handlers. Note that this depends on
65 * the implementation to initialize each element to a null pointer.
68 static struct SIG_hlist **SIG_handlers;
70 /* Define array of default signal vectors */
72 #ifdef POSIX_SIGNALS
73 static struct sigaction *SIG_defaults;
74 #else
75 #ifdef BSD_SIGNALS
76 static struct sigvec *SIG_defaults;
77 #else
78 static RETSIGTYPE (**SIG_defaults) (int);
79 #endif
80 #endif
82 /* Critical section housekeeping */
83 static int SIG_crSectNest = 0; /* Nesting level */
84 #ifdef POSIX_SIGNALS
85 static sigset_t SIG_crSectMask; /* Signal mask */
86 #else
87 static int SIG_crSectMask; /* Signal mask */
88 #endif
91 * Initialize the signal handler arrays
94 static int SIG_init()
96 int i;
97 #ifdef POSIX_SIGNALS
98 sigset_t sigset_test;
99 #endif
101 if (SIG_defaults && SIG_handlers) /* already allocated */
102 return (0);
104 #ifdef POSIX_SIGNALS
105 (void) sigfillset(&sigset_test);
106 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
108 if (i < SIGMAX)
109 i = SIGMAX;
110 i++;
111 if (!SIG_defaults)
112 SIG_defaults = (struct sigaction *)
113 calloc(i, sizeof(struct sigaction));
114 (void) sigemptyset(&SIG_crSectMask);
115 #else
116 i = SIGMAX+1;
117 #ifdef BSD_SIGNALS
118 if (!SIG_defaults)
119 SIG_defaults = (struct sigvec *)
120 calloc(i, sizeof(struct sigvec));
121 #else
122 if (!SIG_defaults)
123 SIG_defaults = ( RETSIGTYPE (**) (int) )
124 calloc( i, sizeof( RETSIGTYPE (**) (int) ) );
125 #endif
126 SIG_crSectMask = 0;
127 #endif
128 if (!SIG_handlers)
129 SIG_handlers = (struct SIG_hlist **)
130 calloc(i, sizeof(struct SIG_hlist *));
131 return (!SIG_defaults || !SIG_handlers);
137 * The following begins a critical section.
139 void SIG_beginCrSect (void)
141 if (SIG_init() == 0)
143 if (SIG_crSectNest == 0)
145 #ifdef POSIX_SIGNALS
146 sigset_t sigset_mask;
148 (void) sigfillset(&sigset_mask);
149 (void) sigprocmask(SIG_SETMASK,
150 &sigset_mask, &SIG_crSectMask);
151 #else
152 #ifdef BSD_SIGNALS
153 SIG_crSectMask = sigblock(~0);
154 #else
155 /* TBD */
156 #endif
157 #endif
159 SIG_crSectNest++;
166 * The following ends a critical section.
168 void SIG_endCrSect (void)
170 if (SIG_init() == 0)
172 SIG_crSectNest--;
173 if (SIG_crSectNest == 0)
175 #ifdef POSIX_SIGNALS
176 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
177 #else
178 #ifdef BSD_SIGNALS
179 (void) sigsetmask(SIG_crSectMask);
180 #else
181 /* TBD */
182 #endif
183 #endif
191 * The following invokes each signal handler in the reverse order in which
192 * they were registered.
194 static RETSIGTYPE SIG_handle (int sig)
196 struct SIG_hlist *this;
198 /* Dispatch signal handlers */
199 /* This crit section stuff is a CVSism - we know that our interrupt
200 * handlers will always end up exiting and we don't want them to be
201 * interrupted themselves.
203 SIG_beginCrSect();
204 this = SIG_handlers[sig];
205 while (this != (struct SIG_hlist *) NULL)
207 (*this->handler)(sig);
208 this = this->next;
210 SIG_endCrSect();
212 return;
216 * The following registers a signal handler. If the handler is already
217 * registered, it is not registered twice, nor is the order in which signal
218 * handlers are invoked changed. If this is the first signal handler
219 * registered for a given signal, the old sigvec structure is saved for
220 * restoration later.
223 int SIG_register(int sig, RETSIGTYPE (*fn)())
225 int val;
226 struct SIG_hlist *this;
227 #ifdef POSIX_SIGNALS
228 struct sigaction act;
229 sigset_t sigset_mask, sigset_omask;
230 #else
231 #ifdef BSD_SIGNALS
232 struct sigvec vec;
233 int mask;
234 #endif
235 #endif
237 /* Initialize */
238 if (SIG_init() != 0)
239 return (-1);
240 val = 0;
242 /* Block this signal while we look at handler chain */
243 #ifdef POSIX_SIGNALS
244 (void) sigemptyset(&sigset_mask);
245 (void) sigaddset(&sigset_mask, sig);
246 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
247 #else
248 #ifdef BSD_SIGNALS
249 mask = sigblock(sigmask(sig));
250 #endif
251 #endif
253 /* See if this handler was already registered */
254 this = SIG_handlers[sig];
255 while (this != (struct SIG_hlist *) NULL)
257 if (this->handler == fn) break;
258 this = this->next;
261 /* Register the new handler only if it is not already registered. */
262 if (this == (struct SIG_hlist *) NULL)
266 * If this is the first handler registered for this signal,
267 * set up the signal handler dispatcher
270 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
272 #ifdef POSIX_SIGNALS
273 act.sa_handler = SIG_handle;
274 (void) sigemptyset(&act.sa_mask);
275 act.sa_flags = 0;
276 val = sigaction(sig, &act, &SIG_defaults[sig]);
277 #else
278 #ifdef BSD_SIGNALS
279 memset (&vec, 0, sizeof (vec));
280 vec.sv_handler = SIG_handle;
281 val = sigvec(sig, &vec, &SIG_defaults[sig]);
282 #else
283 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
284 val = -1;
285 #endif
286 #endif
289 /* If not, register it */
290 if ((val == 0) && (this == (struct SIG_hlist *) NULL))
292 this = (struct SIG_hlist *)
293 malloc(sizeof(struct SIG_hlist));
294 if (this == NULL)
296 val = -1;
298 else
300 this->handler = fn;
301 this->next = SIG_handlers[sig];
302 SIG_handlers[sig] = this;
307 /* Unblock the signal */
308 #ifdef POSIX_SIGNALS
309 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
310 #else
311 #ifdef BSD_SIGNALS
312 (void) sigsetmask(mask);
313 #endif
314 #endif
316 return val;
322 * The following deregisters a signal handler. If the last signal handler for
323 * a given signal is deregistered, the default sigvec information is restored.
326 int SIG_deregister(int sig, RETSIGTYPE (*fn)())
328 int val;
329 struct SIG_hlist *this;
330 struct SIG_hlist *last;
331 #ifdef POSIX_SIGNALS
332 sigset_t sigset_mask, sigset_omask;
333 #else
334 #ifdef BSD_SIGNALS
335 int mask;
336 #endif
337 #endif
339 /* Initialize */
340 if (SIG_init() != 0)
341 return (-1);
342 val = 0;
343 last = (struct SIG_hlist *) NULL;
345 /* Block this signal while we look at handler chain */
346 #ifdef POSIX_SIGNALS
347 (void) sigemptyset(&sigset_mask);
348 (void) sigaddset(&sigset_mask, sig);
349 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
350 #else
351 #ifdef BSD_SIGNALS
352 mask = sigblock(sigmask(sig));
353 #endif
354 #endif
356 /* Search for the signal handler */
357 this = SIG_handlers[sig];
358 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
360 last = this;
361 this = this->next;
364 /* If it was registered, remove it */
365 if (this != (struct SIG_hlist *) NULL)
367 if (last == (struct SIG_hlist *) NULL)
369 SIG_handlers[sig] = this->next;
371 else
373 last->next = this->next;
375 free((char *) this);
378 /* Restore default behavior if there are no registered handlers */
379 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
381 #ifdef POSIX_SIGNALS
382 val = sigaction(sig, &SIG_defaults[sig],
383 (struct sigaction *) NULL);
384 #else
385 #ifdef BSD_SIGNALS
386 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
387 #else
388 if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
389 val = -1;
390 #endif
391 #endif
394 /* Unblock the signal */
395 #ifdef POSIX_SIGNALS
396 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
397 #else
398 #ifdef BSD_SIGNALS
399 (void) sigsetmask(mask);
400 #endif
401 #endif
403 return val;
409 * Return nonzero if currently in a critical section.
410 * Otherwise return zero.
413 int SIG_inCrSect (void)
415 return SIG_crSectNest > 0;