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