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 (at) hal.com> 17 Brian Berliner <berliner (at) 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 /* 94 * Initialize the signal handler arrays 95 */ 96 97 static int SIG_init() 98 { 99 int i; 100 #ifdef POSIX_SIGNALS 101 sigset_t sigset_test; 102 #endif 103 104 if (SIG_defaults && SIG_handlers) /* already allocated */ 105 return (0); 106 107 #ifdef POSIX_SIGNALS 108 (void) sigfillset(&sigset_test); 109 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++) 110 ; 111 if (i < SIGMAX) 112 i = SIGMAX; 113 i++; 114 if (!SIG_defaults) 115 SIG_defaults = (struct sigaction *) 116 calloc(i, sizeof(struct sigaction)); 117 (void) sigemptyset(&SIG_crSectMask); 118 #else 119 i = SIGMAX+1; 120 #ifdef BSD_SIGNALS 121 if (!SIG_defaults) 122 SIG_defaults = (struct sigvec *) 123 calloc(i, sizeof(struct sigvec)); 124 #else 125 if (!SIG_defaults) 126 SIG_defaults = ( RETSIGTYPE (**) (int) ) 127 calloc( i, sizeof( RETSIGTYPE (**) (int) ) ); 128 #endif 129 SIG_crSectMask = 0; 130 #endif 131 if (!SIG_handlers) 132 SIG_handlers = (struct SIG_hlist **) 133 calloc(i, sizeof(struct SIG_hlist *)); 134 return (!SIG_defaults || !SIG_handlers); 135 } 136 137 138 139 /* 140 * The following begins a critical section. 141 */ 142 void SIG_beginCrSect (void) 143 { 144 if (SIG_init() == 0) 145 { 146 if (SIG_crSectNest == 0) 147 { 148 #ifdef POSIX_SIGNALS 149 sigset_t sigset_mask; 150 151 (void) sigfillset(&sigset_mask); 152 (void) sigprocmask(SIG_SETMASK, 153 &sigset_mask, &SIG_crSectMask); 154 #else 155 #ifdef BSD_SIGNALS 156 SIG_crSectMask = sigblock(~0); 157 #else 158 /* TBD */ 159 #endif 160 #endif 161 } 162 SIG_crSectNest++; 163 } 164 } 165 166 167 168 /* 169 * The following ends a critical section. 170 */ 171 void SIG_endCrSect (void) 172 { 173 if (SIG_init() == 0) 174 { 175 SIG_crSectNest--; 176 if (SIG_crSectNest == 0) 177 { 178 #ifdef POSIX_SIGNALS 179 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL); 180 #else 181 #ifdef BSD_SIGNALS 182 (void) sigsetmask(SIG_crSectMask); 183 #else 184 /* TBD */ 185 #endif 186 #endif 187 } 188 } 189 } 190 191 192 193 /* 194 * The following invokes each signal handler in the reverse order in which 195 * they were registered. 196 */ 197 static RETSIGTYPE SIG_handle (int sig) 198 { 199 struct SIG_hlist *this; 200 201 /* Dispatch signal handlers */ 202 /* This crit section stuff is a CVSism - we know that our interrupt 203 * handlers will always end up exiting and we don't want them to be 204 * interrupted themselves. 205 */ 206 SIG_beginCrSect(); 207 this = SIG_handlers[sig]; 208 while (this != (struct SIG_hlist *) NULL) 209 { 210 (*this->handler)(sig); 211 this = this->next; 212 } 213 SIG_endCrSect(); 214 215 return; 216 } 217 218 /* 220 * The following registers a signal handler. If the handler is already 221 * registered, it is not registered twice, nor is the order in which signal 222 * handlers are invoked changed. If this is the first signal handler 223 * registered for a given signal, the old sigvec structure is saved for 224 * restoration later. 225 */ 226 227 int SIG_register(int sig, RETSIGTYPE (*fn)()) 228 { 229 int val; 230 struct SIG_hlist *this; 231 #ifdef POSIX_SIGNALS 232 struct sigaction act; 233 sigset_t sigset_mask, sigset_omask; 234 #else 235 #ifdef BSD_SIGNALS 236 struct sigvec vec; 237 int mask; 238 #endif 239 #endif 240 241 /* Initialize */ 242 if (SIG_init() != 0) 243 return (-1); 244 val = 0; 245 246 /* Block this signal while we look at handler chain */ 247 #ifdef POSIX_SIGNALS 248 (void) sigemptyset(&sigset_mask); 249 (void) sigaddset(&sigset_mask, sig); 250 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 251 #else 252 #ifdef BSD_SIGNALS 253 mask = sigblock(sigmask(sig)); 254 #endif 255 #endif 256 257 /* See if this handler was already registered */ 258 this = SIG_handlers[sig]; 259 while (this != (struct SIG_hlist *) NULL) 260 { 261 if (this->handler == fn) break; 262 this = this->next; 263 } 264 265 /* Register the new handler only if it is not already registered. */ 266 if (this == (struct SIG_hlist *) NULL) 267 { 268 269 /* 270 * If this is the first handler registered for this signal, 271 * set up the signal handler dispatcher 272 */ 273 274 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 275 { 276 #ifdef POSIX_SIGNALS 277 act.sa_handler = SIG_handle; 278 (void) sigemptyset(&act.sa_mask); 279 act.sa_flags = 0; 280 val = sigaction(sig, &act, &SIG_defaults[sig]); 281 #else 282 #ifdef BSD_SIGNALS 283 memset (&vec, 0, sizeof (vec)); 284 vec.sv_handler = SIG_handle; 285 val = sigvec(sig, &vec, &SIG_defaults[sig]); 286 #else 287 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR) 288 val = -1; 289 #endif 290 #endif 291 } 292 293 /* If not, register it */ 294 if ((val == 0) && (this == (struct SIG_hlist *) NULL)) 295 { 296 this = (struct SIG_hlist *) 297 malloc(sizeof(struct SIG_hlist)); 298 if (this == NULL) 299 { 300 val = -1; 301 } 302 else 303 { 304 this->handler = fn; 305 this->next = SIG_handlers[sig]; 306 SIG_handlers[sig] = this; 307 } 308 } 309 } 310 311 /* Unblock the signal */ 312 #ifdef POSIX_SIGNALS 313 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 314 #else 315 #ifdef BSD_SIGNALS 316 (void) sigsetmask(mask); 317 #endif 318 #endif 319 320 return val; 321 } 322 323 324 325 /* 326 * The following deregisters a signal handler. If the last signal handler for 327 * a given signal is deregistered, the default sigvec information is restored. 328 */ 329 330 int SIG_deregister(int sig, RETSIGTYPE (*fn)()) 331 { 332 int val; 333 struct SIG_hlist *this; 334 struct SIG_hlist *last; 335 #ifdef POSIX_SIGNALS 336 sigset_t sigset_mask, sigset_omask; 337 #else 338 #ifdef BSD_SIGNALS 339 int mask; 340 #endif 341 #endif 342 343 /* Initialize */ 344 if (SIG_init() != 0) 345 return (-1); 346 val = 0; 347 last = (struct SIG_hlist *) NULL; 348 349 /* Block this signal while we look at handler chain */ 350 #ifdef POSIX_SIGNALS 351 (void) sigemptyset(&sigset_mask); 352 (void) sigaddset(&sigset_mask, sig); 353 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 354 #else 355 #ifdef BSD_SIGNALS 356 mask = sigblock(sigmask(sig)); 357 #endif 358 #endif 359 360 /* Search for the signal handler */ 361 this = SIG_handlers[sig]; 362 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn)) 363 { 364 last = this; 365 this = this->next; 366 } 367 368 /* If it was registered, remove it */ 369 if (this != (struct SIG_hlist *) NULL) 370 { 371 if (last == (struct SIG_hlist *) NULL) 372 { 373 SIG_handlers[sig] = this->next; 374 } 375 else 376 { 377 last->next = this->next; 378 } 379 free((char *) this); 380 } 381 382 /* Restore default behavior if there are no registered handlers */ 383 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 384 { 385 #ifdef POSIX_SIGNALS 386 val = sigaction(sig, &SIG_defaults[sig], 387 (struct sigaction *) NULL); 388 #else 389 #ifdef BSD_SIGNALS 390 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL); 391 #else 392 if (signal(sig, SIG_defaults[sig]) == SIG_ERR) 393 val = -1; 394 #endif 395 #endif 396 } 397 398 /* Unblock the signal */ 399 #ifdef POSIX_SIGNALS 400 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 401 #else 402 #ifdef BSD_SIGNALS 403 (void) sigsetmask(mask); 404 #endif 405 #endif 406 407 return val; 408 } 409 410 411 412 /* 413 * Return nonzero if currently in a critical section. 414 * Otherwise return zero. 415 */ 416 417 int SIG_inCrSect (void) 418 { 419 return SIG_crSectNest > 0; 420 } 421