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