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