160405Selan /* Extended support for using errno values.
260405Selan Copyright (C) 1992 Free Software Foundation, Inc.
360405Selan Written by Fred Fish. fnf@cygnus.com
460405Selan
560405Selan This file is part of the libiberty library.
660405Selan Libiberty is free software; you can redistribute it and/or
760405Selan modify it under the terms of the GNU Library General Public
860405Selan License as published by the Free Software Foundation; either
960405Selan version 2 of the License, or (at your option) any later version.
1060405Selan
1160405Selan Libiberty is distributed in the hope that it will be useful,
1260405Selan but WITHOUT ANY WARRANTY; without even the implied warranty of
1360405Selan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1460405Selan Library General Public License for more details.
1560405Selan
1660405Selan You should have received a copy of the GNU Library General Public
1760405Selan License along with libiberty; see the file COPYING.LIB. If
1860405Selan not, write to the Free Software Foundation, Inc., 675 Mass Ave,
1960405Selan Cambridge, MA 02139, USA. */
2060405Selan
2160405Selan #include "config.h"
2260405Selan
2360405Selan #include <stdio.h>
2460405Selan #ifndef NEED_sys_errlist
2560405Selan /* Note that errno.h might declare sys_errlist in a way that the
2660405Selan * compiler might consider incompatible with our later declaration,
2760405Selan * perhaps by using const attributes. So we hide the declaration
2860405Selan * in errno.h (if any) using a macro. */
2960405Selan #define sys_errlist sys_errlist__
3060405Selan #endif
3160405Selan #include <errno.h>
3260405Selan #ifndef NEED_sys_errlist
3360405Selan #undef sys_errlist
3460405Selan #endif
3560405Selan
3660405Selan /* Routines imported from standard C runtime libraries. */
3760405Selan
3860405Selan #ifdef __STDC__
3960405Selan #include <stddef.h>
4060405Selan extern void *malloc (size_t size); /* 4.10.3.3 */
4160405Selan extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
4260405Selan #else /* !__STDC__ */
4360405Selan extern char *malloc (); /* Standard memory allocater */
4460405Selan extern char *memset ();
4560405Selan #endif /* __STDC__ */
4660405Selan
4760405Selan #ifndef NULL
4860405Selan # ifdef __STDC__
4960405Selan # define NULL (void *) 0
5060405Selan # else
5160405Selan # define NULL 0
5260405Selan # endif
5360405Selan #endif
5460405Selan
5560405Selan #ifndef MAX
5660405Selan # define MAX(a,b) ((a) > (b) ? (a) : (b))
5760405Selan #endif
5860405Selan
5960405Selan /* Translation table for errno values. See intro(2) in most UNIX systems
6060405Selan Programmers Reference Manuals.
6160405Selan
6260405Selan Note that this table is generally only accessed when it is used at runtime
6360405Selan to initialize errno name and message tables that are indexed by errno
6460405Selan value.
6560405Selan
6660405Selan Not all of these errnos will exist on all systems. This table is the only
6760405Selan thing that should have to be updated as new error numbers are introduced.
6860405Selan It's sort of ugly, but at least its portable. */
6960405Selan
7060405Selan static struct error_info
7160405Selan {
7260405Selan int value; /* The numeric value from <errno.h> */
7360405Selan char *name; /* The equivalent symbolic value */
7460405Selan char *msg; /* Short message about this value */
7560405Selan } error_table[] =
7660405Selan {
7760405Selan #if defined (EPERM)
7860405Selan EPERM, "EPERM", "Not owner",
7960405Selan #endif
8060405Selan #if defined (ENOENT)
8160405Selan ENOENT, "ENOENT", "No such file or directory",
8260405Selan #endif
8360405Selan #if defined (ESRCH)
8460405Selan ESRCH, "ESRCH", "No such process",
8560405Selan #endif
8660405Selan #if defined (EINTR)
8760405Selan EINTR, "EINTR", "Interrupted system call",
8860405Selan #endif
8960405Selan #if defined (EIO)
9060405Selan EIO, "EIO", "I/O error",
9160405Selan #endif
9260405Selan #if defined (ENXIO)
9360405Selan ENXIO, "ENXIO", "No such device or address",
9460405Selan #endif
9560405Selan #if defined (E2BIG)
9660405Selan E2BIG, "E2BIG", "Arg list too long",
9760405Selan #endif
9860405Selan #if defined (ENOEXEC)
9960405Selan ENOEXEC, "ENOEXEC", "Exec format error",
10060405Selan #endif
10160405Selan #if defined (EBADF)
10260405Selan EBADF, "EBADF", "Bad file number",
10360405Selan #endif
10460405Selan #if defined (ECHILD)
10560405Selan ECHILD, "ECHILD", "No child processes",
10660405Selan #endif
10760405Selan #if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
10860405Selan EWOULDBLOCK, "EWOULDBLOCK", "Operation would block",
10960405Selan #endif
11060405Selan #if defined (EAGAIN)
11160405Selan EAGAIN, "EAGAIN", "No more processes",
11260405Selan #endif
11360405Selan #if defined (ENOMEM)
11460405Selan ENOMEM, "ENOMEM", "Not enough space",
11560405Selan #endif
11660405Selan #if defined (EACCES)
11760405Selan EACCES, "EACCES", "Permission denied",
11860405Selan #endif
11960405Selan #if defined (EFAULT)
12060405Selan EFAULT, "EFAULT", "Bad address",
12160405Selan #endif
12260405Selan #if defined (ENOTBLK)
12360405Selan ENOTBLK, "ENOTBLK", "Block device required",
12460405Selan #endif
12560405Selan #if defined (EBUSY)
12660405Selan EBUSY, "EBUSY", "Device busy",
12760405Selan #endif
12860405Selan #if defined (EEXIST)
12960405Selan EEXIST, "EEXIST", "File exists",
13060405Selan #endif
13160405Selan #if defined (EXDEV)
13260405Selan EXDEV, "EXDEV", "Cross-device link",
13360405Selan #endif
13460405Selan #if defined (ENODEV)
13560405Selan ENODEV, "ENODEV", "No such device",
13660405Selan #endif
13760405Selan #if defined (ENOTDIR)
13860405Selan ENOTDIR, "ENOTDIR", "Not a directory",
13960405Selan #endif
14060405Selan #if defined (EISDIR)
14160405Selan EISDIR, "EISDIR", "Is a directory",
14260405Selan #endif
14360405Selan #if defined (EINVAL)
14460405Selan EINVAL, "EINVAL", "Invalid argument",
14560405Selan #endif
14660405Selan #if defined (ENFILE)
14760405Selan ENFILE, "ENFILE", "File table overflow",
14860405Selan #endif
14960405Selan #if defined (EMFILE)
15060405Selan EMFILE, "EMFILE", "Too many open files",
15160405Selan #endif
15260405Selan #if defined (ENOTTY)
15360405Selan ENOTTY, "ENOTTY", "Not a typewriter",
15460405Selan #endif
15560405Selan #if defined (ETXTBSY)
15660405Selan ETXTBSY, "ETXTBSY", "Text file busy",
15760405Selan #endif
15860405Selan #if defined (EFBIG)
15960405Selan EFBIG, "EFBIG", "File too large",
16060405Selan #endif
16160405Selan #if defined (ENOSPC)
16260405Selan ENOSPC, "ENOSPC", "No space left on device",
16360405Selan #endif
16460405Selan #if defined (ESPIPE)
16560405Selan ESPIPE, "ESPIPE", "Illegal seek",
16660405Selan #endif
16760405Selan #if defined (EROFS)
16860405Selan EROFS, "EROFS", "Read-only file system",
16960405Selan #endif
17060405Selan #if defined (EMLINK)
17160405Selan EMLINK, "EMLINK", "Too many links",
17260405Selan #endif
17360405Selan #if defined (EPIPE)
17460405Selan EPIPE, "EPIPE", "Broken pipe",
17560405Selan #endif
17660405Selan #if defined (EDOM)
17760405Selan EDOM, "EDOM", "Math argument out of domain of func",
17860405Selan #endif
17960405Selan #if defined (ERANGE)
18060405Selan ERANGE, "ERANGE", "Math result not representable",
18160405Selan #endif
18260405Selan #if defined (ENOMSG)
18360405Selan ENOMSG, "ENOMSG", "No message of desired type",
18460405Selan #endif
18560405Selan #if defined (EIDRM)
18660405Selan EIDRM, "EIDRM", "Identifier removed",
18760405Selan #endif
18860405Selan #if defined (ECHRNG)
18960405Selan ECHRNG, "ECHRNG", "Channel number out of range",
19060405Selan #endif
19160405Selan #if defined (EL2NSYNC)
19260405Selan EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized",
19360405Selan #endif
19460405Selan #if defined (EL3HLT)
19560405Selan EL3HLT, "EL3HLT", "Level 3 halted",
19660405Selan #endif
19760405Selan #if defined (EL3RST)
19860405Selan EL3RST, "EL3RST", "Level 3 reset",
19960405Selan #endif
20060405Selan #if defined (ELNRNG)
20160405Selan ELNRNG, "ELNRNG", "Link number out of range",
20260405Selan #endif
20360405Selan #if defined (EUNATCH)
20460405Selan EUNATCH, "EUNATCH", "Protocol driver not attached",
20560405Selan #endif
20660405Selan #if defined (ENOCSI)
20760405Selan ENOCSI, "ENOCSI", "No CSI structure available",
20860405Selan #endif
20960405Selan #if defined (EL2HLT)
21060405Selan EL2HLT, "EL2HLT", "Level 2 halted",
21160405Selan #endif
21260405Selan #if defined (EDEADLK)
21360405Selan EDEADLK, "EDEADLK", "Deadlock condition",
21460405Selan #endif
21560405Selan #if defined (ENOLCK)
21660405Selan ENOLCK, "ENOLCK", "No record locks available",
21760405Selan #endif
21860405Selan #if defined (EBADE)
21960405Selan EBADE, "EBADE", "Invalid exchange",
22060405Selan #endif
22160405Selan #if defined (EBADR)
22260405Selan EBADR, "EBADR", "Invalid request descriptor",
22360405Selan #endif
22460405Selan #if defined (EXFULL)
22560405Selan EXFULL, "EXFULL", "Exchange full",
22660405Selan #endif
22760405Selan #if defined (ENOANO)
22860405Selan ENOANO, "ENOANO", "No anode",
22960405Selan #endif
23060405Selan #if defined (EBADRQC)
23160405Selan EBADRQC, "EBADRQC", "Invalid request code",
23260405Selan #endif
23360405Selan #if defined (EBADSLT)
23460405Selan EBADSLT, "EBADSLT", "Invalid slot",
23560405Selan #endif
23660405Selan #if defined (EDEADLOCK)
23760405Selan EDEADLOCK, "EDEADLOCK", "File locking deadlock error",
23860405Selan #endif
23960405Selan #if defined (EBFONT)
24060405Selan EBFONT, "EBFONT", "Bad font file format",
24160405Selan #endif
24260405Selan #if defined (ENOSTR)
24360405Selan ENOSTR, "ENOSTR", "Device not a stream",
24460405Selan #endif
24560405Selan #if defined (ENODATA)
24660405Selan ENODATA, "ENODATA", "No data available",
24760405Selan #endif
24860405Selan #if defined (ETIME)
24960405Selan ETIME, "ETIME", "Timer expired",
25060405Selan #endif
25160405Selan #if defined (ENOSR)
25260405Selan ENOSR, "ENOSR", "Out of streams resources",
25360405Selan #endif
25460405Selan #if defined (ENONET)
25560405Selan ENONET, "ENONET", "Machine is not on the network",
25660405Selan #endif
25760405Selan #if defined (ENOPKG)
25860405Selan ENOPKG, "ENOPKG", "Package not installed",
25960405Selan #endif
26060405Selan #if defined (EREMOTE)
26160405Selan EREMOTE, "EREMOTE", "Object is remote",
26260405Selan #endif
26360405Selan #if defined (ENOLINK)
26460405Selan ENOLINK, "ENOLINK", "Link has been severed",
26560405Selan #endif
26660405Selan #if defined (EADV)
26760405Selan EADV, "EADV", "Advertise error",
26860405Selan #endif
26960405Selan #if defined (ESRMNT)
27060405Selan ESRMNT, "ESRMNT", "Srmount error",
27160405Selan #endif
27260405Selan #if defined (ECOMM)
27360405Selan ECOMM, "ECOMM", "Communication error on send",
27460405Selan #endif
27560405Selan #if defined (EPROTO)
27660405Selan EPROTO, "EPROTO", "Protocol error",
27760405Selan #endif
27860405Selan #if defined (EMULTIHOP)
27960405Selan EMULTIHOP, "EMULTIHOP", "Multihop attempted",
28060405Selan #endif
28160405Selan #if defined (EDOTDOT)
28260405Selan EDOTDOT, "EDOTDOT", "RFS specific error",
28360405Selan #endif
28460405Selan #if defined (EBADMSG)
28560405Selan EBADMSG, "EBADMSG", "Not a data message",
28660405Selan #endif
28760405Selan #if defined (ENAMETOOLONG)
28860405Selan ENAMETOOLONG, "ENAMETOOLONG", "File name too long",
28960405Selan #endif
29060405Selan #if defined (EOVERFLOW)
29160405Selan EOVERFLOW, "EOVERFLOW", "Value too large for defined data type",
29260405Selan #endif
29360405Selan #if defined (ENOTUNIQ)
29460405Selan ENOTUNIQ, "ENOTUNIQ", "Name not unique on network",
29560405Selan #endif
29660405Selan #if defined (EBADFD)
29760405Selan EBADFD, "EBADFD", "File descriptor in bad state",
29860405Selan #endif
29960405Selan #if defined (EREMCHG)
30060405Selan EREMCHG, "EREMCHG", "Remote address changed",
30160405Selan #endif
30260405Selan #if defined (ELIBACC)
30360405Selan ELIBACC, "ELIBACC", "Can not access a needed shared library",
30460405Selan #endif
30560405Selan #if defined (ELIBBAD)
30660405Selan ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library",
30760405Selan #endif
30860405Selan #if defined (ELIBSCN)
30960405Selan ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted",
31060405Selan #endif
31160405Selan #if defined (ELIBMAX)
31260405Selan ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries",
31360405Selan #endif
31460405Selan #if defined (ELIBEXEC)
31560405Selan ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly",
31660405Selan #endif
31760405Selan #if defined (EILSEQ)
31860405Selan EILSEQ, "EILSEQ", "Illegal byte sequence",
31960405Selan #endif
32060405Selan #if defined (ENOSYS)
32160405Selan ENOSYS, "ENOSYS", "Operation not applicable",
32260405Selan #endif
32360405Selan #if defined (ELOOP)
32460405Selan ELOOP, "ELOOP", "Too many symbolic links encountered",
32560405Selan #endif
32660405Selan #if defined (ERESTART)
32760405Selan ERESTART, "ERESTART", "Interrupted system call should be restarted",
32860405Selan #endif
32960405Selan #if defined (ESTRPIPE)
33060405Selan ESTRPIPE, "ESTRPIPE", "Streams pipe error",
33160405Selan #endif
33260405Selan #if defined (ENOTEMPTY)
33360405Selan ENOTEMPTY, "ENOTEMPTY", "Directory not empty",
33460405Selan #endif
33560405Selan #if defined (EUSERS)
33660405Selan EUSERS, "EUSERS", "Too many users",
33760405Selan #endif
33860405Selan #if defined (ENOTSOCK)
33960405Selan ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket",
34060405Selan #endif
34160405Selan #if defined (EDESTADDRREQ)
34260405Selan EDESTADDRREQ, "EDESTADDRREQ", "Destination address required",
34360405Selan #endif
34460405Selan #if defined (EMSGSIZE)
34560405Selan EMSGSIZE, "EMSGSIZE", "Message too long",
34660405Selan #endif
34760405Selan #if defined (EPROTOTYPE)
34860405Selan EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket",
34960405Selan #endif
35060405Selan #if defined (ENOPROTOOPT)
35160405Selan ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available",
35260405Selan #endif
35360405Selan #if defined (EPROTONOSUPPORT)
35460405Selan EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported",
35560405Selan #endif
35660405Selan #if defined (ESOCKTNOSUPPORT)
35760405Selan ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported",
35860405Selan #endif
35960405Selan #if defined (EOPNOTSUPP)
36060405Selan EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint",
36160405Selan #endif
36260405Selan #if defined (EPFNOSUPPORT)
36360405Selan EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported",
36460405Selan #endif
36560405Selan #if defined (EAFNOSUPPORT)
36660405Selan EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol",
36760405Selan #endif
36860405Selan #if defined (EADDRINUSE)
36960405Selan EADDRINUSE, "EADDRINUSE", "Address already in use",
37060405Selan #endif
37160405Selan #if defined (EADDRNOTAVAIL)
37260405Selan EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address",
37360405Selan #endif
37460405Selan #if defined (ENETDOWN)
37560405Selan ENETDOWN, "ENETDOWN", "Network is down",
37660405Selan #endif
37760405Selan #if defined (ENETUNREACH)
37860405Selan ENETUNREACH, "ENETUNREACH", "Network is unreachable",
37960405Selan #endif
38060405Selan #if defined (ENETRESET)
38160405Selan ENETRESET, "ENETRESET", "Network dropped connection because of reset",
38260405Selan #endif
38360405Selan #if defined (ECONNABORTED)
38460405Selan ECONNABORTED, "ECONNABORTED", "Software caused connection abort",
38560405Selan #endif
38660405Selan #if defined (ECONNRESET)
38760405Selan ECONNRESET, "ECONNRESET", "Connection reset by peer",
38860405Selan #endif
38960405Selan #if defined (ENOBUFS)
39060405Selan ENOBUFS, "ENOBUFS", "No buffer space available",
39160405Selan #endif
39260405Selan #if defined (EISCONN)
39360405Selan EISCONN, "EISCONN", "Transport endpoint is already connected",
39460405Selan #endif
39560405Selan #if defined (ENOTCONN)
39660405Selan ENOTCONN, "ENOTCONN", "Transport endpoint is not connected",
39760405Selan #endif
39860405Selan #if defined (ESHUTDOWN)
39960405Selan ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown",
40060405Selan #endif
40160405Selan #if defined (ETOOMANYREFS)
40260405Selan ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice",
40360405Selan #endif
40460405Selan #if defined (ETIMEDOUT)
40560405Selan ETIMEDOUT, "ETIMEDOUT", "Connection timed out",
40660405Selan #endif
40760405Selan #if defined (ECONNREFUSED)
40860405Selan ECONNREFUSED, "ECONNREFUSED", "Connection refused",
40960405Selan #endif
41060405Selan #if defined (EHOSTDOWN)
41160405Selan EHOSTDOWN, "EHOSTDOWN", "Host is down",
41260405Selan #endif
41360405Selan #if defined (EHOSTUNREACH)
41460405Selan EHOSTUNREACH, "EHOSTUNREACH", "No route to host",
41560405Selan #endif
41660405Selan #if defined (EALREADY)
41760405Selan EALREADY, "EALREADY", "Operation already in progress",
41860405Selan #endif
41960405Selan #if defined (EINPROGRESS)
42060405Selan EINPROGRESS, "EINPROGRESS", "Operation now in progress",
42160405Selan #endif
42260405Selan #if defined (ESTALE)
42360405Selan ESTALE, "ESTALE", "Stale NFS file handle",
42460405Selan #endif
42560405Selan #if defined (EUCLEAN)
42660405Selan EUCLEAN, "EUCLEAN", "Structure needs cleaning",
42760405Selan #endif
42860405Selan #if defined (ENOTNAM)
42960405Selan ENOTNAM, "ENOTNAM", "Not a XENIX named type file",
43060405Selan #endif
43160405Selan #if defined (ENAVAIL)
43260405Selan ENAVAIL, "ENAVAIL", "No XENIX semaphores available",
43360405Selan #endif
43460405Selan #if defined (EISNAM)
43560405Selan EISNAM, "EISNAM", "Is a named type file",
43660405Selan #endif
43760405Selan #if defined (EREMOTEIO)
43860405Selan EREMOTEIO, "EREMOTEIO", "Remote I/O error",
43960405Selan #endif
44060405Selan 0, NULL, NULL
44160405Selan };
44260405Selan
44360405Selan /* Translation table allocated and initialized at runtime. Indexed by the
44460405Selan errno value to find the equivalent symbolic value. */
44560405Selan
44660405Selan static char **error_names;
44760405Selan static int num_error_names = 0;
44860405Selan
44960405Selan /* Translation table allocated and initialized at runtime, if it does not
45060405Selan already exist in the host environment. Indexed by the errno value to find
45160405Selan the descriptive string.
45260405Selan
45360405Selan We don't export it for use in other modules because even though it has the
45460405Selan same name, it differs from other implementations in that it is dynamically
45560405Selan initialized rather than statically initialized. */
45660405Selan
457*60406Selan #ifdef notdef
45860405Selan #ifdef NEED_sys_errlist
45960405Selan
46060405Selan static int sys_nerr;
46160405Selan static char **sys_errlist;
46260405Selan
46360405Selan #else
46460405Selan
46560405Selan extern int sys_nerr;
46660405Selan extern char *sys_errlist[];
46760405Selan
46860405Selan #endif
469*60406Selan #endif
47060405Selan
47160405Selan
47260405Selan /*
47360405Selan
47460405Selan NAME
47560405Selan
47660405Selan init_error_tables -- initialize the name and message tables
47760405Selan
47860405Selan SYNOPSIS
47960405Selan
48060405Selan static void init_error_tables ();
48160405Selan
48260405Selan DESCRIPTION
48360405Selan
48460405Selan Using the error_table, which is initialized at compile time, generate
48560405Selan the error_names and the sys_errlist (if needed) tables, which are
48660405Selan indexed at runtime by a specific errno value.
48760405Selan
48860405Selan BUGS
48960405Selan
49060405Selan The initialization of the tables may fail under low memory conditions,
49160405Selan in which case we don't do anything particularly useful, but we don't
49260405Selan bomb either. Who knows, it might succeed at a later point if we free
49360405Selan some memory in the meantime. In any case, the other routines know
49460405Selan how to deal with lack of a table after trying to initialize it. This
49560405Selan may or may not be considered to be a bug, that we don't specifically
49660405Selan warn about this particular failure mode.
49760405Selan
49860405Selan */
49960405Selan
50060405Selan static void
init_error_tables()50160405Selan init_error_tables ()
50260405Selan {
50360405Selan struct error_info *eip;
50460405Selan int nbytes;
50560405Selan
50660405Selan /* If we haven't already scanned the error_table once to find the maximum
50760405Selan errno value, then go find it now. */
50860405Selan
50960405Selan if (num_error_names == 0)
51060405Selan {
51160405Selan for (eip = error_table; eip -> name != NULL; eip++)
51260405Selan {
51360405Selan if (eip -> value >= num_error_names)
51460405Selan {
51560405Selan num_error_names = eip -> value + 1;
51660405Selan }
51760405Selan }
51860405Selan }
51960405Selan
52060405Selan /* Now attempt to allocate the error_names table, zero it out, and then
52160405Selan initialize it from the statically initialized error_table. */
52260405Selan
52360405Selan if (error_names == NULL)
52460405Selan {
52560405Selan nbytes = num_error_names * sizeof (char *);
52660405Selan if ((error_names = (char **) malloc (nbytes)) != NULL)
52760405Selan {
52860405Selan memset (error_names, 0, nbytes);
52960405Selan for (eip = error_table; eip -> name != NULL; eip++)
53060405Selan {
53160405Selan error_names[eip -> value] = eip -> name;
53260405Selan }
53360405Selan }
53460405Selan }
53560405Selan
53660405Selan #ifdef NEED_sys_errlist
53760405Selan
53860405Selan /* Now attempt to allocate the sys_errlist table, zero it out, and then
53960405Selan initialize it from the statically initialized error_table. */
54060405Selan
54160405Selan if (sys_errlist == NULL)
54260405Selan {
54360405Selan nbytes = num_error_names * sizeof (char *);
54460405Selan if ((sys_errlist = (char **) malloc (nbytes)) != NULL)
54560405Selan {
54660405Selan memset (sys_errlist, 0, nbytes);
54760405Selan sys_nerr = num_error_names;
54860405Selan for (eip = error_table; eip -> name != NULL; eip++)
54960405Selan {
55060405Selan sys_errlist[eip -> value] = eip -> msg;
55160405Selan }
55260405Selan }
55360405Selan }
55460405Selan
55560405Selan #endif
55660405Selan
55760405Selan }
55860405Selan
55960405Selan /*
56060405Selan
56160405Selan NAME
56260405Selan
56360405Selan errno_max -- return the max errno value
56460405Selan
56560405Selan SYNOPSIS
56660405Selan
56760405Selan int errno_max ();
56860405Selan
56960405Selan DESCRIPTION
57060405Selan
57160405Selan Returns the maximum errno value for which a corresponding symbolic
57260405Selan name or message is available. Note that in the case where
57360405Selan we use the sys_errlist supplied by the system, it is possible for
57460405Selan there to be more symbolic names than messages, or vice versa.
57560405Selan In fact, the manual page for perror(3C) explicitly warns that one
57660405Selan should check the size of the table (sys_nerr) before indexing it,
57760405Selan since new error codes may be added to the system before they are
57860405Selan added to the table. Thus sys_nerr might be smaller than value
57960405Selan implied by the largest errno value defined in <errno.h>.
58060405Selan
58160405Selan We return the maximum value that can be used to obtain a meaningful
58260405Selan symbolic name or message.
58360405Selan
58460405Selan */
58560405Selan
58660405Selan int
errno_max()58760405Selan errno_max ()
58860405Selan {
58960405Selan int maxsize;
59060405Selan
59160405Selan if (error_names == NULL)
59260405Selan {
59360405Selan init_error_tables ();
59460405Selan }
59560405Selan maxsize = MAX (sys_nerr, num_error_names);
59660405Selan return (maxsize - 1);
59760405Selan }
59860405Selan
59960405Selan #ifdef NEED_strerror
60060405Selan
60160405Selan /*
60260405Selan
60360405Selan NAME
60460405Selan
60560405Selan strerror -- map an error number to an error message string
60660405Selan
60760405Selan SYNOPSIS
60860405Selan
60960405Selan char *strerror (int errnoval)
61060405Selan
61160405Selan DESCRIPTION
61260405Selan
61360405Selan Maps an errno number to an error message string, the contents of
61460405Selan which are implementation defined. On systems which have the external
61560405Selan variables sys_nerr and sys_errlist, these strings will be the same
61660405Selan as the ones used by perror().
61760405Selan
61860405Selan If the supplied error number is within the valid range of indices
61960405Selan for the sys_errlist, but no message is available for the particular
62060405Selan error number, then returns the string "Error NUM", where NUM is the
62160405Selan error number.
62260405Selan
62360405Selan If the supplied error number is not a valid index into sys_errlist,
62460405Selan returns NULL.
62560405Selan
62660405Selan The returned string is only guaranteed to be valid only until the
62760405Selan next call to strerror.
62860405Selan
62960405Selan */
63060405Selan
63160405Selan char *
strerror(errnoval)63260405Selan strerror (errnoval)
63360405Selan int errnoval;
63460405Selan {
63560405Selan char *msg;
63660405Selan static char buf[32];
63760405Selan
63860405Selan #ifdef NEED_sys_errlist
63960405Selan
64060405Selan if (error_names == NULL)
64160405Selan {
64260405Selan init_error_tables ();
64360405Selan }
64460405Selan
64560405Selan #endif
64660405Selan
64760405Selan if ((errnoval < 0) || (errnoval >= sys_nerr))
64860405Selan {
64960405Selan /* Out of range, just return NULL */
65060405Selan msg = NULL;
65160405Selan }
65260405Selan else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
65360405Selan {
65460405Selan /* In range, but no sys_errlist or no entry at this index. */
65560405Selan sprintf (buf, "Error %d", errnoval);
65660405Selan msg = buf;
65760405Selan }
65860405Selan else
65960405Selan {
66060405Selan /* In range, and a valid message. Just return the message. */
66160405Selan msg = sys_errlist[errnoval];
66260405Selan }
66360405Selan
66460405Selan return (msg);
66560405Selan }
66660405Selan
66760405Selan #endif /* NEED_strerror */
66860405Selan
66960405Selan
67060405Selan /*
67160405Selan
67260405Selan NAME
67360405Selan
67460405Selan strerrno -- map an error number to a symbolic name string
67560405Selan
67660405Selan SYNOPSIS
67760405Selan
67860405Selan char *strerrno (int errnoval)
67960405Selan
68060405Selan DESCRIPTION
68160405Selan
68260405Selan Given an error number returned from a system call (typically
68360405Selan returned in errno), returns a pointer to a string containing the
68460405Selan symbolic name of that error number, as found in <errno.h>.
68560405Selan
68660405Selan If the supplied error number is within the valid range of indices
68760405Selan for symbolic names, but no name is available for the particular
68860405Selan error number, then returns the string "Error NUM", where NUM is
68960405Selan the error number.
69060405Selan
69160405Selan If the supplied error number is not within the range of valid
69260405Selan indices, then returns NULL.
69360405Selan
69460405Selan BUGS
69560405Selan
69660405Selan The contents of the location pointed to are only guaranteed to be
69760405Selan valid until the next call to strerrno.
69860405Selan
69960405Selan */
70060405Selan
70160405Selan char *
strerrno(errnoval)70260405Selan strerrno (errnoval)
70360405Selan int errnoval;
70460405Selan {
70560405Selan char *name;
70660405Selan static char buf[32];
70760405Selan
70860405Selan if (error_names == NULL)
70960405Selan {
71060405Selan init_error_tables ();
71160405Selan }
71260405Selan
71360405Selan if ((errnoval < 0) || (errnoval >= num_error_names))
71460405Selan {
71560405Selan /* Out of range, just return NULL */
71660405Selan name = NULL;
71760405Selan }
71860405Selan else if ((error_names == NULL) || (error_names[errnoval] == NULL))
71960405Selan {
72060405Selan /* In range, but no error_names or no entry at this index. */
72160405Selan sprintf (buf, "Error %d", errnoval);
72260405Selan name = buf;
72360405Selan }
72460405Selan else
72560405Selan {
72660405Selan /* In range, and a valid name. Just return the name. */
72760405Selan name = error_names[errnoval];
72860405Selan }
72960405Selan
73060405Selan return (name);
73160405Selan }
73260405Selan
73360405Selan /*
73460405Selan
73560405Selan NAME
73660405Selan
73760405Selan strtoerrno -- map a symbolic errno name to a numeric value
73860405Selan
73960405Selan SYNOPSIS
74060405Selan
74160405Selan int strtoerrno (char *name)
74260405Selan
74360405Selan DESCRIPTION
74460405Selan
74560405Selan Given the symbolic name of a error number, map it to an errno value.
74660405Selan If no translation is found, returns 0.
74760405Selan
74860405Selan */
74960405Selan
75060405Selan int
strtoerrno(name)75160405Selan strtoerrno (name)
75260405Selan char *name;
75360405Selan {
75460405Selan int errnoval = 0;
75560405Selan
75660405Selan if (name != NULL)
75760405Selan {
75860405Selan if (error_names == NULL)
75960405Selan {
76060405Selan init_error_tables ();
76160405Selan }
76260405Selan for (errnoval = 0; errnoval < num_error_names; errnoval++)
76360405Selan {
76460405Selan if ((error_names[errnoval] != NULL) &&
76560405Selan (strcmp (name, error_names[errnoval]) == 0))
76660405Selan {
76760405Selan break;
76860405Selan }
76960405Selan }
77060405Selan if (errnoval == num_error_names)
77160405Selan {
77260405Selan errnoval = 0;
77360405Selan }
77460405Selan }
77560405Selan return (errnoval);
77660405Selan }
77760405Selan
77860405Selan
77960405Selan /* A simple little main that does nothing but print all the errno translations
78060405Selan if MAIN is defined and this file is compiled and linked. */
78160405Selan
78260405Selan #ifdef MAIN
78360405Selan
main()78460405Selan main ()
78560405Selan {
78660405Selan int errn;
78760405Selan int errnmax;
78860405Selan char *name;
78960405Selan char *msg;
79060405Selan char *strerrno ();
79160405Selan char *strerror ();
79260405Selan
79360405Selan errnmax = errno_max ();
79460405Selan printf ("%d entries in names table.\n", num_error_names);
79560405Selan printf ("%d entries in messages table.\n", sys_nerr);
79660405Selan printf ("%d is max useful index.\n", errnmax);
79760405Selan
79860405Selan /* Keep printing values until we get to the end of *both* tables, not
79960405Selan *either* table. Note that knowing the maximum useful index does *not*
80060405Selan relieve us of the responsibility of testing the return pointer for
80160405Selan NULL. */
80260405Selan
80360405Selan for (errn = 0; errn <= errnmax; errn++)
80460405Selan {
80560405Selan name = strerrno (errn);
80660405Selan name = (name == NULL) ? "<NULL>" : name;
80760405Selan msg = strerror (errn);
80860405Selan msg = (msg == NULL) ? "<NULL>" : msg;
80960405Selan printf ("%-4d%-18s%s\n", errn, name, msg);
81060405Selan }
81160405Selan }
81260405Selan
81360405Selan #endif
814