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