OSDN Git Service

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