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