Annotation of GNUtools/libg++/libiberty/strsignal.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.