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