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