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