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
33 extern PTR malloc ();
34 #endif
35 
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #else
39 extern PTR memset ();
40 #endif
41 
42 #ifndef MAX
43 #  define MAX(a,b) ((a) > (b) ? (a) : (b))
44 #endif
45 
46 static 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 
59 struct 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 
74 static 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", "Cannot 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[].  */
445 static 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 
452 static const char **error_names;
453 static 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__
467 static int sys_nerr;
468 static const char **sys_errlist;
469 
470 #else
471 
472 
473 #ifndef sys_nerr
474 extern int sys_nerr;
475 #endif
476 #ifndef sys_errlist
477 extern char *sys_errlist[];
478 #endif
479 
480 #endif
481 
482 /*
483 
484 NAME
485 
486 	init_error_tables -- initialize the name and message tables
487 
488 SYNOPSIS
489 
490 	static void init_error_tables ();
491 
492 DESCRIPTION
493 
494 	Using the error_table, which is initialized at compile time, generate
495 	the error_names and the sys_errlist (if needed) tables, which are
496 	indexed at runtime by a specific errno value.
497 
498 BUGS
499 
500 	The initialization of the tables may fail under low memory conditions,
501 	in which case we don't do anything particularly useful, but we don't
502 	bomb either.  Who knows, it might succeed at a later point if we free
503 	some memory in the meantime.  In any case, the other routines know
504 	how to deal with lack of a table after trying to initialize it.  This
505 	may or may not be considered to be a bug, that we don't specifically
506 	warn about this particular failure mode.
507 
508 */
509 
510 static void
511 init_error_tables (void)
512 {
513   const struct error_info *eip;
514   int nbytes;
515 
516   /* If we haven't already scanned the error_table once to find the maximum
517      errno value, then go find it now. */
518 
519   if (num_error_names == 0)
520     {
521       for (eip = error_table; eip -> name != NULL; eip++)
522 	{
523 	  if (eip -> value >= num_error_names)
524 	    {
525 	      num_error_names = eip -> value + 1;
526 	    }
527 	}
528     }
529 
530   /* Now attempt to allocate the error_names table, zero it out, and then
531      initialize it from the statically initialized error_table. */
532 
533   if (error_names == NULL)
534     {
535       nbytes = num_error_names * sizeof (char *);
536       if ((error_names = (const char **) malloc (nbytes)) != NULL)
537 	{
538 	  memset (error_names, 0, nbytes);
539 	  for (eip = error_table; eip -> name != NULL; eip++)
540 	    {
541 	      error_names[eip -> value] = eip -> name;
542 	    }
543 	}
544     }
545 
546 #ifndef HAVE_SYS_ERRLIST
547 
548   /* Now attempt to allocate the sys_errlist table, zero it out, and then
549      initialize it from the statically initialized error_table. */
550 
551   if (sys_errlist == NULL)
552     {
553       nbytes = num_error_names * sizeof (char *);
554       if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
555 	{
556 	  memset (sys_errlist, 0, nbytes);
557 	  sys_nerr = num_error_names;
558 	  for (eip = error_table; eip -> name != NULL; eip++)
559 	    {
560 	      sys_errlist[eip -> value] = eip -> msg;
561 	    }
562 	}
563     }
564 
565 #endif
566 
567 }
568 
569 /*
570 
571 
572 @deftypefn Extension int errno_max (void)
573 
574 Returns the maximum @code{errno} value for which a corresponding
575 symbolic name or message is available.  Note that in the case where we
576 use the @code{sys_errlist} supplied by the system, it is possible for
577 there to be more symbolic names than messages, or vice versa.  In
578 fact, the manual page for @code{perror(3C)} explicitly warns that one
579 should check the size of the table (@code{sys_nerr}) before indexing
580 it, since new error codes may be added to the system before they are
581 added to the table.  Thus @code{sys_nerr} might be smaller than value
582 implied by the largest @code{errno} value defined in @code{<errno.h>}.
583 
584 We return the maximum value that can be used to obtain a meaningful
585 symbolic name or message.
586 
587 @end deftypefn
588 
589 */
590 
591 int
592 errno_max (void)
593 {
594   int maxsize;
595 
596   if (error_names == NULL)
597     {
598       init_error_tables ();
599     }
600   maxsize = MAX (sys_nerr, num_error_names);
601   return (maxsize - 1);
602 }
603 
604 #ifndef HAVE_STRERROR
605 
606 /*
607 
608 @deftypefn Supplemental char* strerror (int @var{errnoval})
609 
610 Maps an @code{errno} number to an error message string, the contents
611 of which are implementation defined.  On systems which have the
612 external variables @code{sys_nerr} and @code{sys_errlist}, these
613 strings will be the same as the ones used by @code{perror}.
614 
615 If the supplied error number is within the valid range of indices for
616 the @code{sys_errlist}, but no message is available for the particular
617 error number, then returns the string @samp{Error @var{num}}, where
618 @var{num} is the error number.
619 
620 If the supplied error number is not a valid index into
621 @code{sys_errlist}, returns @code{NULL}.
622 
623 The returned string is only guaranteed to be valid only until the
624 next call to @code{strerror}.
625 
626 @end deftypefn
627 
628 */
629 
630 char *
631 strerror (int errnoval)
632 {
633   const char *msg;
634   static char buf[32];
635 
636 #ifndef HAVE_SYS_ERRLIST
637 
638   if (error_names == NULL)
639     {
640       init_error_tables ();
641     }
642 
643 #endif
644 
645   if ((errnoval < 0) || (errnoval >= sys_nerr))
646     {
647 #ifdef EVMSERR
648       if (errnoval == evmserr.value)
649 	msg = evmserr.msg;
650       else
651 #endif
652       /* Out of range, just return NULL */
653       msg = NULL;
654     }
655   else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
656     {
657       /* In range, but no sys_errlist or no entry at this index. */
658       sprintf (buf, "Error %d", errnoval);
659       msg = buf;
660     }
661   else
662     {
663       /* In range, and a valid message.  Just return the message. */
664       msg = (char *) sys_errlist[errnoval];
665     }
666 
667   return (msg);
668 }
669 
670 #endif	/* ! HAVE_STRERROR */
671 
672 
673 /*
674 
675 @deftypefn Replacement {const char*} strerrno (int @var{errnum})
676 
677 Given an error number returned from a system call (typically returned
678 in @code{errno}), returns a pointer to a string containing the
679 symbolic name of that error number, as found in @code{<errno.h>}.
680 
681 If the supplied error number is within the valid range of indices for
682 symbolic names, but no name is available for the particular error
683 number, then returns the string @samp{Error @var{num}}, where @var{num}
684 is the error number.
685 
686 If the supplied error number is not within the range of valid
687 indices, then returns @code{NULL}.
688 
689 The contents of the location pointed to are only guaranteed to be
690 valid until the next call to @code{strerrno}.
691 
692 @end deftypefn
693 
694 */
695 
696 const char *
697 strerrno (int errnoval)
698 {
699   const char *name;
700   static char buf[32];
701 
702   if (error_names == NULL)
703     {
704       init_error_tables ();
705     }
706 
707   if ((errnoval < 0) || (errnoval >= num_error_names))
708     {
709 #ifdef EVMSERR
710       if (errnoval == evmserr.value)
711 	name = evmserr.name;
712       else
713 #endif
714       /* Out of range, just return NULL */
715       name = NULL;
716     }
717   else if ((error_names == NULL) || (error_names[errnoval] == NULL))
718     {
719       /* In range, but no error_names or no entry at this index. */
720       sprintf (buf, "Error %d", errnoval);
721       name = (const char *) buf;
722     }
723   else
724     {
725       /* In range, and a valid name.  Just return the name. */
726       name = error_names[errnoval];
727     }
728 
729   return (name);
730 }
731 
732 /*
733 
734 @deftypefn Extension int strtoerrno (const char *@var{name})
735 
736 Given the symbolic name of a error number (e.g., @code{EACCES}), map it
737 to an errno value.  If no translation is found, returns 0.
738 
739 @end deftypefn
740 
741 */
742 
743 int
744 strtoerrno (const char *name)
745 {
746   int errnoval = 0;
747 
748   if (name != NULL)
749     {
750       if (error_names == NULL)
751 	{
752 	  init_error_tables ();
753 	}
754       for (errnoval = 0; errnoval < num_error_names; errnoval++)
755 	{
756 	  if ((error_names[errnoval] != NULL) &&
757 	      (strcmp (name, error_names[errnoval]) == 0))
758 	    {
759 	      break;
760 	    }
761 	}
762       if (errnoval == num_error_names)
763 	{
764 #ifdef EVMSERR
765 	  if (strcmp (name, evmserr.name) == 0)
766 	    errnoval = evmserr.value;
767 	  else
768 #endif
769 	  errnoval = 0;
770 	}
771     }
772   return (errnoval);
773 }
774 
775 
776 /* A simple little main that does nothing but print all the errno translations
777    if MAIN is defined and this file is compiled and linked. */
778 
779 #ifdef MAIN
780 
781 #include <stdio.h>
782 
783 int
784 main (void)
785 {
786   int errn;
787   int errnmax;
788   const char *name;
789   const char *msg;
790   char *strerror ();
791 
792   errnmax = errno_max ();
793   printf ("%d entries in names table.\n", num_error_names);
794   printf ("%d entries in messages table.\n", sys_nerr);
795   printf ("%d is max useful index.\n", errnmax);
796 
797   /* Keep printing values until we get to the end of *both* tables, not
798      *either* table.  Note that knowing the maximum useful index does *not*
799      relieve us of the responsibility of testing the return pointer for
800      NULL. */
801 
802   for (errn = 0; errn <= errnmax; errn++)
803     {
804       name = strerrno (errn);
805       name = (name == NULL) ? "<NULL>" : name;
806       msg = strerror (errn);
807       msg = (msg == NULL) ? "<NULL>" : msg;
808       printf ("%-4d%-18s%s\n", errn, name, msg);
809     }
810 
811   return 0;
812 }
813 
814 #endif
815