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