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