1 /* sighandle.c -- Library routines for manipulating chains of signal handlers 2 Copyright (C) 1992 Free Software Foundation, Inc. 3 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. 8 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. */ 13 14 /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com> 15 Brian Berliner <berliner@Sun.COM> added POSIX support */ 16 17 /************************************************************************* 18 * 19 * signal.c -- This file contains code that manipulates chains of signal 20 * handlers. 21 * 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. 28 * 29 *************************************************************************/ 30 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif 34 #include "system.h" 35 36 #include <sys/types.h> 37 #include <stdio.h> 38 #include <signal.h> 39 40 /* Add prototype support. */ 41 #ifndef PROTO 42 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 43 #define PROTO(ARGS) ARGS 44 #else 45 #define PROTO(ARGS) () 46 #endif 47 #endif 48 49 #ifdef STDC_HEADERS 50 #include <stdlib.h> 51 #else 52 #if __STDC__ 53 char *calloc(unsigned nelem, unsigned size); 54 char *malloc(unsigned size); 55 #else 56 char *calloc(); 57 char *malloc(); 58 #endif /* __STDC__ */ 59 #endif /* STDC_HEADERS */ 60 61 /* Define the highest signal number (usually) */ 62 #ifndef SIGMAX 63 #define SIGMAX 64 64 #endif 65 66 /* Define linked list of signal handlers structure */ 67 struct SIG_hlist { 68 RETSIGTYPE (*handler)(); 69 struct SIG_hlist *next; 70 }; 71 72 /* 73 * Define array of lists of signal handlers. Note that this depends on 74 * the implementation to initialize each element to a null pointer. 75 */ 76 77 static struct SIG_hlist **SIG_handlers; 78 79 /* Define array of default signal vectors */ 80 81 #ifdef POSIX_SIGNALS 82 static struct sigaction *SIG_defaults; 83 #else 84 #ifdef BSD_SIGNALS 85 static struct sigvec *SIG_defaults; 86 #else 87 static RETSIGTYPE (**SIG_defaults) PROTO ((int)); 88 #endif 89 #endif 90 91 /* Critical section housekeeping */ 92 static int SIG_crSectNest = 0; /* Nesting level */ 93 #ifdef POSIX_SIGNALS 94 static sigset_t SIG_crSectMask; /* Signal mask */ 95 #else 96 static int SIG_crSectMask; /* Signal mask */ 97 #endif 98 99 /* 100 * Initialize the signal handler arrays 101 */ 102 103 static int SIG_init() 104 { 105 int i; 106 #ifdef POSIX_SIGNALS 107 sigset_t sigset_test; 108 #endif 109 110 if (SIG_defaults && SIG_handlers) /* already allocated */ 111 return (0); 112 113 #ifdef POSIX_SIGNALS 114 (void) sigfillset(&sigset_test); 115 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++) 116 ; 117 if (i < SIGMAX) 118 i = SIGMAX; 119 i++; 120 if (!SIG_defaults) 121 SIG_defaults = (struct sigaction *) 122 calloc(i, sizeof(struct sigaction)); 123 (void) sigemptyset(&SIG_crSectMask); 124 #else 125 i = SIGMAX+1; 126 #ifdef BSD_SIGNALS 127 if (!SIG_defaults) 128 SIG_defaults = (struct sigvec *) 129 calloc(i, sizeof(struct sigvec)); 130 #else 131 if (!SIG_defaults) 132 SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) ) 133 calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) )); 134 #endif 135 SIG_crSectMask = 0; 136 #endif 137 if (!SIG_handlers) 138 SIG_handlers = (struct SIG_hlist **) 139 calloc(i, sizeof(struct SIG_hlist *)); 140 return (!SIG_defaults || !SIG_handlers); 141 } 142 143 /* 144 * The following invokes each signal handler in the reverse order in which 145 * they were registered. 146 */ 147 static RETSIGTYPE SIG_handle PROTO ((int)); 148 149 static RETSIGTYPE SIG_handle(sig) 150 int sig; 151 { 152 struct SIG_hlist *this; 153 154 /* Dispatch signal handlers */ 155 this = SIG_handlers[sig]; 156 while (this != (struct SIG_hlist *) NULL) 157 { 158 /* handler may free this (and thus clobber this->next) */ 159 struct SIG_hlist *current = this; 160 this = this->next; 161 (*current->handler)(sig); 162 } 163 164 return; 165 } 166 167 /* 168 * The following registers a signal handler. If the handler is already 169 * registered, it is not registered twice, nor is the order in which signal 170 * handlers are invoked changed. If this is the first signal handler 171 * registered for a given signal, the old sigvec structure is saved for 172 * restoration later. 173 */ 174 175 int SIG_register(sig,fn) 176 int sig; 177 RETSIGTYPE (*fn)(); 178 { 179 int val; 180 struct SIG_hlist *this; 181 #ifdef POSIX_SIGNALS 182 struct sigaction act; 183 sigset_t sigset_mask, sigset_omask; 184 #else 185 #ifdef BSD_SIGNALS 186 struct sigvec vec; 187 int mask; 188 #endif 189 #endif 190 191 /* Initialize */ 192 if (SIG_init() != 0) 193 return (-1); 194 val = 0; 195 196 /* Block this signal while we look at handler chain */ 197 #ifdef POSIX_SIGNALS 198 (void) sigemptyset(&sigset_mask); 199 (void) sigaddset(&sigset_mask, sig); 200 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 201 #else 202 #ifdef BSD_SIGNALS 203 mask = sigblock(sigmask(sig)); 204 #endif 205 #endif 206 207 /* See if this handler was already registered */ 208 this = SIG_handlers[sig]; 209 while (this != (struct SIG_hlist *) NULL) 210 { 211 if (this->handler == fn) break; 212 this = this->next; 213 } 214 215 /* Register the new handler only if it is not already registered. */ 216 if (this == (struct SIG_hlist *) NULL) 217 { 218 219 /* 220 * If this is the first handler registered for this signal, 221 * set up the signal handler dispatcher 222 */ 223 224 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 225 { 226 #ifdef POSIX_SIGNALS 227 memset(&act, 0, sizeof act); 228 act.sa_handler = SIG_handle; 229 (void) sigemptyset(&act.sa_mask); 230 act.sa_flags = 0; 231 val = sigaction(sig, &act, &SIG_defaults[sig]); 232 #else 233 #ifdef BSD_SIGNALS 234 memset (&vec, 0, sizeof (vec)); 235 vec.sv_handler = SIG_handle; 236 val = sigvec(sig, &vec, &SIG_defaults[sig]); 237 #else 238 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR) 239 val = -1; 240 #endif 241 #endif 242 } 243 244 /* If not, register it */ 245 if ((val == 0) && (this == (struct SIG_hlist *) NULL)) 246 { 247 this = (struct SIG_hlist *) 248 malloc(sizeof(struct SIG_hlist)); 249 if (this == NULL) 250 { 251 val = -1; 252 } 253 else 254 { 255 this->handler = fn; 256 this->next = SIG_handlers[sig]; 257 SIG_handlers[sig] = this; 258 } 259 } 260 } 261 262 /* Unblock the signal */ 263 #ifdef POSIX_SIGNALS 264 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 265 #else 266 #ifdef BSD_SIGNALS 267 (void) sigsetmask(mask); 268 #endif 269 #endif 270 271 return val; 272 } 273 274 /* 275 * The following deregisters a signal handler. If the last signal handler for 276 * a given signal is deregistered, the default sigvec information is restored. 277 */ 278 279 int SIG_deregister(sig,fn) 280 int sig; 281 RETSIGTYPE (*fn)(); 282 { 283 int val; 284 struct SIG_hlist *this; 285 struct SIG_hlist *last; 286 #ifdef POSIX_SIGNALS 287 sigset_t sigset_mask, sigset_omask; 288 #else 289 #ifdef BSD_SIGNALS 290 int mask; 291 #endif 292 #endif 293 294 /* Initialize */ 295 if (SIG_init() != 0) 296 return (-1); 297 val = 0; 298 last = (struct SIG_hlist *) NULL; 299 300 /* Block this signal while we look at handler chain */ 301 #ifdef POSIX_SIGNALS 302 (void) sigemptyset(&sigset_mask); 303 (void) sigaddset(&sigset_mask, sig); 304 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 305 #else 306 #ifdef BSD_SIGNALS 307 mask = sigblock(sigmask(sig)); 308 #endif 309 #endif 310 311 /* Search for the signal handler */ 312 this = SIG_handlers[sig]; 313 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn)) 314 { 315 last = this; 316 this = this->next; 317 } 318 319 /* If it was registered, remove it */ 320 if (this != (struct SIG_hlist *) NULL) 321 { 322 if (last == (struct SIG_hlist *) NULL) 323 { 324 SIG_handlers[sig] = this->next; 325 } 326 else 327 { 328 last->next = this->next; 329 } 330 free((char *) this); 331 } 332 333 /* Restore default behavior if there are no registered handlers */ 334 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 335 { 336 #ifdef POSIX_SIGNALS 337 val = sigaction(sig, &SIG_defaults[sig], 338 (struct sigaction *) NULL); 339 #else 340 #ifdef BSD_SIGNALS 341 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL); 342 #else 343 if (signal(sig, SIG_defaults[sig]) == SIG_ERR) 344 val = -1; 345 #endif 346 #endif 347 } 348 349 /* Unblock the signal */ 350 #ifdef POSIX_SIGNALS 351 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 352 #else 353 #ifdef BSD_SIGNALS 354 (void) sigsetmask(mask); 355 #endif 356 #endif 357 358 return val; 359 } 360 361 /* 362 * The following begins a critical section. 363 */ 364 365 void SIG_beginCrSect() 366 { 367 if (SIG_init() == 0) 368 { 369 if (SIG_crSectNest == 0) 370 { 371 #ifdef POSIX_SIGNALS 372 sigset_t sigset_mask; 373 374 (void) sigfillset(&sigset_mask); 375 (void) sigprocmask(SIG_SETMASK, 376 &sigset_mask, &SIG_crSectMask); 377 #else 378 #ifdef BSD_SIGNALS 379 SIG_crSectMask = sigblock(~0); 380 #else 381 /* TBD */ 382 #endif 383 #endif 384 } 385 SIG_crSectNest++; 386 } 387 } 388 389 /* 390 * Return nonzero if currently in a critical section. 391 * Otherwise return zero. 392 */ 393 394 int SIG_inCrSect() 395 { 396 return SIG_crSectNest > 0; 397 } 398 399 /* 400 * The following ends a critical section. 401 */ 402 403 void SIG_endCrSect() 404 { 405 if (SIG_init() == 0) 406 { 407 SIG_crSectNest--; 408 if (SIG_crSectNest == 0) 409 { 410 #ifdef POSIX_SIGNALS 411 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL); 412 #else 413 #ifdef BSD_SIGNALS 414 (void) sigsetmask(SIG_crSectMask); 415 #else 416 /* TBD */ 417 #endif 418 #endif 419 } 420 } 421 } 422