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