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