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