1440a403fSchristos /* Extended support for using signal values.
2440a403fSchristos    Written by Fred Fish.  fnf@cygnus.com
3440a403fSchristos    This file is in the public domain.  */
4440a403fSchristos 
5440a403fSchristos #include "config.h"
6440a403fSchristos #include "ansidecl.h"
7440a403fSchristos #include "libiberty.h"
8440a403fSchristos 
9440a403fSchristos /* We need to declare sys_siglist, because even if the system provides
10440a403fSchristos    it we can't assume that it is declared in <signal.h> (for example,
11440a403fSchristos    SunOS provides sys_siglist, but it does not declare it in any
12440a403fSchristos    header file).  However, we can't declare sys_siglist portably,
13440a403fSchristos    because on some systems it is declared with const and on some
14440a403fSchristos    systems it is declared without const.  If we were using autoconf,
15440a403fSchristos    we could work out the right declaration.  Until, then we just
16440a403fSchristos    ignore any declaration in the system header files, and always
17440a403fSchristos    declare it ourselves.  With luck, this will always work.  */
18440a403fSchristos #define sys_siglist no_such_symbol
19440a403fSchristos #define sys_nsig sys_nsig__no_such_symbol
20440a403fSchristos 
21440a403fSchristos #include <stdio.h>
22440a403fSchristos #include <signal.h>
23440a403fSchristos 
24440a403fSchristos /*  Routines imported from standard C runtime libraries. */
25440a403fSchristos 
26440a403fSchristos #ifdef HAVE_STDLIB_H
27440a403fSchristos #include <stdlib.h>
28440a403fSchristos #else
29440a403fSchristos extern PTR malloc ();
30440a403fSchristos #endif
31440a403fSchristos 
32440a403fSchristos #ifdef HAVE_STRING_H
33440a403fSchristos #include <string.h>
34440a403fSchristos #else
35440a403fSchristos extern PTR memset ();
36440a403fSchristos #endif
37440a403fSchristos 
38440a403fSchristos /* Undefine the macro we used to hide the definition of sys_siglist
39440a403fSchristos    found in the system header files.  */
40440a403fSchristos #undef sys_siglist
41440a403fSchristos #undef sys_nsig
42440a403fSchristos 
43440a403fSchristos #ifndef NULL
44440a403fSchristos #  define NULL (void *) 0
45440a403fSchristos #endif
46440a403fSchristos 
47440a403fSchristos #ifndef MAX
48440a403fSchristos #  define MAX(a,b) ((a) > (b) ? (a) : (b))
49440a403fSchristos #endif
50440a403fSchristos 
51440a403fSchristos static void init_signal_tables (void);
52440a403fSchristos 
53440a403fSchristos /* Translation table for signal values.
54440a403fSchristos 
55440a403fSchristos    Note that this table is generally only accessed when it is used at runtime
56440a403fSchristos    to initialize signal name and message tables that are indexed by signal
57440a403fSchristos    value.
58440a403fSchristos 
59440a403fSchristos    Not all of these signals will exist on all systems.  This table is the only
60440a403fSchristos    thing that should have to be updated as new signal numbers are introduced.
61440a403fSchristos    It's sort of ugly, but at least its portable. */
62440a403fSchristos 
63440a403fSchristos struct signal_info
64440a403fSchristos {
65440a403fSchristos   const int value;		/* The numeric value from <signal.h> */
66440a403fSchristos   const char *const name;	/* The equivalent symbolic value */
67440a403fSchristos #ifndef HAVE_SYS_SIGLIST
68440a403fSchristos   const char *const msg;	/* Short message about this value */
69440a403fSchristos #endif
70440a403fSchristos };
71440a403fSchristos 
72440a403fSchristos #ifndef HAVE_SYS_SIGLIST
73440a403fSchristos #   define ENTRY(value, name, msg)	{value, name, msg}
74440a403fSchristos #else
75440a403fSchristos #   define ENTRY(value, name, msg)	{value, name}
76440a403fSchristos #endif
77440a403fSchristos 
78440a403fSchristos static const struct signal_info signal_table[] =
79440a403fSchristos {
80440a403fSchristos #if defined (SIGHUP)
81440a403fSchristos   ENTRY(SIGHUP, "SIGHUP", "Hangup"),
82440a403fSchristos #endif
83440a403fSchristos #if defined (SIGINT)
84440a403fSchristos   ENTRY(SIGINT, "SIGINT", "Interrupt"),
85440a403fSchristos #endif
86440a403fSchristos #if defined (SIGQUIT)
87440a403fSchristos   ENTRY(SIGQUIT, "SIGQUIT", "Quit"),
88440a403fSchristos #endif
89440a403fSchristos #if defined (SIGILL)
90440a403fSchristos   ENTRY(SIGILL, "SIGILL", "Illegal instruction"),
91440a403fSchristos #endif
92440a403fSchristos #if defined (SIGTRAP)
93440a403fSchristos   ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"),
94440a403fSchristos #endif
95440a403fSchristos /* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
96440a403fSchristos    overrides SIGIOT.  SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
97440a403fSchristos #if defined (SIGIOT)
98440a403fSchristos   ENTRY(SIGIOT, "SIGIOT", "IOT trap"),
99440a403fSchristos #endif
100440a403fSchristos #if defined (SIGABRT)
101440a403fSchristos   ENTRY(SIGABRT, "SIGABRT", "Aborted"),
102440a403fSchristos #endif
103440a403fSchristos #if defined (SIGEMT)
104440a403fSchristos   ENTRY(SIGEMT, "SIGEMT", "Emulation trap"),
105440a403fSchristos #endif
106440a403fSchristos #if defined (SIGFPE)
107440a403fSchristos   ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"),
108440a403fSchristos #endif
109440a403fSchristos #if defined (SIGKILL)
110440a403fSchristos   ENTRY(SIGKILL, "SIGKILL", "Killed"),
111440a403fSchristos #endif
112440a403fSchristos #if defined (SIGBUS)
113440a403fSchristos   ENTRY(SIGBUS, "SIGBUS", "Bus error"),
114440a403fSchristos #endif
115440a403fSchristos #if defined (SIGSEGV)
116440a403fSchristos   ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"),
117440a403fSchristos #endif
118440a403fSchristos #if defined (SIGSYS)
119440a403fSchristos   ENTRY(SIGSYS, "SIGSYS", "Bad system call"),
120440a403fSchristos #endif
121440a403fSchristos #if defined (SIGPIPE)
122440a403fSchristos   ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"),
123440a403fSchristos #endif
124440a403fSchristos #if defined (SIGALRM)
125440a403fSchristos   ENTRY(SIGALRM, "SIGALRM", "Alarm clock"),
126440a403fSchristos #endif
127440a403fSchristos #if defined (SIGTERM)
128440a403fSchristos   ENTRY(SIGTERM, "SIGTERM", "Terminated"),
129440a403fSchristos #endif
130440a403fSchristos #if defined (SIGUSR1)
131440a403fSchristos   ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"),
132440a403fSchristos #endif
133440a403fSchristos #if defined (SIGUSR2)
134440a403fSchristos   ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"),
135440a403fSchristos #endif
136440a403fSchristos /* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
137440a403fSchristos    overrides SIGCLD.  SIGCHLD is in POXIX.1 */
138440a403fSchristos #if defined (SIGCLD)
139440a403fSchristos   ENTRY(SIGCLD, "SIGCLD", "Child status changed"),
140440a403fSchristos #endif
141440a403fSchristos #if defined (SIGCHLD)
142440a403fSchristos   ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"),
143440a403fSchristos #endif
144440a403fSchristos #if defined (SIGPWR)
145440a403fSchristos   ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"),
146440a403fSchristos #endif
147440a403fSchristos #if defined (SIGWINCH)
148440a403fSchristos   ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"),
149440a403fSchristos #endif
150440a403fSchristos #if defined (SIGURG)
151440a403fSchristos   ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"),
152440a403fSchristos #endif
153440a403fSchristos #if defined (SIGIO)
154440a403fSchristos   /* "I/O pending" has also been suggested, but is misleading since the
155440a403fSchristos      signal only happens when the process has asked for it, not everytime
156440a403fSchristos      I/O is pending. */
157440a403fSchristos   ENTRY(SIGIO, "SIGIO", "I/O possible"),
158440a403fSchristos #endif
159440a403fSchristos #if defined (SIGPOLL)
160440a403fSchristos   ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"),
161440a403fSchristos #endif
162440a403fSchristos #if defined (SIGSTOP)
163440a403fSchristos   ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"),
164440a403fSchristos #endif
165440a403fSchristos #if defined (SIGTSTP)
166440a403fSchristos   ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"),
167440a403fSchristos #endif
168440a403fSchristos #if defined (SIGCONT)
169440a403fSchristos   ENTRY(SIGCONT, "SIGCONT", "Continued"),
170440a403fSchristos #endif
171440a403fSchristos #if defined (SIGTTIN)
172440a403fSchristos   ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"),
173440a403fSchristos #endif
174440a403fSchristos #if defined (SIGTTOU)
175440a403fSchristos   ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"),
176440a403fSchristos #endif
177440a403fSchristos #if defined (SIGVTALRM)
178440a403fSchristos   ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"),
179440a403fSchristos #endif
180440a403fSchristos #if defined (SIGPROF)
181440a403fSchristos   ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"),
182440a403fSchristos #endif
183440a403fSchristos #if defined (SIGXCPU)
184440a403fSchristos   ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"),
185440a403fSchristos #endif
186440a403fSchristos #if defined (SIGXFSZ)
187440a403fSchristos   ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"),
188440a403fSchristos #endif
189440a403fSchristos #if defined (SIGWIND)
190440a403fSchristos   ENTRY(SIGWIND, "SIGWIND", "SIGWIND"),
191440a403fSchristos #endif
192440a403fSchristos #if defined (SIGPHONE)
193440a403fSchristos   ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"),
194440a403fSchristos #endif
195440a403fSchristos #if defined (SIGLOST)
196440a403fSchristos   ENTRY(SIGLOST, "SIGLOST", "Resource lost"),
197440a403fSchristos #endif
198440a403fSchristos #if defined (SIGWAITING)
199440a403fSchristos   ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"),
200440a403fSchristos #endif
201440a403fSchristos #if defined (SIGLWP)
202440a403fSchristos   ENTRY(SIGLWP, "SIGLWP", "Signal LWP"),
203440a403fSchristos #endif
204440a403fSchristos #if defined (SIGDANGER)
205440a403fSchristos   ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"),
206440a403fSchristos #endif
207440a403fSchristos #if defined (SIGGRANT)
208440a403fSchristos   ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"),
209440a403fSchristos #endif
210440a403fSchristos #if defined (SIGRETRACT)
211440a403fSchristos   ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"),
212440a403fSchristos #endif
213440a403fSchristos #if defined (SIGMSG)
214440a403fSchristos   ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"),
215440a403fSchristos #endif
216440a403fSchristos #if defined (SIGSOUND)
217440a403fSchristos   ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"),
218440a403fSchristos #endif
219440a403fSchristos #if defined (SIGSAK)
220440a403fSchristos   ENTRY(SIGSAK, "SIGSAK", "Secure attention"),
221440a403fSchristos #endif
222440a403fSchristos   ENTRY(0, NULL, NULL)
223440a403fSchristos };
224440a403fSchristos 
225440a403fSchristos /* Translation table allocated and initialized at runtime.  Indexed by the
226440a403fSchristos    signal value to find the equivalent symbolic value. */
227440a403fSchristos 
228440a403fSchristos static const char **signal_names;
229440a403fSchristos static int num_signal_names = 0;
230440a403fSchristos 
231440a403fSchristos /* Translation table allocated and initialized at runtime, if it does not
232440a403fSchristos    already exist in the host environment.  Indexed by the signal value to find
233440a403fSchristos    the descriptive string.
234440a403fSchristos 
235440a403fSchristos    We don't export it for use in other modules because even though it has the
236440a403fSchristos    same name, it differs from other implementations in that it is dynamically
237440a403fSchristos    initialized rather than statically initialized. */
238440a403fSchristos 
239440a403fSchristos #ifndef HAVE_SYS_SIGLIST
240440a403fSchristos 
241440a403fSchristos static int sys_nsig;
242440a403fSchristos static const char **sys_siglist;
243440a403fSchristos 
244440a403fSchristos #else
245440a403fSchristos 
246440a403fSchristos #ifdef NSIG
247440a403fSchristos static int sys_nsig = NSIG;
248440a403fSchristos #else
249440a403fSchristos #ifdef _NSIG
250440a403fSchristos static int sys_nsig = _NSIG;
251440a403fSchristos #endif
252440a403fSchristos #endif
253440a403fSchristos extern const char * const sys_siglist[];
254440a403fSchristos 
255440a403fSchristos #endif
256440a403fSchristos 
257440a403fSchristos 
258440a403fSchristos /*
259440a403fSchristos 
260440a403fSchristos NAME
261440a403fSchristos 
262440a403fSchristos 	init_signal_tables -- initialize the name and message tables
263440a403fSchristos 
264440a403fSchristos SYNOPSIS
265440a403fSchristos 
266440a403fSchristos 	static void init_signal_tables ();
267440a403fSchristos 
268440a403fSchristos DESCRIPTION
269440a403fSchristos 
270440a403fSchristos 	Using the signal_table, which is initialized at compile time, generate
271440a403fSchristos 	the signal_names and the sys_siglist (if needed) tables, which are
272440a403fSchristos 	indexed at runtime by a specific signal value.
273440a403fSchristos 
274440a403fSchristos BUGS
275440a403fSchristos 
276440a403fSchristos 	The initialization of the tables may fail under low memory conditions,
277440a403fSchristos 	in which case we don't do anything particularly useful, but we don't
278440a403fSchristos 	bomb either.  Who knows, it might succeed at a later point if we free
279440a403fSchristos 	some memory in the meantime.  In any case, the other routines know
280440a403fSchristos 	how to deal with lack of a table after trying to initialize it.  This
281440a403fSchristos 	may or may not be considered to be a bug, that we don't specifically
282440a403fSchristos 	warn about this particular failure mode.
283440a403fSchristos 
284440a403fSchristos */
285440a403fSchristos 
286440a403fSchristos static void
init_signal_tables(void)287440a403fSchristos init_signal_tables (void)
288440a403fSchristos {
289440a403fSchristos   const struct signal_info *eip;
290440a403fSchristos   int nbytes;
291440a403fSchristos 
292440a403fSchristos   /* If we haven't already scanned the signal_table once to find the maximum
293440a403fSchristos      signal value, then go find it now. */
294440a403fSchristos 
295440a403fSchristos   if (num_signal_names == 0)
296440a403fSchristos     {
297440a403fSchristos       for (eip = signal_table; eip -> name != NULL; eip++)
298440a403fSchristos 	{
299440a403fSchristos 	  if (eip -> value >= num_signal_names)
300440a403fSchristos 	    {
301440a403fSchristos 	      num_signal_names = eip -> value + 1;
302440a403fSchristos 	    }
303440a403fSchristos 	}
304440a403fSchristos     }
305440a403fSchristos 
306440a403fSchristos   /* Now attempt to allocate the signal_names table, zero it out, and then
307440a403fSchristos      initialize it from the statically initialized signal_table. */
308440a403fSchristos 
309440a403fSchristos   if (signal_names == NULL)
310440a403fSchristos     {
311440a403fSchristos       nbytes = num_signal_names * sizeof (char *);
312440a403fSchristos       if ((signal_names = (const char **) malloc (nbytes)) != NULL)
313440a403fSchristos 	{
314440a403fSchristos 	  memset (signal_names, 0, nbytes);
315440a403fSchristos 	  for (eip = signal_table; eip -> name != NULL; eip++)
316440a403fSchristos 	    {
317440a403fSchristos 	      signal_names[eip -> value] = eip -> name;
318440a403fSchristos 	    }
319440a403fSchristos 	}
320440a403fSchristos     }
321440a403fSchristos 
322440a403fSchristos #ifndef HAVE_SYS_SIGLIST
323440a403fSchristos 
324440a403fSchristos   /* Now attempt to allocate the sys_siglist table, zero it out, and then
325440a403fSchristos      initialize it from the statically initialized signal_table. */
326440a403fSchristos 
327440a403fSchristos   if (sys_siglist == NULL)
328440a403fSchristos     {
329440a403fSchristos       nbytes = num_signal_names * sizeof (char *);
330440a403fSchristos       if ((sys_siglist = (const char **) malloc (nbytes)) != NULL)
331440a403fSchristos 	{
332440a403fSchristos 	  memset (sys_siglist, 0, nbytes);
333440a403fSchristos 	  sys_nsig = num_signal_names;
334440a403fSchristos 	  for (eip = signal_table; eip -> name != NULL; eip++)
335440a403fSchristos 	    {
336440a403fSchristos 	      sys_siglist[eip -> value] = eip -> msg;
337440a403fSchristos 	    }
338440a403fSchristos 	}
339440a403fSchristos     }
340440a403fSchristos 
341440a403fSchristos #endif
342440a403fSchristos 
343440a403fSchristos }
344440a403fSchristos 
345440a403fSchristos 
346440a403fSchristos /*
347440a403fSchristos 
348440a403fSchristos @deftypefn Extension int signo_max (void)
349440a403fSchristos 
350440a403fSchristos Returns the maximum signal value for which a corresponding symbolic
351440a403fSchristos name or message is available.  Note that in the case where we use the
352440a403fSchristos @code{sys_siglist} supplied by the system, it is possible for there to
353440a403fSchristos be more symbolic names than messages, or vice versa.  In fact, the
354440a403fSchristos manual page for @code{psignal(3b)} explicitly warns that one should
355440a403fSchristos check the size of the table (@code{NSIG}) before indexing it, since
356440a403fSchristos new signal codes may be added to the system before they are added to
357440a403fSchristos the table.  Thus @code{NSIG} might be smaller than value implied by
358440a403fSchristos the largest signo value defined in @code{<signal.h>}.
359440a403fSchristos 
360440a403fSchristos We return the maximum value that can be used to obtain a meaningful
361440a403fSchristos symbolic name or message.
362440a403fSchristos 
363440a403fSchristos @end deftypefn
364440a403fSchristos 
365440a403fSchristos */
366440a403fSchristos 
367440a403fSchristos int
signo_max(void)368440a403fSchristos signo_max (void)
369440a403fSchristos {
370440a403fSchristos   int maxsize;
371440a403fSchristos 
372440a403fSchristos   if (signal_names == NULL)
373440a403fSchristos     {
374440a403fSchristos       init_signal_tables ();
375440a403fSchristos     }
376440a403fSchristos   maxsize = MAX (sys_nsig, num_signal_names);
377440a403fSchristos   return (maxsize - 1);
378440a403fSchristos }
379440a403fSchristos 
380440a403fSchristos 
381440a403fSchristos /*
382440a403fSchristos 
383440a403fSchristos @deftypefn Supplemental {const char *} strsignal (int @var{signo})
384440a403fSchristos 
385440a403fSchristos Maps an signal number to an signal message string, the contents of
386440a403fSchristos which are implementation defined.  On systems which have the external
387440a403fSchristos variable @code{sys_siglist}, these strings will be the same as the
388440a403fSchristos ones used by @code{psignal()}.
389440a403fSchristos 
390440a403fSchristos If the supplied signal number is within the valid range of indices for
391440a403fSchristos the @code{sys_siglist}, but no message is available for the particular
392440a403fSchristos signal number, then returns the string @samp{Signal @var{num}}, where
393440a403fSchristos @var{num} is the signal number.
394440a403fSchristos 
395440a403fSchristos If the supplied signal number is not a valid index into
396440a403fSchristos @code{sys_siglist}, returns @code{NULL}.
397440a403fSchristos 
398440a403fSchristos The returned string is only guaranteed to be valid only until the next
399440a403fSchristos call to @code{strsignal}.
400440a403fSchristos 
401440a403fSchristos @end deftypefn
402440a403fSchristos 
403440a403fSchristos */
404440a403fSchristos 
405440a403fSchristos #ifndef HAVE_STRSIGNAL
406440a403fSchristos 
407440a403fSchristos char *
strsignal(int signo)408440a403fSchristos strsignal (int signo)
409440a403fSchristos {
410440a403fSchristos   char *msg;
411440a403fSchristos   static char buf[32];
412440a403fSchristos 
413440a403fSchristos #ifndef HAVE_SYS_SIGLIST
414440a403fSchristos 
415440a403fSchristos   if (signal_names == NULL)
416440a403fSchristos     {
417440a403fSchristos       init_signal_tables ();
418440a403fSchristos     }
419440a403fSchristos 
420440a403fSchristos #endif
421440a403fSchristos 
422440a403fSchristos   if ((signo < 0) || (signo >= sys_nsig))
423440a403fSchristos     {
424440a403fSchristos       /* Out of range, just return NULL */
425440a403fSchristos       msg = NULL;
426440a403fSchristos     }
427440a403fSchristos   else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
428440a403fSchristos     {
429440a403fSchristos       /* In range, but no sys_siglist or no entry at this index. */
430440a403fSchristos       sprintf (buf, "Signal %d", signo);
431440a403fSchristos       msg = buf;
432440a403fSchristos     }
433440a403fSchristos   else
434440a403fSchristos     {
435440a403fSchristos       /* In range, and a valid message.  Just return the message.  We
436440a403fSchristos 	 can safely cast away const, since POSIX says the user must
437440a403fSchristos 	 not modify the result.	 */
438440a403fSchristos       msg = (char *) sys_siglist[signo];
439440a403fSchristos     }
440440a403fSchristos 
441440a403fSchristos   return (msg);
442440a403fSchristos }
443440a403fSchristos 
444440a403fSchristos #endif /* ! HAVE_STRSIGNAL */
445440a403fSchristos 
446440a403fSchristos /*
447440a403fSchristos 
448440a403fSchristos @deftypefn Extension {const char*} strsigno (int @var{signo})
449440a403fSchristos 
450440a403fSchristos Given an signal number, returns a pointer to a string containing the
451440a403fSchristos symbolic name of that signal number, as found in @code{<signal.h>}.
452440a403fSchristos 
453440a403fSchristos If the supplied signal number is within the valid range of indices for
454440a403fSchristos symbolic names, but no name is available for the particular signal
455440a403fSchristos number, then returns the string @samp{Signal @var{num}}, where
456440a403fSchristos @var{num} is the signal number.
457440a403fSchristos 
458440a403fSchristos If the supplied signal number is not within the range of valid
459440a403fSchristos indices, then returns @code{NULL}.
460440a403fSchristos 
461440a403fSchristos The contents of the location pointed to are only guaranteed to be
462440a403fSchristos valid until the next call to @code{strsigno}.
463440a403fSchristos 
464440a403fSchristos @end deftypefn
465440a403fSchristos 
466440a403fSchristos */
467440a403fSchristos 
468440a403fSchristos const char *
strsigno(int signo)469440a403fSchristos strsigno (int signo)
470440a403fSchristos {
471440a403fSchristos   const char *name;
472440a403fSchristos   static char buf[32];
473440a403fSchristos 
474440a403fSchristos   if (signal_names == NULL)
475440a403fSchristos     {
476440a403fSchristos       init_signal_tables ();
477440a403fSchristos     }
478440a403fSchristos 
479440a403fSchristos   if ((signo < 0) || (signo >= num_signal_names))
480440a403fSchristos     {
481440a403fSchristos       /* Out of range, just return NULL */
482440a403fSchristos       name = NULL;
483440a403fSchristos     }
484440a403fSchristos   else if ((signal_names == NULL) || (signal_names[signo] == NULL))
485440a403fSchristos     {
486440a403fSchristos       /* In range, but no signal_names or no entry at this index. */
487440a403fSchristos       sprintf (buf, "Signal %d", signo);
488440a403fSchristos       name = (const char *) buf;
489440a403fSchristos     }
490440a403fSchristos   else
491440a403fSchristos     {
492440a403fSchristos       /* In range, and a valid name.  Just return the name. */
493440a403fSchristos       name = signal_names[signo];
494440a403fSchristos     }
495440a403fSchristos 
496440a403fSchristos   return (name);
497440a403fSchristos }
498440a403fSchristos 
499440a403fSchristos 
500440a403fSchristos /*
501440a403fSchristos 
502440a403fSchristos @deftypefn Extension int strtosigno (const char *@var{name})
503440a403fSchristos 
504440a403fSchristos Given the symbolic name of a signal, map it to a signal number.  If no
505440a403fSchristos translation is found, returns 0.
506440a403fSchristos 
507440a403fSchristos @end deftypefn
508440a403fSchristos 
509440a403fSchristos */
510440a403fSchristos 
511440a403fSchristos int
strtosigno(const char * name)512440a403fSchristos strtosigno (const char *name)
513440a403fSchristos {
514440a403fSchristos   int signo = 0;
515440a403fSchristos 
516440a403fSchristos   if (name != NULL)
517440a403fSchristos     {
518440a403fSchristos       if (signal_names == NULL)
519440a403fSchristos 	{
520440a403fSchristos 	  init_signal_tables ();
521440a403fSchristos 	}
522440a403fSchristos       for (signo = 0; signo < num_signal_names; signo++)
523440a403fSchristos 	{
524440a403fSchristos 	  if ((signal_names[signo] != NULL) &&
525440a403fSchristos 	      (strcmp (name, signal_names[signo]) == 0))
526440a403fSchristos 	    {
527440a403fSchristos 	      break;
528440a403fSchristos 	    }
529440a403fSchristos 	}
530440a403fSchristos       if (signo == num_signal_names)
531440a403fSchristos 	{
532440a403fSchristos 	  signo = 0;
533440a403fSchristos 	}
534440a403fSchristos     }
535440a403fSchristos   return (signo);
536440a403fSchristos }
537440a403fSchristos 
538440a403fSchristos 
539440a403fSchristos /*
540440a403fSchristos 
541440a403fSchristos @deftypefn Supplemental void psignal (int @var{signo}, char *@var{message})
542440a403fSchristos 
543440a403fSchristos Print @var{message} to the standard error, followed by a colon,
544440a403fSchristos followed by the description of the signal specified by @var{signo},
545440a403fSchristos followed by a newline.
546440a403fSchristos 
547440a403fSchristos @end deftypefn
548440a403fSchristos 
549440a403fSchristos */
550440a403fSchristos 
551440a403fSchristos #ifndef HAVE_PSIGNAL
552440a403fSchristos 
553440a403fSchristos void
psignal(int signo,const char * message)554*b88e3e88Schristos psignal (int signo, const char *message)
555440a403fSchristos {
556440a403fSchristos   if (signal_names == NULL)
557440a403fSchristos     {
558440a403fSchristos       init_signal_tables ();
559440a403fSchristos     }
560440a403fSchristos   if ((signo <= 0) || (signo >= sys_nsig))
561440a403fSchristos     {
562440a403fSchristos       fprintf (stderr, "%s: unknown signal\n", message);
563440a403fSchristos     }
564440a403fSchristos   else
565440a403fSchristos     {
566440a403fSchristos       fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
567440a403fSchristos     }
568440a403fSchristos }
569440a403fSchristos 
570440a403fSchristos #endif	/* ! HAVE_PSIGNAL */
571440a403fSchristos 
572440a403fSchristos 
573440a403fSchristos /* A simple little main that does nothing but print all the signal translations
574440a403fSchristos    if MAIN is defined and this file is compiled and linked. */
575440a403fSchristos 
576440a403fSchristos #ifdef MAIN
577440a403fSchristos 
578440a403fSchristos #include <stdio.h>
579440a403fSchristos 
580440a403fSchristos int
main(void)581440a403fSchristos main (void)
582440a403fSchristos {
583440a403fSchristos   int signo;
584440a403fSchristos   int maxsigno;
585440a403fSchristos   const char *name;
586440a403fSchristos   const char *msg;
587440a403fSchristos 
588440a403fSchristos   maxsigno = signo_max ();
589440a403fSchristos   printf ("%d entries in names table.\n", num_signal_names);
590440a403fSchristos   printf ("%d entries in messages table.\n", sys_nsig);
591440a403fSchristos   printf ("%d is max useful index.\n", maxsigno);
592440a403fSchristos 
593440a403fSchristos   /* Keep printing values until we get to the end of *both* tables, not
594440a403fSchristos      *either* table.  Note that knowing the maximum useful index does *not*
595440a403fSchristos      relieve us of the responsibility of testing the return pointer for
596440a403fSchristos      NULL. */
597440a403fSchristos 
598440a403fSchristos   for (signo = 0; signo <= maxsigno; signo++)
599440a403fSchristos     {
600440a403fSchristos       name = strsigno (signo);
601440a403fSchristos       name = (name == NULL) ? "<NULL>" : name;
602440a403fSchristos       msg = strsignal (signo);
603440a403fSchristos       msg = (msg == NULL) ? "<NULL>" : msg;
604440a403fSchristos       printf ("%-4d%-18s%s\n", signo, name, msg);
605440a403fSchristos     }
606440a403fSchristos 
607440a403fSchristos   return 0;
608440a403fSchristos }
609440a403fSchristos 
610440a403fSchristos #endif
611