1169695Skan/* Extended support for using signal values.
2169695Skan   Written by Fred Fish.  fnf@cygnus.com
3169695Skan   This file is in the public domain.  */
4169695Skan
5169695Skan#include "config.h"
6169695Skan#include "ansidecl.h"
7169695Skan#include "libiberty.h"
8169695Skan
9169695Skan/* We need to declare sys_siglist, because even if the system provides
10169695Skan   it we can't assume that it is declared in <signal.h> (for example,
11169695Skan   SunOS provides sys_siglist, but it does not declare it in any
12258817Spfg   header file).  However, we can't declare sys_siglist portably,
13169695Skan   because on some systems it is declared with const and on some
14169695Skan   systems it is declared without const.  If we were using autoconf,
15169695Skan   we could work out the right declaration.  Until, then we just
16169695Skan   ignore any declaration in the system header files, and always
17169695Skan   declare it ourselves.  With luck, this will always work.  */
18169695Skan#define sys_siglist no_such_symbol
19169695Skan#define sys_nsig sys_nsig__no_such_symbol
20169695Skan
21169695Skan#include <stdio.h>
22169695Skan#include <signal.h>
23169695Skan
24169695Skan/*  Routines imported from standard C runtime libraries. */
25169695Skan
26169695Skan#ifdef HAVE_STDLIB_H
27169695Skan#include <stdlib.h>
28169695Skan#else
29169695Skanextern PTR malloc ();
30169695Skan#endif
31169695Skan
32169695Skan#ifdef HAVE_STRING_H
33169695Skan#include <string.h>
34169695Skan#else
35169695Skanextern PTR memset ();
36169695Skan#endif
37169695Skan
38169695Skan/* Undefine the macro we used to hide the definition of sys_siglist
39169695Skan   found in the system header files.  */
40169695Skan#undef sys_siglist
41169695Skan#undef sys_nsig
42169695Skan
43169695Skan#ifndef NULL
44169695Skan#  define NULL (void *) 0
45169695Skan#endif
46169695Skan
47169695Skan#ifndef MAX
48169695Skan#  define MAX(a,b) ((a) > (b) ? (a) : (b))
49169695Skan#endif
50169695Skan
51169695Skanstatic void init_signal_tables (void);
52169695Skan
53169695Skan/* Translation table for signal values.
54169695Skan
55169695Skan   Note that this table is generally only accessed when it is used at runtime
56169695Skan   to initialize signal name and message tables that are indexed by signal
57169695Skan   value.
58169695Skan
59169695Skan   Not all of these signals will exist on all systems.  This table is the only
60169695Skan   thing that should have to be updated as new signal numbers are introduced.
61169695Skan   It's sort of ugly, but at least its portable. */
62169695Skan
63169695Skanstruct signal_info
64169695Skan{
65169695Skan  const int value;		/* The numeric value from <signal.h> */
66169695Skan  const char *const name;	/* The equivalent symbolic value */
67169695Skan#ifndef HAVE_SYS_SIGLIST
68169695Skan  const char *const msg;	/* Short message about this value */
69169695Skan#endif
70169695Skan};
71169695Skan
72169695Skan#ifndef HAVE_SYS_SIGLIST
73169695Skan#   define ENTRY(value, name, msg)	{value, name, msg}
74169695Skan#else
75169695Skan#   define ENTRY(value, name, msg)	{value, name}
76169695Skan#endif
77169695Skan
78169695Skanstatic const struct signal_info signal_table[] =
79169695Skan{
80169695Skan#if defined (SIGHUP)
81169695Skan  ENTRY(SIGHUP, "SIGHUP", "Hangup"),
82169695Skan#endif
83169695Skan#if defined (SIGINT)
84169695Skan  ENTRY(SIGINT, "SIGINT", "Interrupt"),
85169695Skan#endif
86169695Skan#if defined (SIGQUIT)
87169695Skan  ENTRY(SIGQUIT, "SIGQUIT", "Quit"),
88169695Skan#endif
89169695Skan#if defined (SIGILL)
90169695Skan  ENTRY(SIGILL, "SIGILL", "Illegal instruction"),
91169695Skan#endif
92169695Skan#if defined (SIGTRAP)
93169695Skan  ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"),
94169695Skan#endif
95169695Skan/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
96169695Skan   overrides SIGIOT.  SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
97169695Skan#if defined (SIGIOT)
98169695Skan  ENTRY(SIGIOT, "SIGIOT", "IOT trap"),
99169695Skan#endif
100169695Skan#if defined (SIGABRT)
101169695Skan  ENTRY(SIGABRT, "SIGABRT", "Aborted"),
102169695Skan#endif
103169695Skan#if defined (SIGEMT)
104169695Skan  ENTRY(SIGEMT, "SIGEMT", "Emulation trap"),
105169695Skan#endif
106169695Skan#if defined (SIGFPE)
107169695Skan  ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"),
108169695Skan#endif
109169695Skan#if defined (SIGKILL)
110169695Skan  ENTRY(SIGKILL, "SIGKILL", "Killed"),
111169695Skan#endif
112169695Skan#if defined (SIGBUS)
113169695Skan  ENTRY(SIGBUS, "SIGBUS", "Bus error"),
114169695Skan#endif
115169695Skan#if defined (SIGSEGV)
116169695Skan  ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"),
117169695Skan#endif
118169695Skan#if defined (SIGSYS)
119169695Skan  ENTRY(SIGSYS, "SIGSYS", "Bad system call"),
120169695Skan#endif
121169695Skan#if defined (SIGPIPE)
122169695Skan  ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"),
123169695Skan#endif
124169695Skan#if defined (SIGALRM)
125169695Skan  ENTRY(SIGALRM, "SIGALRM", "Alarm clock"),
126169695Skan#endif
127169695Skan#if defined (SIGTERM)
128169695Skan  ENTRY(SIGTERM, "SIGTERM", "Terminated"),
129169695Skan#endif
130169695Skan#if defined (SIGUSR1)
131169695Skan  ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"),
132169695Skan#endif
133169695Skan#if defined (SIGUSR2)
134169695Skan  ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"),
135169695Skan#endif
136169695Skan/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
137169695Skan   overrides SIGCLD.  SIGCHLD is in POXIX.1 */
138169695Skan#if defined (SIGCLD)
139169695Skan  ENTRY(SIGCLD, "SIGCLD", "Child status changed"),
140169695Skan#endif
141169695Skan#if defined (SIGCHLD)
142169695Skan  ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"),
143169695Skan#endif
144169695Skan#if defined (SIGPWR)
145169695Skan  ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"),
146169695Skan#endif
147169695Skan#if defined (SIGWINCH)
148169695Skan  ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"),
149169695Skan#endif
150169695Skan#if defined (SIGURG)
151169695Skan  ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"),
152169695Skan#endif
153169695Skan#if defined (SIGIO)
154169695Skan  /* "I/O pending" has also been suggested, but is misleading since the
155169695Skan     signal only happens when the process has asked for it, not everytime
156169695Skan     I/O is pending. */
157169695Skan  ENTRY(SIGIO, "SIGIO", "I/O possible"),
158169695Skan#endif
159169695Skan#if defined (SIGPOLL)
160169695Skan  ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"),
161169695Skan#endif
162169695Skan#if defined (SIGSTOP)
163169695Skan  ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"),
164169695Skan#endif
165169695Skan#if defined (SIGTSTP)
166169695Skan  ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"),
167169695Skan#endif
168169695Skan#if defined (SIGCONT)
169169695Skan  ENTRY(SIGCONT, "SIGCONT", "Continued"),
170169695Skan#endif
171169695Skan#if defined (SIGTTIN)
172169695Skan  ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"),
173169695Skan#endif
174169695Skan#if defined (SIGTTOU)
175169695Skan  ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"),
176169695Skan#endif
177169695Skan#if defined (SIGVTALRM)
178169695Skan  ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"),
179169695Skan#endif
180169695Skan#if defined (SIGPROF)
181169695Skan  ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"),
182169695Skan#endif
183169695Skan#if defined (SIGXCPU)
184169695Skan  ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"),
185169695Skan#endif
186169695Skan#if defined (SIGXFSZ)
187169695Skan  ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"),
188169695Skan#endif
189169695Skan#if defined (SIGWIND)
190169695Skan  ENTRY(SIGWIND, "SIGWIND", "SIGWIND"),
191169695Skan#endif
192169695Skan#if defined (SIGPHONE)
193169695Skan  ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"),
194169695Skan#endif
195169695Skan#if defined (SIGLOST)
196169695Skan  ENTRY(SIGLOST, "SIGLOST", "Resource lost"),
197169695Skan#endif
198169695Skan#if defined (SIGWAITING)
199169695Skan  ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"),
200169695Skan#endif
201169695Skan#if defined (SIGLWP)
202169695Skan  ENTRY(SIGLWP, "SIGLWP", "Signal LWP"),
203169695Skan#endif
204169695Skan#if defined (SIGDANGER)
205169695Skan  ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"),
206169695Skan#endif
207169695Skan#if defined (SIGGRANT)
208169695Skan  ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"),
209169695Skan#endif
210169695Skan#if defined (SIGRETRACT)
211169695Skan  ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"),
212169695Skan#endif
213169695Skan#if defined (SIGMSG)
214169695Skan  ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"),
215169695Skan#endif
216169695Skan#if defined (SIGSOUND)
217169695Skan  ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"),
218169695Skan#endif
219169695Skan#if defined (SIGSAK)
220169695Skan  ENTRY(SIGSAK, "SIGSAK", "Secure attention"),
221169695Skan#endif
222169695Skan  ENTRY(0, NULL, NULL)
223169695Skan};
224169695Skan
225169695Skan/* Translation table allocated and initialized at runtime.  Indexed by the
226169695Skan   signal value to find the equivalent symbolic value. */
227169695Skan
228169695Skanstatic const char **signal_names;
229169695Skanstatic int num_signal_names = 0;
230169695Skan
231169695Skan/* Translation table allocated and initialized at runtime, if it does not
232169695Skan   already exist in the host environment.  Indexed by the signal value to find
233169695Skan   the descriptive string.
234169695Skan
235169695Skan   We don't export it for use in other modules because even though it has the
236169695Skan   same name, it differs from other implementations in that it is dynamically
237169695Skan   initialized rather than statically initialized. */
238169695Skan
239169695Skan#ifndef HAVE_SYS_SIGLIST
240169695Skan
241169695Skanstatic int sys_nsig;
242169695Skanstatic const char **sys_siglist;
243169695Skan
244169695Skan#else
245169695Skan
246169695Skan#ifdef NSIG
247169695Skanstatic int sys_nsig = NSIG;
248169695Skan#else
249169695Skan#ifdef _NSIG
250169695Skanstatic int sys_nsig = _NSIG;
251169695Skan#endif
252169695Skan#endif
253169695Skanextern const char * const sys_siglist[];
254169695Skan
255169695Skan#endif
256169695Skan
257169695Skan
258169695Skan/*
259169695Skan
260169695SkanNAME
261169695Skan
262169695Skan	init_signal_tables -- initialize the name and message tables
263169695Skan
264169695SkanSYNOPSIS
265169695Skan
266169695Skan	static void init_signal_tables ();
267169695Skan
268169695SkanDESCRIPTION
269169695Skan
270169695Skan	Using the signal_table, which is initialized at compile time, generate
271169695Skan	the signal_names and the sys_siglist (if needed) tables, which are
272169695Skan	indexed at runtime by a specific signal value.
273169695Skan
274169695SkanBUGS
275169695Skan
276169695Skan	The initialization of the tables may fail under low memory conditions,
277169695Skan	in which case we don't do anything particularly useful, but we don't
278169695Skan	bomb either.  Who knows, it might succeed at a later point if we free
279169695Skan	some memory in the meantime.  In any case, the other routines know
280169695Skan	how to deal with lack of a table after trying to initialize it.  This
281169695Skan	may or may not be considered to be a bug, that we don't specifically
282169695Skan	warn about this particular failure mode.
283169695Skan
284169695Skan*/
285169695Skan
286169695Skanstatic void
287169695Skaninit_signal_tables (void)
288169695Skan{
289169695Skan  const struct signal_info *eip;
290169695Skan  int nbytes;
291169695Skan
292169695Skan  /* If we haven't already scanned the signal_table once to find the maximum
293169695Skan     signal value, then go find it now. */
294169695Skan
295169695Skan  if (num_signal_names == 0)
296169695Skan    {
297169695Skan      for (eip = signal_table; eip -> name != NULL; eip++)
298169695Skan	{
299169695Skan	  if (eip -> value >= num_signal_names)
300169695Skan	    {
301169695Skan	      num_signal_names = eip -> value + 1;
302169695Skan	    }
303169695Skan	}
304169695Skan    }
305169695Skan
306169695Skan  /* Now attempt to allocate the signal_names table, zero it out, and then
307169695Skan     initialize it from the statically initialized signal_table. */
308169695Skan
309169695Skan  if (signal_names == NULL)
310169695Skan    {
311169695Skan      nbytes = num_signal_names * sizeof (char *);
312169695Skan      if ((signal_names = (const char **) malloc (nbytes)) != NULL)
313169695Skan	{
314169695Skan	  memset (signal_names, 0, nbytes);
315169695Skan	  for (eip = signal_table; eip -> name != NULL; eip++)
316169695Skan	    {
317169695Skan	      signal_names[eip -> value] = eip -> name;
318169695Skan	    }
319169695Skan	}
320169695Skan    }
321169695Skan
322169695Skan#ifndef HAVE_SYS_SIGLIST
323169695Skan
324169695Skan  /* Now attempt to allocate the sys_siglist table, zero it out, and then
325169695Skan     initialize it from the statically initialized signal_table. */
326169695Skan
327169695Skan  if (sys_siglist == NULL)
328169695Skan    {
329169695Skan      nbytes = num_signal_names * sizeof (char *);
330169695Skan      if ((sys_siglist = (const char **) malloc (nbytes)) != NULL)
331169695Skan	{
332169695Skan	  memset (sys_siglist, 0, nbytes);
333169695Skan	  sys_nsig = num_signal_names;
334169695Skan	  for (eip = signal_table; eip -> name != NULL; eip++)
335169695Skan	    {
336169695Skan	      sys_siglist[eip -> value] = eip -> msg;
337169695Skan	    }
338169695Skan	}
339169695Skan    }
340169695Skan
341169695Skan#endif
342169695Skan
343169695Skan}
344169695Skan
345169695Skan
346169695Skan/*
347169695Skan
348169695Skan@deftypefn Extension int signo_max (void)
349169695Skan
350169695SkanReturns the maximum signal value for which a corresponding symbolic
351169695Skanname or message is available.  Note that in the case where we use the
352169695Skan@code{sys_siglist} supplied by the system, it is possible for there to
353169695Skanbe more symbolic names than messages, or vice versa.  In fact, the
354169695Skanmanual page for @code{psignal(3b)} explicitly warns that one should
355169695Skancheck the size of the table (@code{NSIG}) before indexing it, since
356169695Skannew signal codes may be added to the system before they are added to
357169695Skanthe table.  Thus @code{NSIG} might be smaller than value implied by
358169695Skanthe largest signo value defined in @code{<signal.h>}.
359169695Skan
360169695SkanWe return the maximum value that can be used to obtain a meaningful
361169695Skansymbolic name or message.
362169695Skan
363169695Skan@end deftypefn
364169695Skan
365169695Skan*/
366169695Skan
367169695Skanint
368169695Skansigno_max (void)
369169695Skan{
370169695Skan  int maxsize;
371169695Skan
372169695Skan  if (signal_names == NULL)
373169695Skan    {
374169695Skan      init_signal_tables ();
375169695Skan    }
376169695Skan  maxsize = MAX (sys_nsig, num_signal_names);
377169695Skan  return (maxsize - 1);
378169695Skan}
379169695Skan
380169695Skan
381169695Skan/*
382169695Skan
383169695Skan@deftypefn Supplemental {const char *} strsignal (int @var{signo})
384169695Skan
385169695SkanMaps an signal number to an signal message string, the contents of
386169695Skanwhich are implementation defined.  On systems which have the external
387169695Skanvariable @code{sys_siglist}, these strings will be the same as the
388169695Skanones used by @code{psignal()}.
389169695Skan
390169695SkanIf the supplied signal number is within the valid range of indices for
391169695Skanthe @code{sys_siglist}, but no message is available for the particular
392169695Skansignal number, then returns the string @samp{Signal @var{num}}, where
393169695Skan@var{num} is the signal number.
394169695Skan
395169695SkanIf the supplied signal number is not a valid index into
396169695Skan@code{sys_siglist}, returns @code{NULL}.
397169695Skan
398169695SkanThe returned string is only guaranteed to be valid only until the next
399169695Skancall to @code{strsignal}.
400169695Skan
401169695Skan@end deftypefn
402169695Skan
403169695Skan*/
404169695Skan
405169695Skan#ifndef HAVE_STRSIGNAL
406169695Skan
407169695Skanconst char *
408169695Skanstrsignal (int signo)
409169695Skan{
410169695Skan  const char *msg;
411169695Skan  static char buf[32];
412169695Skan
413169695Skan#ifndef HAVE_SYS_SIGLIST
414169695Skan
415169695Skan  if (signal_names == NULL)
416169695Skan    {
417169695Skan      init_signal_tables ();
418169695Skan    }
419169695Skan
420169695Skan#endif
421169695Skan
422169695Skan  if ((signo < 0) || (signo >= sys_nsig))
423169695Skan    {
424169695Skan      /* Out of range, just return NULL */
425169695Skan      msg = NULL;
426169695Skan    }
427169695Skan  else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
428169695Skan    {
429169695Skan      /* In range, but no sys_siglist or no entry at this index. */
430169695Skan      sprintf (buf, "Signal %d", signo);
431169695Skan      msg = (const char *) buf;
432169695Skan    }
433169695Skan  else
434169695Skan    {
435169695Skan      /* In range, and a valid message.  Just return the message. */
436169695Skan      msg = (const char *) sys_siglist[signo];
437169695Skan    }
438169695Skan
439169695Skan  return (msg);
440169695Skan}
441169695Skan
442169695Skan#endif /* ! HAVE_STRSIGNAL */
443169695Skan
444169695Skan/*
445169695Skan
446169695Skan@deftypefn Extension {const char*} strsigno (int @var{signo})
447169695Skan
448169695SkanGiven an signal number, returns a pointer to a string containing the
449169695Skansymbolic name of that signal number, as found in @code{<signal.h>}.
450169695Skan
451169695SkanIf the supplied signal number is within the valid range of indices for
452169695Skansymbolic names, but no name is available for the particular signal
453169695Skannumber, then returns the string @samp{Signal @var{num}}, where
454169695Skan@var{num} is the signal number.
455169695Skan
456169695SkanIf the supplied signal number is not within the range of valid
457169695Skanindices, then returns @code{NULL}.
458169695Skan
459169695SkanThe contents of the location pointed to are only guaranteed to be
460169695Skanvalid until the next call to @code{strsigno}.
461169695Skan
462169695Skan@end deftypefn
463169695Skan
464169695Skan*/
465169695Skan
466169695Skanconst char *
467169695Skanstrsigno (int signo)
468169695Skan{
469169695Skan  const char *name;
470169695Skan  static char buf[32];
471169695Skan
472169695Skan  if (signal_names == NULL)
473169695Skan    {
474169695Skan      init_signal_tables ();
475169695Skan    }
476169695Skan
477169695Skan  if ((signo < 0) || (signo >= num_signal_names))
478169695Skan    {
479169695Skan      /* Out of range, just return NULL */
480169695Skan      name = NULL;
481169695Skan    }
482169695Skan  else if ((signal_names == NULL) || (signal_names[signo] == NULL))
483169695Skan    {
484169695Skan      /* In range, but no signal_names or no entry at this index. */
485169695Skan      sprintf (buf, "Signal %d", signo);
486169695Skan      name = (const char *) buf;
487169695Skan    }
488169695Skan  else
489169695Skan    {
490169695Skan      /* In range, and a valid name.  Just return the name. */
491169695Skan      name = signal_names[signo];
492169695Skan    }
493169695Skan
494169695Skan  return (name);
495169695Skan}
496169695Skan
497169695Skan
498169695Skan/*
499169695Skan
500169695Skan@deftypefn Extension int strtosigno (const char *@var{name})
501169695Skan
502169695SkanGiven the symbolic name of a signal, map it to a signal number.  If no
503169695Skantranslation is found, returns 0.
504169695Skan
505169695Skan@end deftypefn
506169695Skan
507169695Skan*/
508169695Skan
509169695Skanint
510169695Skanstrtosigno (const char *name)
511169695Skan{
512169695Skan  int signo = 0;
513169695Skan
514169695Skan  if (name != NULL)
515169695Skan    {
516169695Skan      if (signal_names == NULL)
517169695Skan	{
518169695Skan	  init_signal_tables ();
519169695Skan	}
520169695Skan      for (signo = 0; signo < num_signal_names; signo++)
521169695Skan	{
522169695Skan	  if ((signal_names[signo] != NULL) &&
523169695Skan	      (strcmp (name, signal_names[signo]) == 0))
524169695Skan	    {
525169695Skan	      break;
526169695Skan	    }
527169695Skan	}
528169695Skan      if (signo == num_signal_names)
529169695Skan	{
530169695Skan	  signo = 0;
531169695Skan	}
532169695Skan    }
533169695Skan  return (signo);
534169695Skan}
535169695Skan
536169695Skan
537169695Skan/*
538169695Skan
539258817Spfg@deftypefn Supplemental void psignal (int @var{signo}, char *@var{message})
540169695Skan
541169695SkanPrint @var{message} to the standard error, followed by a colon,
542169695Skanfollowed by the description of the signal specified by @var{signo},
543169695Skanfollowed by a newline.
544169695Skan
545169695Skan@end deftypefn
546169695Skan
547169695Skan*/
548169695Skan
549169695Skan#ifndef HAVE_PSIGNAL
550169695Skan
551169695Skanvoid
552258817Spfgpsignal (int signo, char *message)
553169695Skan{
554169695Skan  if (signal_names == NULL)
555169695Skan    {
556169695Skan      init_signal_tables ();
557169695Skan    }
558169695Skan  if ((signo <= 0) || (signo >= sys_nsig))
559169695Skan    {
560169695Skan      fprintf (stderr, "%s: unknown signal\n", message);
561169695Skan    }
562169695Skan  else
563169695Skan    {
564169695Skan      fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
565169695Skan    }
566169695Skan}
567169695Skan
568169695Skan#endif	/* ! HAVE_PSIGNAL */
569169695Skan
570169695Skan
571169695Skan/* A simple little main that does nothing but print all the signal translations
572169695Skan   if MAIN is defined and this file is compiled and linked. */
573169695Skan
574169695Skan#ifdef MAIN
575169695Skan
576169695Skan#include <stdio.h>
577169695Skan
578169695Skanint
579169695Skanmain (void)
580169695Skan{
581169695Skan  int signo;
582169695Skan  int maxsigno;
583169695Skan  const char *name;
584169695Skan  const char *msg;
585169695Skan
586169695Skan  maxsigno = signo_max ();
587169695Skan  printf ("%d entries in names table.\n", num_signal_names);
588169695Skan  printf ("%d entries in messages table.\n", sys_nsig);
589169695Skan  printf ("%d is max useful index.\n", maxsigno);
590169695Skan
591169695Skan  /* Keep printing values until we get to the end of *both* tables, not
592169695Skan     *either* table.  Note that knowing the maximum useful index does *not*
593169695Skan     relieve us of the responsibility of testing the return pointer for
594169695Skan     NULL. */
595169695Skan
596169695Skan  for (signo = 0; signo <= maxsigno; signo++)
597169695Skan    {
598169695Skan      name = strsigno (signo);
599169695Skan      name = (name == NULL) ? "<NULL>" : name;
600169695Skan      msg = strsignal (signo);
601169695Skan      msg = (msg == NULL) ? "<NULL>" : msg;
602169695Skan      printf ("%-4d%-18s%s\n", signo, name, msg);
603169695Skan    }
604169695Skan
605169695Skan  return 0;
606169695Skan}
607169695Skan
608169695Skan#endif
609