1 /* Extended support for using signal values. 2 Written by Fred Fish. fnf@cygnus.com 3 This file is in the public domain. */ 4 5 #include "config.h" 6 #include "ansidecl.h" 7 #include "libiberty.h" 8 9 /* We need to declare sys_siglist, because even if the system provides 10 it we can't assume that it is declared in <signal.h> (for example, 11 SunOS provides sys_siglist, but it does not declare it in any 12 header file). However, we can't declare sys_siglist portably, 13 because on some systems it is declared with const and on some 14 systems it is declared without const. If we were using autoconf, 15 we could work out the right declaration. Until, then we just 16 ignore any declaration in the system header files, and always 17 declare it ourselves. With luck, this will always work. */ 18 #define sys_siglist no_such_symbol 19 #define sys_nsig sys_nsig__no_such_symbol 20 21 #include <stdio.h> 22 #include <signal.h> 23 24 /* Routines imported from standard C runtime libraries. */ 25 26 #ifdef HAVE_STDLIB_H 27 #include <stdlib.h> 28 #else 29 extern PTR malloc (); 30 #endif 31 32 #ifdef HAVE_STRING_H 33 #include <string.h> 34 #else 35 extern PTR memset (); 36 #endif 37 38 /* Undefine the macro we used to hide the definition of sys_siglist 39 found in the system header files. */ 40 #undef sys_siglist 41 #undef sys_nsig 42 43 #ifndef NULL 44 # define NULL (void *) 0 45 #endif 46 47 #ifndef MAX 48 # define MAX(a,b) ((a) > (b) ? (a) : (b)) 49 #endif 50 51 static void init_signal_tables (void); 52 53 /* Translation table for signal values. 54 55 Note that this table is generally only accessed when it is used at runtime 56 to initialize signal name and message tables that are indexed by signal 57 value. 58 59 Not all of these signals will exist on all systems. This table is the only 60 thing that should have to be updated as new signal numbers are introduced. 61 It's sort of ugly, but at least its portable. */ 62 63 struct signal_info 64 { 65 const int value; /* The numeric value from <signal.h> */ 66 const char *const name; /* The equivalent symbolic value */ 67 #ifndef HAVE_SYS_SIGLIST 68 const char *const msg; /* Short message about this value */ 69 #endif 70 }; 71 72 #ifndef HAVE_SYS_SIGLIST 73 # define ENTRY(value, name, msg) {value, name, msg} 74 #else 75 # define ENTRY(value, name, msg) {value, name} 76 #endif 77 78 static const struct signal_info signal_table[] = 79 { 80 #if defined (SIGHUP) 81 ENTRY(SIGHUP, "SIGHUP", "Hangup"), 82 #endif 83 #if defined (SIGINT) 84 ENTRY(SIGINT, "SIGINT", "Interrupt"), 85 #endif 86 #if defined (SIGQUIT) 87 ENTRY(SIGQUIT, "SIGQUIT", "Quit"), 88 #endif 89 #if defined (SIGILL) 90 ENTRY(SIGILL, "SIGILL", "Illegal instruction"), 91 #endif 92 #if defined (SIGTRAP) 93 ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"), 94 #endif 95 /* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT 96 overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */ 97 #if defined (SIGIOT) 98 ENTRY(SIGIOT, "SIGIOT", "IOT trap"), 99 #endif 100 #if defined (SIGABRT) 101 ENTRY(SIGABRT, "SIGABRT", "Aborted"), 102 #endif 103 #if defined (SIGEMT) 104 ENTRY(SIGEMT, "SIGEMT", "Emulation trap"), 105 #endif 106 #if defined (SIGFPE) 107 ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"), 108 #endif 109 #if defined (SIGKILL) 110 ENTRY(SIGKILL, "SIGKILL", "Killed"), 111 #endif 112 #if defined (SIGBUS) 113 ENTRY(SIGBUS, "SIGBUS", "Bus error"), 114 #endif 115 #if defined (SIGSEGV) 116 ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"), 117 #endif 118 #if defined (SIGSYS) 119 ENTRY(SIGSYS, "SIGSYS", "Bad system call"), 120 #endif 121 #if defined (SIGPIPE) 122 ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"), 123 #endif 124 #if defined (SIGALRM) 125 ENTRY(SIGALRM, "SIGALRM", "Alarm clock"), 126 #endif 127 #if defined (SIGTERM) 128 ENTRY(SIGTERM, "SIGTERM", "Terminated"), 129 #endif 130 #if defined (SIGUSR1) 131 ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"), 132 #endif 133 #if defined (SIGUSR2) 134 ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"), 135 #endif 136 /* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD 137 overrides SIGCLD. SIGCHLD is in POXIX.1 */ 138 #if defined (SIGCLD) 139 ENTRY(SIGCLD, "SIGCLD", "Child status changed"), 140 #endif 141 #if defined (SIGCHLD) 142 ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"), 143 #endif 144 #if defined (SIGPWR) 145 ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"), 146 #endif 147 #if defined (SIGWINCH) 148 ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"), 149 #endif 150 #if defined (SIGURG) 151 ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"), 152 #endif 153 #if defined (SIGIO) 154 /* "I/O pending" has also been suggested, but is misleading since the 155 signal only happens when the process has asked for it, not everytime 156 I/O is pending. */ 157 ENTRY(SIGIO, "SIGIO", "I/O possible"), 158 #endif 159 #if defined (SIGPOLL) 160 ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"), 161 #endif 162 #if defined (SIGSTOP) 163 ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"), 164 #endif 165 #if defined (SIGTSTP) 166 ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"), 167 #endif 168 #if defined (SIGCONT) 169 ENTRY(SIGCONT, "SIGCONT", "Continued"), 170 #endif 171 #if defined (SIGTTIN) 172 ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"), 173 #endif 174 #if defined (SIGTTOU) 175 ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"), 176 #endif 177 #if defined (SIGVTALRM) 178 ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"), 179 #endif 180 #if defined (SIGPROF) 181 ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"), 182 #endif 183 #if defined (SIGXCPU) 184 ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"), 185 #endif 186 #if defined (SIGXFSZ) 187 ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"), 188 #endif 189 #if defined (SIGWIND) 190 ENTRY(SIGWIND, "SIGWIND", "SIGWIND"), 191 #endif 192 #if defined (SIGPHONE) 193 ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"), 194 #endif 195 #if defined (SIGLOST) 196 ENTRY(SIGLOST, "SIGLOST", "Resource lost"), 197 #endif 198 #if defined (SIGWAITING) 199 ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"), 200 #endif 201 #if defined (SIGLWP) 202 ENTRY(SIGLWP, "SIGLWP", "Signal LWP"), 203 #endif 204 #if defined (SIGDANGER) 205 ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"), 206 #endif 207 #if defined (SIGGRANT) 208 ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"), 209 #endif 210 #if defined (SIGRETRACT) 211 ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"), 212 #endif 213 #if defined (SIGMSG) 214 ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"), 215 #endif 216 #if defined (SIGSOUND) 217 ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"), 218 #endif 219 #if defined (SIGSAK) 220 ENTRY(SIGSAK, "SIGSAK", "Secure attention"), 221 #endif 222 ENTRY(0, NULL, NULL) 223 }; 224 225 /* Translation table allocated and initialized at runtime. Indexed by the 226 signal value to find the equivalent symbolic value. */ 227 228 static const char **signal_names; 229 static int num_signal_names = 0; 230 231 /* Translation table allocated and initialized at runtime, if it does not 232 already exist in the host environment. Indexed by the signal value to find 233 the descriptive string. 234 235 We don't export it for use in other modules because even though it has the 236 same name, it differs from other implementations in that it is dynamically 237 initialized rather than statically initialized. */ 238 239 #ifndef HAVE_SYS_SIGLIST 240 241 static int sys_nsig; 242 static const char **sys_siglist; 243 244 #else 245 246 #ifdef NSIG 247 static int sys_nsig = NSIG; 248 #else 249 #ifdef _NSIG 250 static int sys_nsig = _NSIG; 251 #endif 252 #endif 253 extern const char * const sys_siglist[]; 254 255 #endif 256 257 258 /* 259 260 NAME 261 262 init_signal_tables -- initialize the name and message tables 263 264 SYNOPSIS 265 266 static void init_signal_tables (); 267 268 DESCRIPTION 269 270 Using the signal_table, which is initialized at compile time, generate 271 the signal_names and the sys_siglist (if needed) tables, which are 272 indexed at runtime by a specific signal value. 273 274 BUGS 275 276 The initialization of the tables may fail under low memory conditions, 277 in which case we don't do anything particularly useful, but we don't 278 bomb either. Who knows, it might succeed at a later point if we free 279 some memory in the meantime. In any case, the other routines know 280 how to deal with lack of a table after trying to initialize it. This 281 may or may not be considered to be a bug, that we don't specifically 282 warn about this particular failure mode. 283 284 */ 285 286 static void 287 init_signal_tables (void) 288 { 289 const struct signal_info *eip; 290 int nbytes; 291 292 /* If we haven't already scanned the signal_table once to find the maximum 293 signal value, then go find it now. */ 294 295 if (num_signal_names == 0) 296 { 297 for (eip = signal_table; eip -> name != NULL; eip++) 298 { 299 if (eip -> value >= num_signal_names) 300 { 301 num_signal_names = eip -> value + 1; 302 } 303 } 304 } 305 306 /* Now attempt to allocate the signal_names table, zero it out, and then 307 initialize it from the statically initialized signal_table. */ 308 309 if (signal_names == NULL) 310 { 311 nbytes = num_signal_names * sizeof (char *); 312 if ((signal_names = (const char **) malloc (nbytes)) != NULL) 313 { 314 memset (signal_names, 0, nbytes); 315 for (eip = signal_table; eip -> name != NULL; eip++) 316 { 317 signal_names[eip -> value] = eip -> name; 318 } 319 } 320 } 321 322 #ifndef HAVE_SYS_SIGLIST 323 324 /* Now attempt to allocate the sys_siglist table, zero it out, and then 325 initialize it from the statically initialized signal_table. */ 326 327 if (sys_siglist == NULL) 328 { 329 nbytes = num_signal_names * sizeof (char *); 330 if ((sys_siglist = (const char **) malloc (nbytes)) != NULL) 331 { 332 memset (sys_siglist, 0, nbytes); 333 sys_nsig = num_signal_names; 334 for (eip = signal_table; eip -> name != NULL; eip++) 335 { 336 sys_siglist[eip -> value] = eip -> msg; 337 } 338 } 339 } 340 341 #endif 342 343 } 344 345 346 /* 347 348 @deftypefn Extension int signo_max (void) 349 350 Returns the maximum signal value for which a corresponding symbolic 351 name or message is available. Note that in the case where we use the 352 @code{sys_siglist} supplied by the system, it is possible for there to 353 be more symbolic names than messages, or vice versa. In fact, the 354 manual page for @code{psignal(3b)} explicitly warns that one should 355 check the size of the table (@code{NSIG}) before indexing it, since 356 new signal codes may be added to the system before they are added to 357 the table. Thus @code{NSIG} might be smaller than value implied by 358 the largest signo value defined in @code{<signal.h>}. 359 360 We return the maximum value that can be used to obtain a meaningful 361 symbolic name or message. 362 363 @end deftypefn 364 365 */ 366 367 int 368 signo_max (void) 369 { 370 int maxsize; 371 372 if (signal_names == NULL) 373 { 374 init_signal_tables (); 375 } 376 maxsize = MAX (sys_nsig, num_signal_names); 377 return (maxsize - 1); 378 } 379 380 381 /* 382 383 @deftypefn Supplemental {const char *} strsignal (int @var{signo}) 384 385 Maps an signal number to an signal message string, the contents of 386 which are implementation defined. On systems which have the external 387 variable @code{sys_siglist}, these strings will be the same as the 388 ones used by @code{psignal()}. 389 390 If the supplied signal number is within the valid range of indices for 391 the @code{sys_siglist}, but no message is available for the particular 392 signal number, then returns the string @samp{Signal @var{num}}, where 393 @var{num} is the signal number. 394 395 If the supplied signal number is not a valid index into 396 @code{sys_siglist}, returns @code{NULL}. 397 398 The returned string is only guaranteed to be valid only until the next 399 call to @code{strsignal}. 400 401 @end deftypefn 402 403 */ 404 405 #ifndef HAVE_STRSIGNAL 406 407 char * 408 strsignal (int signo) 409 { 410 char *msg; 411 static char buf[32]; 412 413 #ifndef HAVE_SYS_SIGLIST 414 415 if (signal_names == NULL) 416 { 417 init_signal_tables (); 418 } 419 420 #endif 421 422 if ((signo < 0) || (signo >= sys_nsig)) 423 { 424 /* Out of range, just return NULL */ 425 msg = NULL; 426 } 427 else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL)) 428 { 429 /* In range, but no sys_siglist or no entry at this index. */ 430 sprintf (buf, "Signal %d", signo); 431 msg = buf; 432 } 433 else 434 { 435 /* In range, and a valid message. Just return the message. We 436 can safely cast away const, since POSIX says the user must 437 not modify the result. */ 438 msg = (char *) sys_siglist[signo]; 439 } 440 441 return (msg); 442 } 443 444 #endif /* ! HAVE_STRSIGNAL */ 445 446 /* 447 448 @deftypefn Extension {const char*} strsigno (int @var{signo}) 449 450 Given an signal number, returns a pointer to a string containing the 451 symbolic name of that signal number, as found in @code{<signal.h>}. 452 453 If the supplied signal number is within the valid range of indices for 454 symbolic names, but no name is available for the particular signal 455 number, then returns the string @samp{Signal @var{num}}, where 456 @var{num} is the signal number. 457 458 If the supplied signal number is not within the range of valid 459 indices, then returns @code{NULL}. 460 461 The contents of the location pointed to are only guaranteed to be 462 valid until the next call to @code{strsigno}. 463 464 @end deftypefn 465 466 */ 467 468 const char * 469 strsigno (int signo) 470 { 471 const char *name; 472 static char buf[32]; 473 474 if (signal_names == NULL) 475 { 476 init_signal_tables (); 477 } 478 479 if ((signo < 0) || (signo >= num_signal_names)) 480 { 481 /* Out of range, just return NULL */ 482 name = NULL; 483 } 484 else if ((signal_names == NULL) || (signal_names[signo] == NULL)) 485 { 486 /* In range, but no signal_names or no entry at this index. */ 487 sprintf (buf, "Signal %d", signo); 488 name = (const char *) buf; 489 } 490 else 491 { 492 /* In range, and a valid name. Just return the name. */ 493 name = signal_names[signo]; 494 } 495 496 return (name); 497 } 498 499 500 /* 501 502 @deftypefn Extension int strtosigno (const char *@var{name}) 503 504 Given the symbolic name of a signal, map it to a signal number. If no 505 translation is found, returns 0. 506 507 @end deftypefn 508 509 */ 510 511 int 512 strtosigno (const char *name) 513 { 514 int signo = 0; 515 516 if (name != NULL) 517 { 518 if (signal_names == NULL) 519 { 520 init_signal_tables (); 521 } 522 for (signo = 0; signo < num_signal_names; signo++) 523 { 524 if ((signal_names[signo] != NULL) && 525 (strcmp (name, signal_names[signo]) == 0)) 526 { 527 break; 528 } 529 } 530 if (signo == num_signal_names) 531 { 532 signo = 0; 533 } 534 } 535 return (signo); 536 } 537 538 539 /* 540 541 @deftypefn Supplemental void psignal (int @var{signo}, char *@var{message}) 542 543 Print @var{message} to the standard error, followed by a colon, 544 followed by the description of the signal specified by @var{signo}, 545 followed by a newline. 546 547 @end deftypefn 548 549 */ 550 551 #ifndef HAVE_PSIGNAL 552 553 void 554 psignal (int signo, char *message) 555 { 556 if (signal_names == NULL) 557 { 558 init_signal_tables (); 559 } 560 if ((signo <= 0) || (signo >= sys_nsig)) 561 { 562 fprintf (stderr, "%s: unknown signal\n", message); 563 } 564 else 565 { 566 fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]); 567 } 568 } 569 570 #endif /* ! HAVE_PSIGNAL */ 571 572 573 /* A simple little main that does nothing but print all the signal translations 574 if MAIN is defined and this file is compiled and linked. */ 575 576 #ifdef MAIN 577 578 #include <stdio.h> 579 580 int 581 main (void) 582 { 583 int signo; 584 int maxsigno; 585 const char *name; 586 const char *msg; 587 588 maxsigno = signo_max (); 589 printf ("%d entries in names table.\n", num_signal_names); 590 printf ("%d entries in messages table.\n", sys_nsig); 591 printf ("%d is max useful index.\n", maxsigno); 592 593 /* Keep printing values until we get to the end of *both* tables, not 594 *either* table. Note that knowing the maximum useful index does *not* 595 relieve us of the responsibility of testing the return pointer for 596 NULL. */ 597 598 for (signo = 0; signo <= maxsigno; signo++) 599 { 600 name = strsigno (signo); 601 name = (name == NULL) ? "<NULL>" : name; 602 msg = strsignal (signo); 603 msg = (msg == NULL) ? "<NULL>" : msg; 604 printf ("%-4d%-18s%s\n", signo, name, msg); 605 } 606 607 return 0; 608 } 609 610 #endif 611