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