Back to index

cell-binutils  2.17cvs20070401
strsignal.c
Go to the documentation of this file.
00001 /* Extended support for using signal values.
00002    Written by Fred Fish.  fnf@cygnus.com
00003    This file is in the public domain.  */
00004 
00005 #include "config.h"
00006 #include "ansidecl.h"
00007 #include "libiberty.h"
00008 
00009 /* We need to declare sys_siglist, because even if the system provides
00010    it we can't assume that it is declared in <signal.h> (for example,
00011    SunOS provides sys_siglist, but it does not declare it in any
00012    header file).  However, we can't declare sys_siglist portably,
00013    because on some systems it is declared with const and on some
00014    systems it is declared without const.  If we were using autoconf,
00015    we could work out the right declaration.  Until, then we just
00016    ignore any declaration in the system header files, and always
00017    declare it ourselves.  With luck, this will always work.  */
00018 #define sys_siglist no_such_symbol
00019 #define sys_nsig sys_nsig__no_such_symbol
00020 
00021 #include <stdio.h>
00022 #include <signal.h>
00023 
00024 /*  Routines imported from standard C runtime libraries. */
00025 
00026 #ifdef HAVE_STDLIB_H
00027 #include <stdlib.h>
00028 #else
00029 extern PTR malloc ();
00030 #endif
00031 
00032 #ifdef HAVE_STRING_H
00033 #include <string.h>
00034 #else
00035 extern PTR memset ();
00036 #endif
00037 
00038 /* Undefine the macro we used to hide the definition of sys_siglist
00039    found in the system header files.  */
00040 #undef sys_siglist
00041 #undef sys_nsig
00042 
00043 #ifndef NULL
00044 #  define NULL (void *) 0
00045 #endif
00046 
00047 #ifndef MAX
00048 #  define MAX(a,b) ((a) > (b) ? (a) : (b))
00049 #endif
00050 
00051 static void init_signal_tables (void);
00052 
00053 /* Translation table for signal values.
00054 
00055    Note that this table is generally only accessed when it is used at runtime
00056    to initialize signal name and message tables that are indexed by signal
00057    value.
00058 
00059    Not all of these signals will exist on all systems.  This table is the only
00060    thing that should have to be updated as new signal numbers are introduced.
00061    It's sort of ugly, but at least its portable. */
00062 
00063 struct signal_info
00064 {
00065   const int value;          /* The numeric value from <signal.h> */
00066   const char *const name;   /* The equivalent symbolic value */
00067 #ifndef HAVE_SYS_SIGLIST
00068   const char *const msg;    /* Short message about this value */
00069 #endif
00070 };
00071 
00072 #ifndef HAVE_SYS_SIGLIST
00073 #   define ENTRY(value, name, msg) {value, name, msg}
00074 #else
00075 #   define ENTRY(value, name, msg) {value, name}
00076 #endif
00077 
00078 static const struct signal_info signal_table[] =
00079 {
00080 #if defined (SIGHUP)
00081   ENTRY(SIGHUP, "SIGHUP", "Hangup"),
00082 #endif
00083 #if defined (SIGINT)
00084   ENTRY(SIGINT, "SIGINT", "Interrupt"),
00085 #endif
00086 #if defined (SIGQUIT)
00087   ENTRY(SIGQUIT, "SIGQUIT", "Quit"),
00088 #endif
00089 #if defined (SIGILL)
00090   ENTRY(SIGILL, "SIGILL", "Illegal instruction"),
00091 #endif
00092 #if defined (SIGTRAP)
00093   ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"),
00094 #endif
00095 /* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
00096    overrides SIGIOT.  SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
00097 #if defined (SIGIOT)
00098   ENTRY(SIGIOT, "SIGIOT", "IOT trap"),
00099 #endif
00100 #if defined (SIGABRT)
00101   ENTRY(SIGABRT, "SIGABRT", "Aborted"),
00102 #endif
00103 #if defined (SIGEMT)
00104   ENTRY(SIGEMT, "SIGEMT", "Emulation trap"),
00105 #endif
00106 #if defined (SIGFPE)
00107   ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"),
00108 #endif
00109 #if defined (SIGKILL)
00110   ENTRY(SIGKILL, "SIGKILL", "Killed"),
00111 #endif
00112 #if defined (SIGBUS)
00113   ENTRY(SIGBUS, "SIGBUS", "Bus error"),
00114 #endif
00115 #if defined (SIGSEGV)
00116   ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"),
00117 #endif
00118 #if defined (SIGSYS)
00119   ENTRY(SIGSYS, "SIGSYS", "Bad system call"),
00120 #endif
00121 #if defined (SIGPIPE)
00122   ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"),
00123 #endif
00124 #if defined (SIGALRM)
00125   ENTRY(SIGALRM, "SIGALRM", "Alarm clock"),
00126 #endif
00127 #if defined (SIGTERM)
00128   ENTRY(SIGTERM, "SIGTERM", "Terminated"),
00129 #endif
00130 #if defined (SIGUSR1)
00131   ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"),
00132 #endif
00133 #if defined (SIGUSR2)
00134   ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"),
00135 #endif
00136 /* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
00137    overrides SIGCLD.  SIGCHLD is in POXIX.1 */
00138 #if defined (SIGCLD)
00139   ENTRY(SIGCLD, "SIGCLD", "Child status changed"),
00140 #endif
00141 #if defined (SIGCHLD)
00142   ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"),
00143 #endif
00144 #if defined (SIGPWR)
00145   ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"),
00146 #endif
00147 #if defined (SIGWINCH)
00148   ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"),
00149 #endif
00150 #if defined (SIGURG)
00151   ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"),
00152 #endif
00153 #if defined (SIGIO)
00154   /* "I/O pending" has also been suggested, but is misleading since the
00155      signal only happens when the process has asked for it, not everytime
00156      I/O is pending. */
00157   ENTRY(SIGIO, "SIGIO", "I/O possible"),
00158 #endif
00159 #if defined (SIGPOLL)
00160   ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"),
00161 #endif
00162 #if defined (SIGSTOP)
00163   ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"),
00164 #endif
00165 #if defined (SIGTSTP)
00166   ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"),
00167 #endif
00168 #if defined (SIGCONT)
00169   ENTRY(SIGCONT, "SIGCONT", "Continued"),
00170 #endif
00171 #if defined (SIGTTIN)
00172   ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"),
00173 #endif
00174 #if defined (SIGTTOU)
00175   ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"),
00176 #endif
00177 #if defined (SIGVTALRM)
00178   ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"),
00179 #endif
00180 #if defined (SIGPROF)
00181   ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"),
00182 #endif
00183 #if defined (SIGXCPU)
00184   ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"),
00185 #endif
00186 #if defined (SIGXFSZ)
00187   ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"),
00188 #endif
00189 #if defined (SIGWIND)
00190   ENTRY(SIGWIND, "SIGWIND", "SIGWIND"),
00191 #endif
00192 #if defined (SIGPHONE)
00193   ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"),
00194 #endif
00195 #if defined (SIGLOST)
00196   ENTRY(SIGLOST, "SIGLOST", "Resource lost"),
00197 #endif
00198 #if defined (SIGWAITING)
00199   ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"),
00200 #endif
00201 #if defined (SIGLWP)
00202   ENTRY(SIGLWP, "SIGLWP", "Signal LWP"),
00203 #endif
00204 #if defined (SIGDANGER)
00205   ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"),
00206 #endif
00207 #if defined (SIGGRANT)
00208   ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"),
00209 #endif
00210 #if defined (SIGRETRACT)
00211   ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"),
00212 #endif
00213 #if defined (SIGMSG)
00214   ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"),
00215 #endif
00216 #if defined (SIGSOUND)
00217   ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"),
00218 #endif
00219 #if defined (SIGSAK)
00220   ENTRY(SIGSAK, "SIGSAK", "Secure attention"),
00221 #endif
00222   ENTRY(0, NULL, NULL)
00223 };
00224 
00225 /* Translation table allocated and initialized at runtime.  Indexed by the
00226    signal value to find the equivalent symbolic value. */
00227 
00228 static const char **signal_names;
00229 static int num_signal_names = 0;
00230 
00231 /* Translation table allocated and initialized at runtime, if it does not
00232    already exist in the host environment.  Indexed by the signal value to find
00233    the descriptive string.
00234 
00235    We don't export it for use in other modules because even though it has the
00236    same name, it differs from other implementations in that it is dynamically
00237    initialized rather than statically initialized. */
00238 
00239 #ifndef HAVE_SYS_SIGLIST
00240 
00241 static int sys_nsig;
00242 static const char **sys_siglist;
00243 
00244 #else
00245 
00246 #ifdef NSIG
00247 static int sys_nsig = NSIG;
00248 #else
00249 #ifdef _NSIG
00250 static int sys_nsig = _NSIG;
00251 #endif
00252 #endif
00253 extern const char * const sys_siglist[];
00254 
00255 #endif
00256 
00257 
00258 /*
00259 
00260 NAME
00261 
00262        init_signal_tables -- initialize the name and message tables
00263 
00264 SYNOPSIS
00265 
00266        static void init_signal_tables ();
00267 
00268 DESCRIPTION
00269 
00270        Using the signal_table, which is initialized at compile time, generate
00271        the signal_names and the sys_siglist (if needed) tables, which are
00272        indexed at runtime by a specific signal value.
00273 
00274 BUGS
00275 
00276        The initialization of the tables may fail under low memory conditions,
00277        in which case we don't do anything particularly useful, but we don't
00278        bomb either.  Who knows, it might succeed at a later point if we free
00279        some memory in the meantime.  In any case, the other routines know
00280        how to deal with lack of a table after trying to initialize it.  This
00281        may or may not be considered to be a bug, that we don't specifically
00282        warn about this particular failure mode.
00283 
00284 */
00285 
00286 static void
00287 init_signal_tables (void)
00288 {
00289   const struct signal_info *eip;
00290   int nbytes;
00291 
00292   /* If we haven't already scanned the signal_table once to find the maximum
00293      signal value, then go find it now. */
00294 
00295   if (num_signal_names == 0)
00296     {
00297       for (eip = signal_table; eip -> name != NULL; eip++)
00298        {
00299          if (eip -> value >= num_signal_names)
00300            {
00301              num_signal_names = eip -> value + 1;
00302            }
00303        }
00304     }
00305 
00306   /* Now attempt to allocate the signal_names table, zero it out, and then
00307      initialize it from the statically initialized signal_table. */
00308 
00309   if (signal_names == NULL)
00310     {
00311       nbytes = num_signal_names * sizeof (char *);
00312       if ((signal_names = (const char **) malloc (nbytes)) != NULL)
00313        {
00314          memset (signal_names, 0, nbytes);
00315          for (eip = signal_table; eip -> name != NULL; eip++)
00316            {
00317              signal_names[eip -> value] = eip -> name;
00318            }
00319        }
00320     }
00321 
00322 #ifndef HAVE_SYS_SIGLIST
00323 
00324   /* Now attempt to allocate the sys_siglist table, zero it out, and then
00325      initialize it from the statically initialized signal_table. */
00326 
00327   if (sys_siglist == NULL)
00328     {
00329       nbytes = num_signal_names * sizeof (char *);
00330       if ((sys_siglist = (const char **) malloc (nbytes)) != NULL)
00331        {
00332          memset (sys_siglist, 0, nbytes);
00333          sys_nsig = num_signal_names;
00334          for (eip = signal_table; eip -> name != NULL; eip++)
00335            {
00336              sys_siglist[eip -> value] = eip -> msg;
00337            }
00338        }
00339     }
00340 
00341 #endif
00342 
00343 }
00344 
00345 
00346 /*
00347 
00348 @deftypefn Extension int signo_max (void)
00349 
00350 Returns the maximum signal value for which a corresponding symbolic
00351 name or message is available.  Note that in the case where we use the
00352 @code{sys_siglist} supplied by the system, it is possible for there to
00353 be more symbolic names than messages, or vice versa.  In fact, the
00354 manual page for @code{psignal(3b)} explicitly warns that one should
00355 check the size of the table (@code{NSIG}) before indexing it, since
00356 new signal codes may be added to the system before they are added to
00357 the table.  Thus @code{NSIG} might be smaller than value implied by
00358 the largest signo value defined in @code{<signal.h>}.
00359 
00360 We return the maximum value that can be used to obtain a meaningful
00361 symbolic name or message.
00362 
00363 @end deftypefn
00364 
00365 */
00366 
00367 int
00368 signo_max (void)
00369 {
00370   int maxsize;
00371 
00372   if (signal_names == NULL)
00373     {
00374       init_signal_tables ();
00375     }
00376   maxsize = MAX (sys_nsig, num_signal_names);
00377   return (maxsize - 1);
00378 }
00379 
00380 
00381 /*
00382 
00383 @deftypefn Supplemental {const char *} strsignal (int @var{signo})
00384 
00385 Maps an signal number to an signal message string, the contents of
00386 which are implementation defined.  On systems which have the external
00387 variable @code{sys_siglist}, these strings will be the same as the
00388 ones used by @code{psignal()}.
00389 
00390 If the supplied signal number is within the valid range of indices for
00391 the @code{sys_siglist}, but no message is available for the particular
00392 signal number, then returns the string @samp{Signal @var{num}}, where
00393 @var{num} is the signal number.
00394 
00395 If the supplied signal number is not a valid index into
00396 @code{sys_siglist}, returns @code{NULL}.
00397 
00398 The returned string is only guaranteed to be valid only until the next
00399 call to @code{strsignal}.
00400 
00401 @end deftypefn
00402 
00403 */
00404 
00405 #ifndef HAVE_STRSIGNAL
00406 
00407 const char *
00408 strsignal (int signo)
00409 {
00410   const char *msg;
00411   static char buf[32];
00412 
00413 #ifndef HAVE_SYS_SIGLIST
00414 
00415   if (signal_names == NULL)
00416     {
00417       init_signal_tables ();
00418     }
00419 
00420 #endif
00421 
00422   if ((signo < 0) || (signo >= sys_nsig))
00423     {
00424       /* Out of range, just return NULL */
00425       msg = NULL;
00426     }
00427   else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
00428     {
00429       /* In range, but no sys_siglist or no entry at this index. */
00430       sprintf (buf, "Signal %d", signo);
00431       msg = (const char *) buf;
00432     }
00433   else
00434     {
00435       /* In range, and a valid message.  Just return the message. */
00436       msg = (const char *) sys_siglist[signo];
00437     }
00438   
00439   return (msg);
00440 }
00441 
00442 #endif /* ! HAVE_STRSIGNAL */
00443 
00444 /*
00445 
00446 @deftypefn Extension {const char*} strsigno (int @var{signo})
00447 
00448 Given an signal number, returns a pointer to a string containing the
00449 symbolic name of that signal number, as found in @code{<signal.h>}.
00450 
00451 If the supplied signal number is within the valid range of indices for
00452 symbolic names, but no name is available for the particular signal
00453 number, then returns the string @samp{Signal @var{num}}, where
00454 @var{num} is the signal number.
00455 
00456 If the supplied signal number is not within the range of valid
00457 indices, then returns @code{NULL}.
00458 
00459 The contents of the location pointed to are only guaranteed to be
00460 valid until the next call to @code{strsigno}.
00461 
00462 @end deftypefn
00463 
00464 */
00465 
00466 const char *
00467 strsigno (int signo)
00468 {
00469   const char *name;
00470   static char buf[32];
00471 
00472   if (signal_names == NULL)
00473     {
00474       init_signal_tables ();
00475     }
00476 
00477   if ((signo < 0) || (signo >= num_signal_names))
00478     {
00479       /* Out of range, just return NULL */
00480       name = NULL;
00481     }
00482   else if ((signal_names == NULL) || (signal_names[signo] == NULL))
00483     {
00484       /* In range, but no signal_names or no entry at this index. */
00485       sprintf (buf, "Signal %d", signo);
00486       name = (const char *) buf;
00487     }
00488   else
00489     {
00490       /* In range, and a valid name.  Just return the name. */
00491       name = signal_names[signo];
00492     }
00493 
00494   return (name);
00495 }
00496 
00497 
00498 /*
00499 
00500 @deftypefn Extension int strtosigno (const char *@var{name})
00501 
00502 Given the symbolic name of a signal, map it to a signal number.  If no
00503 translation is found, returns 0.
00504 
00505 @end deftypefn
00506 
00507 */
00508 
00509 int
00510 strtosigno (const char *name)
00511 {
00512   int signo = 0;
00513 
00514   if (name != NULL)
00515     {
00516       if (signal_names == NULL)
00517        {
00518          init_signal_tables ();
00519        }
00520       for (signo = 0; signo < num_signal_names; signo++)
00521        {
00522          if ((signal_names[signo] != NULL) &&
00523              (strcmp (name, signal_names[signo]) == 0))
00524            {
00525              break;
00526            }
00527        }
00528       if (signo == num_signal_names)
00529        {
00530          signo = 0;
00531        }
00532     }
00533   return (signo);
00534 }
00535 
00536 
00537 /*
00538 
00539 @deftypefn Supplemental void psignal (int @var{signo}, char *@var{message})
00540 
00541 Print @var{message} to the standard error, followed by a colon,
00542 followed by the description of the signal specified by @var{signo},
00543 followed by a newline.
00544 
00545 @end deftypefn
00546 
00547 */
00548 
00549 #ifndef HAVE_PSIGNAL
00550 
00551 void
00552 psignal (int signo, char *message)
00553 {
00554   if (signal_names == NULL)
00555     {
00556       init_signal_tables ();
00557     }
00558   if ((signo <= 0) || (signo >= sys_nsig))
00559     {
00560       fprintf (stderr, "%s: unknown signal\n", message);
00561     }
00562   else
00563     {
00564       fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
00565     }
00566 }
00567 
00568 #endif /* ! HAVE_PSIGNAL */
00569 
00570 
00571 /* A simple little main that does nothing but print all the signal translations
00572    if MAIN is defined and this file is compiled and linked. */
00573 
00574 #ifdef MAIN
00575 
00576 #include <stdio.h>
00577 
00578 int
00579 main (void)
00580 {
00581   int signo;
00582   int maxsigno;
00583   const char *name;
00584   const char *msg;
00585 
00586   maxsigno = signo_max ();
00587   printf ("%d entries in names table.\n", num_signal_names);
00588   printf ("%d entries in messages table.\n", sys_nsig);
00589   printf ("%d is max useful index.\n", maxsigno);
00590 
00591   /* Keep printing values until we get to the end of *both* tables, not
00592      *either* table.  Note that knowing the maximum useful index does *not*
00593      relieve us of the responsibility of testing the return pointer for
00594      NULL. */
00595 
00596   for (signo = 0; signo <= maxsigno; signo++)
00597     {
00598       name = strsigno (signo);
00599       name = (name == NULL) ? "<NULL>" : name;
00600       msg = strsignal (signo);
00601       msg = (msg == NULL) ? "<NULL>" : msg;
00602       printf ("%-4d%-18s%s\n", signo, name, msg);
00603     }
00604 
00605   return 0;
00606 }
00607 
00608 #endif