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