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