strerror.c revision 77298
1/* Extended support for using errno values.
2   Written by Fred Fish.  fnf@cygnus.com
3   This file is in the public domain.  --Per Bothner.  */
4
5#include "ansidecl.h"
6#include "libiberty.h"
7
8#include "config.h"
9
10#ifdef HAVE_SYS_ERRLIST
11/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
12   might declare sys_errlist in a way that the compiler might consider
13   incompatible with our later declaration, perhaps by using const
14   attributes.  So we hide the declaration in errno.h (if any) using a
15   macro. */
16#define sys_errlist sys_errlist__
17#endif
18
19#include <stdio.h>
20#include <errno.h>
21
22#ifdef HAVE_SYS_ERRLIST
23#undef sys_errlist
24#endif
25
26/*  Routines imported from standard C runtime libraries. */
27
28#ifdef HAVE_STDLIB_H
29#include <stdlib.h>
30#else
31extern PTR malloc ();
32#endif
33
34#ifdef HAVE_STRING_H
35#include <string.h>
36#else
37extern PTR memset ();
38#endif
39
40#ifndef MAX
41#  define MAX(a,b) ((a) > (b) ? (a) : (b))
42#endif
43
44static void init_error_tables PARAMS ((void));
45
46/* Translation table for errno values.  See intro(2) in most UNIX systems
47   Programmers Reference Manuals.
48
49   Note that this table is generally only accessed when it is used at runtime
50   to initialize errno name and message tables that are indexed by errno
51   value.
52
53   Not all of these errnos will exist on all systems.  This table is the only
54   thing that should have to be updated as new error numbers are introduced.
55   It's sort of ugly, but at least its portable. */
56
57struct error_info
58{
59  int value;		/* The numeric value from <errno.h> */
60  const char *name;	/* The equivalent symbolic value */
61#ifndef HAVE_SYS_ERRLIST
62  const char *msg;	/* Short message about this value */
63#endif
64};
65
66#ifndef HAVE_SYS_ERRLIST
67#   define ENTRY(value, name, msg)	{value, name, msg}
68#else
69#   define ENTRY(value, name, msg)	{value, name}
70#endif
71
72static const struct error_info error_table[] =
73{
74#if defined (EPERM)
75  ENTRY(EPERM, "EPERM", "Not owner"),
76#endif
77#if defined (ENOENT)
78  ENTRY(ENOENT, "ENOENT", "No such file or directory"),
79#endif
80#if defined (ESRCH)
81  ENTRY(ESRCH, "ESRCH", "No such process"),
82#endif
83#if defined (EINTR)
84  ENTRY(EINTR, "EINTR", "Interrupted system call"),
85#endif
86#if defined (EIO)
87  ENTRY(EIO, "EIO", "I/O error"),
88#endif
89#if defined (ENXIO)
90  ENTRY(ENXIO, "ENXIO", "No such device or address"),
91#endif
92#if defined (E2BIG)
93  ENTRY(E2BIG, "E2BIG", "Arg list too long"),
94#endif
95#if defined (ENOEXEC)
96  ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
97#endif
98#if defined (EBADF)
99  ENTRY(EBADF, "EBADF", "Bad file number"),
100#endif
101#if defined (ECHILD)
102  ENTRY(ECHILD, "ECHILD", "No child processes"),
103#endif
104#if defined (EWOULDBLOCK)	/* Put before EAGAIN, sometimes aliased */
105  ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
106#endif
107#if defined (EAGAIN)
108  ENTRY(EAGAIN, "EAGAIN", "No more processes"),
109#endif
110#if defined (ENOMEM)
111  ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
112#endif
113#if defined (EACCES)
114  ENTRY(EACCES, "EACCES", "Permission denied"),
115#endif
116#if defined (EFAULT)
117  ENTRY(EFAULT, "EFAULT", "Bad address"),
118#endif
119#if defined (ENOTBLK)
120  ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
121#endif
122#if defined (EBUSY)
123  ENTRY(EBUSY, "EBUSY", "Device busy"),
124#endif
125#if defined (EEXIST)
126  ENTRY(EEXIST, "EEXIST", "File exists"),
127#endif
128#if defined (EXDEV)
129  ENTRY(EXDEV, "EXDEV", "Cross-device link"),
130#endif
131#if defined (ENODEV)
132  ENTRY(ENODEV, "ENODEV", "No such device"),
133#endif
134#if defined (ENOTDIR)
135  ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
136#endif
137#if defined (EISDIR)
138  ENTRY(EISDIR, "EISDIR", "Is a directory"),
139#endif
140#if defined (EINVAL)
141  ENTRY(EINVAL, "EINVAL", "Invalid argument"),
142#endif
143#if defined (ENFILE)
144  ENTRY(ENFILE, "ENFILE", "File table overflow"),
145#endif
146#if defined (EMFILE)
147  ENTRY(EMFILE, "EMFILE", "Too many open files"),
148#endif
149#if defined (ENOTTY)
150  ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
151#endif
152#if defined (ETXTBSY)
153  ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
154#endif
155#if defined (EFBIG)
156  ENTRY(EFBIG, "EFBIG", "File too large"),
157#endif
158#if defined (ENOSPC)
159  ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
160#endif
161#if defined (ESPIPE)
162  ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
163#endif
164#if defined (EROFS)
165  ENTRY(EROFS, "EROFS", "Read-only file system"),
166#endif
167#if defined (EMLINK)
168  ENTRY(EMLINK, "EMLINK", "Too many links"),
169#endif
170#if defined (EPIPE)
171  ENTRY(EPIPE, "EPIPE", "Broken pipe"),
172#endif
173#if defined (EDOM)
174  ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
175#endif
176#if defined (ERANGE)
177  ENTRY(ERANGE, "ERANGE", "Math result not representable"),
178#endif
179#if defined (ENOMSG)
180  ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
181#endif
182#if defined (EIDRM)
183  ENTRY(EIDRM, "EIDRM", "Identifier removed"),
184#endif
185#if defined (ECHRNG)
186  ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
187#endif
188#if defined (EL2NSYNC)
189  ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
190#endif
191#if defined (EL3HLT)
192  ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
193#endif
194#if defined (EL3RST)
195  ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
196#endif
197#if defined (ELNRNG)
198  ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
199#endif
200#if defined (EUNATCH)
201  ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
202#endif
203#if defined (ENOCSI)
204  ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
205#endif
206#if defined (EL2HLT)
207  ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
208#endif
209#if defined (EDEADLK)
210  ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
211#endif
212#if defined (ENOLCK)
213  ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
214#endif
215#if defined (EBADE)
216  ENTRY(EBADE, "EBADE", "Invalid exchange"),
217#endif
218#if defined (EBADR)
219  ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
220#endif
221#if defined (EXFULL)
222  ENTRY(EXFULL, "EXFULL", "Exchange full"),
223#endif
224#if defined (ENOANO)
225  ENTRY(ENOANO, "ENOANO", "No anode"),
226#endif
227#if defined (EBADRQC)
228  ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
229#endif
230#if defined (EBADSLT)
231  ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
232#endif
233#if defined (EDEADLOCK)
234  ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
235#endif
236#if defined (EBFONT)
237  ENTRY(EBFONT, "EBFONT", "Bad font file format"),
238#endif
239#if defined (ENOSTR)
240  ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
241#endif
242#if defined (ENODATA)
243  ENTRY(ENODATA, "ENODATA", "No data available"),
244#endif
245#if defined (ETIME)
246  ENTRY(ETIME, "ETIME", "Timer expired"),
247#endif
248#if defined (ENOSR)
249  ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
250#endif
251#if defined (ENONET)
252  ENTRY(ENONET, "ENONET", "Machine is not on the network"),
253#endif
254#if defined (ENOPKG)
255  ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
256#endif
257#if defined (EREMOTE)
258  ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
259#endif
260#if defined (ENOLINK)
261  ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
262#endif
263#if defined (EADV)
264  ENTRY(EADV, "EADV", "Advertise error"),
265#endif
266#if defined (ESRMNT)
267  ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
268#endif
269#if defined (ECOMM)
270  ENTRY(ECOMM, "ECOMM", "Communication error on send"),
271#endif
272#if defined (EPROTO)
273  ENTRY(EPROTO, "EPROTO", "Protocol error"),
274#endif
275#if defined (EMULTIHOP)
276  ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
277#endif
278#if defined (EDOTDOT)
279  ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
280#endif
281#if defined (EBADMSG)
282  ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
283#endif
284#if defined (ENAMETOOLONG)
285  ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
286#endif
287#if defined (EOVERFLOW)
288  ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
289#endif
290#if defined (ENOTUNIQ)
291  ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
292#endif
293#if defined (EBADFD)
294  ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
295#endif
296#if defined (EREMCHG)
297  ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
298#endif
299#if defined (ELIBACC)
300  ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
301#endif
302#if defined (ELIBBAD)
303  ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
304#endif
305#if defined (ELIBSCN)
306  ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
307#endif
308#if defined (ELIBMAX)
309  ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
310#endif
311#if defined (ELIBEXEC)
312  ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
313#endif
314#if defined (EILSEQ)
315  ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
316#endif
317#if defined (ENOSYS)
318  ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
319#endif
320#if defined (ELOOP)
321  ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
322#endif
323#if defined (ERESTART)
324  ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
325#endif
326#if defined (ESTRPIPE)
327  ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
328#endif
329#if defined (ENOTEMPTY)
330  ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
331#endif
332#if defined (EUSERS)
333  ENTRY(EUSERS, "EUSERS", "Too many users"),
334#endif
335#if defined (ENOTSOCK)
336  ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
337#endif
338#if defined (EDESTADDRREQ)
339  ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
340#endif
341#if defined (EMSGSIZE)
342  ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
343#endif
344#if defined (EPROTOTYPE)
345  ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
346#endif
347#if defined (ENOPROTOOPT)
348  ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
349#endif
350#if defined (EPROTONOSUPPORT)
351  ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
352#endif
353#if defined (ESOCKTNOSUPPORT)
354  ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
355#endif
356#if defined (EOPNOTSUPP)
357  ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
358#endif
359#if defined (EPFNOSUPPORT)
360  ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
361#endif
362#if defined (EAFNOSUPPORT)
363  ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
364#endif
365#if defined (EADDRINUSE)
366  ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
367#endif
368#if defined (EADDRNOTAVAIL)
369  ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
370#endif
371#if defined (ENETDOWN)
372  ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
373#endif
374#if defined (ENETUNREACH)
375  ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
376#endif
377#if defined (ENETRESET)
378  ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
379#endif
380#if defined (ECONNABORTED)
381  ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
382#endif
383#if defined (ECONNRESET)
384  ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
385#endif
386#if defined (ENOBUFS)
387  ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
388#endif
389#if defined (EISCONN)
390  ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
391#endif
392#if defined (ENOTCONN)
393  ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
394#endif
395#if defined (ESHUTDOWN)
396  ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
397#endif
398#if defined (ETOOMANYREFS)
399  ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
400#endif
401#if defined (ETIMEDOUT)
402  ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
403#endif
404#if defined (ECONNREFUSED)
405  ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
406#endif
407#if defined (EHOSTDOWN)
408  ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
409#endif
410#if defined (EHOSTUNREACH)
411  ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
412#endif
413#if defined (EALREADY)
414  ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
415#endif
416#if defined (EINPROGRESS)
417  ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
418#endif
419#if defined (ESTALE)
420  ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
421#endif
422#if defined (EUCLEAN)
423  ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
424#endif
425#if defined (ENOTNAM)
426  ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
427#endif
428#if defined (ENAVAIL)
429  ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
430#endif
431#if defined (EISNAM)
432  ENTRY(EISNAM, "EISNAM", "Is a named type file"),
433#endif
434#if defined (EREMOTEIO)
435  ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
436#endif
437  ENTRY(0, NULL, NULL)
438};
439
440#ifdef EVMSERR
441/* This is not in the table, because the numeric value of EVMSERR (32767)
442   lies outside the range of sys_errlist[].  */
443static struct { int value; const char *name, *msg; }
444  evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
445#endif
446
447/* Translation table allocated and initialized at runtime.  Indexed by the
448   errno value to find the equivalent symbolic value. */
449
450static const char **error_names;
451static int num_error_names = 0;
452
453/* Translation table allocated and initialized at runtime, if it does not
454   already exist in the host environment.  Indexed by the errno value to find
455   the descriptive string.
456
457   We don't export it for use in other modules because even though it has the
458   same name, it differs from other implementations in that it is dynamically
459   initialized rather than statically initialized. */
460
461#ifndef HAVE_SYS_ERRLIST
462
463static int sys_nerr;
464static const char **sys_errlist;
465
466#else
467
468extern int sys_nerr;
469extern char *sys_errlist[];
470
471#endif
472
473
474/*
475
476NAME
477
478	init_error_tables -- initialize the name and message tables
479
480SYNOPSIS
481
482	static void init_error_tables ();
483
484DESCRIPTION
485
486	Using the error_table, which is initialized at compile time, generate
487	the error_names and the sys_errlist (if needed) tables, which are
488	indexed at runtime by a specific errno value.
489
490BUGS
491
492	The initialization of the tables may fail under low memory conditions,
493	in which case we don't do anything particularly useful, but we don't
494	bomb either.  Who knows, it might succeed at a later point if we free
495	some memory in the meantime.  In any case, the other routines know
496	how to deal with lack of a table after trying to initialize it.  This
497	may or may not be considered to be a bug, that we don't specifically
498	warn about this particular failure mode.
499
500*/
501
502static void
503init_error_tables ()
504{
505  const struct error_info *eip;
506  int nbytes;
507
508  /* If we haven't already scanned the error_table once to find the maximum
509     errno value, then go find it now. */
510
511  if (num_error_names == 0)
512    {
513      for (eip = error_table; eip -> name != NULL; eip++)
514	{
515	  if (eip -> value >= num_error_names)
516	    {
517	      num_error_names = eip -> value + 1;
518	    }
519	}
520    }
521
522  /* Now attempt to allocate the error_names table, zero it out, and then
523     initialize it from the statically initialized error_table. */
524
525  if (error_names == NULL)
526    {
527      nbytes = num_error_names * sizeof (char *);
528      if ((error_names = (const char **) malloc (nbytes)) != NULL)
529	{
530	  memset (error_names, 0, nbytes);
531	  for (eip = error_table; eip -> name != NULL; eip++)
532	    {
533	      error_names[eip -> value] = eip -> name;
534	    }
535	}
536    }
537
538#ifndef HAVE_SYS_ERRLIST
539
540  /* Now attempt to allocate the sys_errlist table, zero it out, and then
541     initialize it from the statically initialized error_table. */
542
543  if (sys_errlist == NULL)
544    {
545      nbytes = num_error_names * sizeof (char *);
546      if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
547	{
548	  memset (sys_errlist, 0, nbytes);
549	  sys_nerr = num_error_names;
550	  for (eip = error_table; eip -> name != NULL; eip++)
551	    {
552	      sys_errlist[eip -> value] = eip -> msg;
553	    }
554	}
555    }
556
557#endif
558
559}
560
561/*
562
563NAME
564
565	errno_max -- return the max errno value
566
567SYNOPSIS
568
569	int errno_max ();
570
571DESCRIPTION
572
573	Returns the maximum errno value for which a corresponding symbolic
574	name or message is available.  Note that in the case where
575	we use the sys_errlist supplied by the system, it is possible for
576	there to be more symbolic names than messages, or vice versa.
577	In fact, the manual page for perror(3C) explicitly warns that one
578	should check the size of the table (sys_nerr) before indexing it,
579	since new error codes may be added to the system before they are
580	added to the table.  Thus sys_nerr might be smaller than value
581	implied by the largest errno value defined in <errno.h>.
582
583	We return the maximum value that can be used to obtain a meaningful
584	symbolic name or message.
585
586*/
587
588int
589errno_max ()
590{
591  int maxsize;
592
593  if (error_names == NULL)
594    {
595      init_error_tables ();
596    }
597  maxsize = MAX (sys_nerr, num_error_names);
598  return (maxsize - 1);
599}
600
601#ifndef HAVE_STRERROR
602
603/*
604
605NAME
606
607	strerror -- map an error number to an error message string
608
609SYNOPSIS
610
611	char *strerror (int errnoval)
612
613DESCRIPTION
614
615	Maps an errno number to an error message string, the contents of
616	which are implementation defined.  On systems which have the external
617	variables sys_nerr and sys_errlist, these strings will be the same
618	as the ones used by perror().
619
620	If the supplied error number is within the valid range of indices
621	for the sys_errlist, but no message is available for the particular
622	error number, then returns the string "Error NUM", where NUM is the
623	error number.
624
625	If the supplied error number is not a valid index into sys_errlist,
626	returns NULL.
627
628	The returned string is only guaranteed to be valid only until the
629	next call to strerror.
630
631*/
632
633char *
634strerror (errnoval)
635  int errnoval;
636{
637  char *msg;
638  static char buf[32];
639
640#ifndef HAVE_SYS_ERRLIST
641
642  if (error_names == NULL)
643    {
644      init_error_tables ();
645    }
646
647#endif
648
649  if ((errnoval < 0) || (errnoval >= sys_nerr))
650    {
651#ifdef EVMSERR
652      if (errnoval == evmserr.value)
653	msg = evmserr.msg;
654      else
655#endif
656      /* Out of range, just return NULL */
657      msg = NULL;
658    }
659  else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
660    {
661      /* In range, but no sys_errlist or no entry at this index. */
662      sprintf (buf, "Error %d", errnoval);
663      msg = buf;
664    }
665  else
666    {
667      /* In range, and a valid message.  Just return the message. */
668      msg = (char *) sys_errlist[errnoval];
669    }
670
671  return (msg);
672}
673
674#endif	/* ! HAVE_STRERROR */
675
676
677/*
678
679NAME
680
681	strerrno -- map an error number to a symbolic name string
682
683SYNOPSIS
684
685	const char *strerrno (int errnoval)
686
687DESCRIPTION
688
689	Given an error number returned from a system call (typically
690	returned in errno), returns a pointer to a string containing the
691	symbolic name of that error number, as found in <errno.h>.
692
693	If the supplied error number is within the valid range of indices
694	for symbolic names, but no name is available for the particular
695	error number, then returns the string "Error NUM", where NUM is
696	the error number.
697
698	If the supplied error number is not within the range of valid
699	indices, then returns NULL.
700
701BUGS
702
703	The contents of the location pointed to are only guaranteed to be
704	valid until the next call to strerrno.
705
706*/
707
708const char *
709strerrno (errnoval)
710  int errnoval;
711{
712  const char *name;
713  static char buf[32];
714
715  if (error_names == NULL)
716    {
717      init_error_tables ();
718    }
719
720  if ((errnoval < 0) || (errnoval >= num_error_names))
721    {
722#ifdef EVMSERR
723      if (errnoval == evmserr.value)
724	name = evmserr.name;
725      else
726#endif
727      /* Out of range, just return NULL */
728      name = NULL;
729    }
730  else if ((error_names == NULL) || (error_names[errnoval] == NULL))
731    {
732      /* In range, but no error_names or no entry at this index. */
733      sprintf (buf, "Error %d", errnoval);
734      name = (const char *) buf;
735    }
736  else
737    {
738      /* In range, and a valid name.  Just return the name. */
739      name = error_names[errnoval];
740    }
741
742  return (name);
743}
744
745/*
746
747NAME
748
749	strtoerrno -- map a symbolic errno name to a numeric value
750
751SYNOPSIS
752
753	int strtoerrno (char *name)
754
755DESCRIPTION
756
757	Given the symbolic name of a error number, map it to an errno value.
758	If no translation is found, returns 0.
759
760*/
761
762int
763strtoerrno (name)
764     const char *name;
765{
766  int errnoval = 0;
767
768  if (name != NULL)
769    {
770      if (error_names == NULL)
771	{
772	  init_error_tables ();
773	}
774      for (errnoval = 0; errnoval < num_error_names; errnoval++)
775	{
776	  if ((error_names[errnoval] != NULL) &&
777	      (strcmp (name, error_names[errnoval]) == 0))
778	    {
779	      break;
780	    }
781	}
782      if (errnoval == num_error_names)
783	{
784#ifdef EVMSERR
785	  if (strcmp (name, evmserr.name) == 0)
786	    errnoval = evmserr.value;
787	  else
788#endif
789	  errnoval = 0;
790	}
791    }
792  return (errnoval);
793}
794
795
796/* A simple little main that does nothing but print all the errno translations
797   if MAIN is defined and this file is compiled and linked. */
798
799#ifdef MAIN
800
801#include <stdio.h>
802
803int
804main ()
805{
806  int errn;
807  int errnmax;
808  const char *name;
809  char *msg;
810  char *strerror ();
811
812  errnmax = errno_max ();
813  printf ("%d entries in names table.\n", num_error_names);
814  printf ("%d entries in messages table.\n", sys_nerr);
815  printf ("%d is max useful index.\n", errnmax);
816
817  /* Keep printing values until we get to the end of *both* tables, not
818     *either* table.  Note that knowing the maximum useful index does *not*
819     relieve us of the responsibility of testing the return pointer for
820     NULL. */
821
822  for (errn = 0; errn <= errnmax; errn++)
823    {
824      name = strerrno (errn);
825      name = (name == NULL) ? "<NULL>" : name;
826      msg = strerror (errn);
827      msg = (msg == NULL) ? "<NULL>" : msg;
828      printf ("%-4d%-18s%s\n", errn, name, msg);
829    }
830
831  return 0;
832}
833
834#endif
835