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