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