|
|
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 "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: static char **sys_siglist; ! 211: ! 212: #else ! 213: ! 214: static int sys_nsig = NSIG; ! 215: #ifdef __STDC__ ! 216: extern const char * const sys_siglist[]; ! 217: #else ! 218: extern char *sys_siglist[]; ! 219: #endif ! 220: #endif ! 221: ! 222: ! 223: /* ! 224: ! 225: NAME ! 226: ! 227: init_signal_tables -- initialize the name and message tables ! 228: ! 229: SYNOPSIS ! 230: ! 231: static void init_signal_tables (); ! 232: ! 233: DESCRIPTION ! 234: ! 235: Using the signal_table, which is initialized at compile time, generate ! 236: the signal_names and the sys_siglist (if needed) tables, which are ! 237: indexed at runtime by a specific signal value. ! 238: ! 239: BUGS ! 240: ! 241: The initialization of the tables may fail under low memory conditions, ! 242: in which case we don't do anything particularly useful, but we don't ! 243: bomb either. Who knows, it might succeed at a later point if we free ! 244: some memory in the meantime. In any case, the other routines know ! 245: how to deal with lack of a table after trying to initialize it. This ! 246: may or may not be considered to be a bug, that we don't specifically ! 247: warn about this particular failure mode. ! 248: ! 249: */ ! 250: ! 251: static void ! 252: init_signal_tables () ! 253: { ! 254: struct signal_info *eip; ! 255: int nbytes; ! 256: ! 257: /* If we haven't already scanned the signal_table once to find the maximum ! 258: signal value, then go find it now. */ ! 259: ! 260: if (num_signal_names == 0) ! 261: { ! 262: for (eip = signal_table; eip -> name != NULL; eip++) ! 263: { ! 264: if (eip -> value >= num_signal_names) ! 265: { ! 266: num_signal_names = eip -> value + 1; ! 267: } ! 268: } ! 269: } ! 270: ! 271: /* Now attempt to allocate the signal_names table, zero it out, and then ! 272: initialize it from the statically initialized signal_table. */ ! 273: ! 274: if (signal_names == NULL) ! 275: { ! 276: nbytes = num_signal_names * sizeof (char *); ! 277: if ((signal_names = (char **) malloc (nbytes)) != NULL) ! 278: { ! 279: memset (signal_names, 0, nbytes); ! 280: for (eip = signal_table; eip -> name != NULL; eip++) ! 281: { ! 282: signal_names[eip -> value] = eip -> name; ! 283: } ! 284: } ! 285: } ! 286: ! 287: #ifdef NEED_sys_siglist ! 288: ! 289: /* Now attempt to allocate the sys_siglist table, zero it out, and then ! 290: initialize it from the statically initialized signal_table. */ ! 291: ! 292: if (sys_siglist == NULL) ! 293: { ! 294: nbytes = num_signal_names * sizeof (char *); ! 295: if ((sys_siglist = (char **) malloc (nbytes)) != NULL) ! 296: { ! 297: memset (sys_siglist, 0, nbytes); ! 298: sys_nsig = num_signal_names; ! 299: for (eip = signal_table; eip -> name != NULL; eip++) ! 300: { ! 301: sys_siglist[eip -> value] = eip -> msg; ! 302: } ! 303: } ! 304: } ! 305: ! 306: #endif ! 307: ! 308: } ! 309: ! 310: ! 311: /* ! 312: ! 313: NAME ! 314: ! 315: signo_max -- return the max signo value ! 316: ! 317: SYNOPSIS ! 318: ! 319: int signo_max (); ! 320: ! 321: DESCRIPTION ! 322: ! 323: Returns the maximum signo value for which a corresponding symbolic ! 324: name or message is available. Note that in the case where ! 325: we use the sys_siglist supplied by the system, it is possible for ! 326: there to be more symbolic names than messages, or vice versa. ! 327: In fact, the manual page for psignal(3b) explicitly warns that one ! 328: should check the size of the table (NSIG) before indexing it, ! 329: since new signal codes may be added to the system before they are ! 330: added to the table. Thus NSIG might be smaller than value ! 331: implied by the largest signo value defined in <signal.h>. ! 332: ! 333: We return the maximum value that can be used to obtain a meaningful ! 334: symbolic name or message. ! 335: ! 336: */ ! 337: ! 338: int ! 339: signo_max () ! 340: { ! 341: int maxsize; ! 342: ! 343: if (signal_names == NULL) ! 344: { ! 345: init_signal_tables (); ! 346: } ! 347: maxsize = MAX (sys_nsig, num_signal_names); ! 348: return (maxsize - 1); ! 349: } ! 350: ! 351: ! 352: /* ! 353: ! 354: NAME ! 355: ! 356: strsignal -- map a signal number to a signal message string ! 357: ! 358: SYNOPSIS ! 359: ! 360: char *strsignal (int signo) ! 361: ! 362: DESCRIPTION ! 363: ! 364: Maps an signal number to an signal message string, the contents of ! 365: which are implementation defined. On systems which have the external ! 366: variable sys_siglist, these strings will be the same as the ones used ! 367: by psignal(). ! 368: ! 369: If the supplied signal number is within the valid range of indices ! 370: for the sys_siglist, but no message is available for the particular ! 371: signal number, then returns the string "Signal NUM", where NUM is the ! 372: signal number. ! 373: ! 374: If the supplied signal number is not a valid index into sys_siglist, ! 375: returns NULL. ! 376: ! 377: The returned string is only guaranteed to be valid only until the ! 378: next call to strsignal. ! 379: ! 380: */ ! 381: ! 382: char * ! 383: strsignal (signo) ! 384: int signo; ! 385: { ! 386: char *msg; ! 387: static char buf[32]; ! 388: ! 389: #ifdef NEED_sys_siglist ! 390: ! 391: if (signal_names == NULL) ! 392: { ! 393: init_signal_tables (); ! 394: } ! 395: ! 396: #endif ! 397: ! 398: if ((signo < 0) || (signo >= sys_nsig)) ! 399: { ! 400: /* Out of range, just return NULL */ ! 401: msg = NULL; ! 402: } ! 403: else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL)) ! 404: { ! 405: /* In range, but no sys_siglist or no entry at this index. */ ! 406: sprintf (buf, "Signal %d", signo); ! 407: msg = buf; ! 408: } ! 409: else ! 410: { ! 411: /* In range, and a valid message. Just return the message. */ ! 412: msg = (char*)sys_siglist[signo]; ! 413: } ! 414: ! 415: return (msg); ! 416: } ! 417: ! 418: ! 419: /* ! 420: ! 421: NAME ! 422: ! 423: strsigno -- map an signal number to a symbolic name string ! 424: ! 425: SYNOPSIS ! 426: ! 427: char *strsigno (int signo) ! 428: ! 429: DESCRIPTION ! 430: ! 431: Given an signal number, returns a pointer to a string containing ! 432: the symbolic name of that signal number, as found in <signal.h>. ! 433: ! 434: If the supplied signal number is within the valid range of indices ! 435: for symbolic names, but no name is available for the particular ! 436: signal number, then returns the string "Signal NUM", where NUM is ! 437: the signal number. ! 438: ! 439: If the supplied signal number is not within the range of valid ! 440: indices, then returns NULL. ! 441: ! 442: BUGS ! 443: ! 444: The contents of the location pointed to are only guaranteed to be ! 445: valid until the next call to strsigno. ! 446: ! 447: */ ! 448: ! 449: char * ! 450: strsigno (signo) ! 451: int signo; ! 452: { ! 453: char *name; ! 454: static char buf[32]; ! 455: ! 456: if (signal_names == NULL) ! 457: { ! 458: init_signal_tables (); ! 459: } ! 460: ! 461: if ((signo < 0) || (signo >= num_signal_names)) ! 462: { ! 463: /* Out of range, just return NULL */ ! 464: name = NULL; ! 465: } ! 466: else if ((signal_names == NULL) || (signal_names[signo] == NULL)) ! 467: { ! 468: /* In range, but no signal_names or no entry at this index. */ ! 469: sprintf (buf, "Signal %d", signo); ! 470: name = buf; ! 471: } ! 472: else ! 473: { ! 474: /* In range, and a valid name. Just return the name. */ ! 475: name = signal_names[signo]; ! 476: } ! 477: ! 478: return (name); ! 479: } ! 480: ! 481: ! 482: /* ! 483: ! 484: NAME ! 485: ! 486: strtosigno -- map a symbolic signal name to a numeric value ! 487: ! 488: SYNOPSIS ! 489: ! 490: int strtosigno (char *name) ! 491: ! 492: DESCRIPTION ! 493: ! 494: Given the symbolic name of a signal, map it to a signal number. ! 495: If no translation is found, returns 0. ! 496: ! 497: */ ! 498: ! 499: int ! 500: strtosigno (name) ! 501: char *name; ! 502: { ! 503: int signo = 0; ! 504: ! 505: if (name != NULL) ! 506: { ! 507: if (signal_names == NULL) ! 508: { ! 509: init_signal_tables (); ! 510: } ! 511: for (signo = 0; signo < num_signal_names; signo++) ! 512: { ! 513: if ((signal_names[signo] != NULL) && ! 514: (strcmp (name, signal_names[signo]) == 0)) ! 515: { ! 516: break; ! 517: } ! 518: } ! 519: if (signo == num_signal_names) ! 520: { ! 521: signo = 0; ! 522: } ! 523: } ! 524: return (signo); ! 525: } ! 526: ! 527: ! 528: /* ! 529: ! 530: NAME ! 531: ! 532: psignal -- print message about signal to stderr ! 533: ! 534: SYNOPSIS ! 535: ! 536: void psignal (unsigned signo, char *message); ! 537: ! 538: DESCRIPTION ! 539: ! 540: Print to the standard error the message, followed by a colon, ! 541: followed by the description of the signal specified by signo, ! 542: followed by a newline. ! 543: */ ! 544: ! 545: #ifdef NEED_psignal ! 546: ! 547: void ! 548: psignal (signo, message) ! 549: unsigned signo; ! 550: char *message; ! 551: { ! 552: if (signal_names == NULL) ! 553: { ! 554: init_signal_tables (); ! 555: } ! 556: if ((signo <= 0) || (signo >= sys_nsig)) ! 557: { ! 558: fprintf (stderr, "%s: unknown signal\n", message); ! 559: } ! 560: else ! 561: { ! 562: fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]); ! 563: } ! 564: } ! 565: ! 566: #endif /* NEED_psignal */ ! 567: ! 568: ! 569: /* A simple little main that does nothing but print all the signal translations ! 570: if MAIN is defined and this file is compiled and linked. */ ! 571: ! 572: #ifdef MAIN ! 573: ! 574: main () ! 575: { ! 576: int signo; ! 577: int maxsigno; ! 578: char *name; ! 579: char *msg; ! 580: char *strsigno (); ! 581: char *strsignal (); ! 582: ! 583: maxsigno = signo_max (); ! 584: printf ("%d entries in names table.\n", num_signal_names); ! 585: printf ("%d entries in messages table.\n", sys_nsig); ! 586: printf ("%d is max useful index.\n", maxsigno); ! 587: ! 588: /* Keep printing values until we get to the end of *both* tables, not ! 589: *either* table. Note that knowing the maximum useful index does *not* ! 590: relieve us of the responsibility of testing the return pointer for ! 591: NULL. */ ! 592: ! 593: for (signo = 0; signo <= maxsigno; signo++) ! 594: { ! 595: name = strsigno (signo); ! 596: name = (name == NULL) ? "<NULL>" : name; ! 597: msg = strsignal (signo); ! 598: msg = (msg == NULL) ? "<NULL>" : msg; ! 599: printf ("%-4d%-18s%s\n", signo, name, msg); ! 600: } ! 601: } ! 602: ! 603: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.