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