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). fHowever, 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 const char * 408 strsignal (int signo) 409 { 410 const 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 snprintf (buf, sizeof buf, "Signal %d", signo); 431 msg = (const char *) buf; 432 } 433 else 434 { 435 /* In range, and a valid message. Just return the message. */ 436 msg = (const char *) sys_siglist[signo]; 437 } 438 439 return (msg); 440 } 441 442 #endif /* ! HAVE_STRSIGNAL */ 443 444 /* 445 446 @deftypefn Extension {const char*} strsigno (int @var{signo}) 447 448 Given an signal number, returns a pointer to a string containing the 449 symbolic name of that signal number, as found in @code{<signal.h>}. 450 451 If the supplied signal number is within the valid range of indices for 452 symbolic names, but no name is available for the particular signal 453 number, then returns the string @samp{Signal @var{num}}, where 454 @var{num} is the signal number. 455 456 If the supplied signal number is not within the range of valid 457 indices, then returns @code{NULL}. 458 459 The contents of the location pointed to are only guaranteed to be 460 valid until the next call to @code{strsigno}. 461 462 @end deftypefn 463 464 */ 465 466 const char * 467 strsigno (int signo) 468 { 469 const char *name; 470 static char buf[32]; 471 472 if (signal_names == NULL) 473 { 474 init_signal_tables (); 475 } 476 477 if ((signo < 0) || (signo >= num_signal_names)) 478 { 479 /* Out of range, just return NULL */ 480 name = NULL; 481 } 482 else if ((signal_names == NULL) || (signal_names[signo] == NULL)) 483 { 484 /* In range, but no signal_names or no entry at this index. */ 485 snprintf (buf, sizeof buf, "Signal %d", signo); 486 name = (const char *) buf; 487 } 488 else 489 { 490 /* In range, and a valid name. Just return the name. */ 491 name = signal_names[signo]; 492 } 493 494 return (name); 495 } 496 497 498 /* 499 500 @deftypefn Extension int strtosigno (const char *@var{name}) 501 502 Given the symbolic name of a signal, map it to a signal number. If no 503 translation is found, returns 0. 504 505 @end deftypefn 506 507 */ 508 509 int 510 strtosigno (const char *name) 511 { 512 int signo = 0; 513 514 if (name != NULL) 515 { 516 if (signal_names == NULL) 517 { 518 init_signal_tables (); 519 } 520 for (signo = 0; signo < num_signal_names; signo++) 521 { 522 if ((signal_names[signo] != NULL) && 523 (strcmp (name, signal_names[signo]) == 0)) 524 { 525 break; 526 } 527 } 528 if (signo == num_signal_names) 529 { 530 signo = 0; 531 } 532 } 533 return (signo); 534 } 535 536 537 /* 538 539 @deftypefn Supplemental void psignal (unsigned @var{signo}, char *@var{message}) 540 541 Print @var{message} to the standard error, followed by a colon, 542 followed by the description of the signal specified by @var{signo}, 543 followed by a newline. 544 545 @end deftypefn 546 547 */ 548 549 #ifndef HAVE_PSIGNAL 550 551 void 552 psignal (unsigned signo, char *message) 553 { 554 if (signal_names == NULL) 555 { 556 init_signal_tables (); 557 } 558 if ((signo <= 0) || (signo >= sys_nsig)) 559 { 560 fprintf (stderr, "%s: unknown signal\n", message); 561 } 562 else 563 { 564 fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]); 565 } 566 } 567 568 #endif /* ! HAVE_PSIGNAL */ 569 570 571 /* A simple little main that does nothing but print all the signal translations 572 if MAIN is defined and this file is compiled and linked. */ 573 574 #ifdef MAIN 575 576 #include <stdio.h> 577 578 int 579 main (void) 580 { 581 int signo; 582 int maxsigno; 583 const char *name; 584 const char *msg; 585 586 maxsigno = signo_max (); 587 printf ("%d entries in names table.\n", num_signal_names); 588 printf ("%d entries in messages table.\n", sys_nsig); 589 printf ("%d is max useful index.\n", maxsigno); 590 591 /* Keep printing values until we get to the end of *both* tables, not 592 *either* table. Note that knowing the maximum useful index does *not* 593 relieve us of the responsibility of testing the return pointer for 594 NULL. */ 595 596 for (signo = 0; signo <= maxsigno; signo++) 597 { 598 name = strsigno (signo); 599 name = (name == NULL) ? "<NULL>" : name; 600 msg = strsignal (signo); 601 msg = (msg == NULL) ? "<NULL>" : msg; 602 printf ("%-4d%-18s%s\n", signo, name, msg); 603 } 604 605 return 0; 606 } 607 608 #endif 609