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