133965Sjdp/* Extended support for using errno values.
233965Sjdp   Written by Fred Fish.  fnf@cygnus.com
333965Sjdp   This file is in the public domain.  --Per Bothner.  */
433965Sjdp
533965Sjdp#include "config.h"
633965Sjdp
760484Sobrien#ifdef HAVE_SYS_ERRLIST
833965Sjdp/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
933965Sjdp   might declare sys_errlist in a way that the compiler might consider
1033965Sjdp   incompatible with our later declaration, perhaps by using const
1133965Sjdp   attributes.  So we hide the declaration in errno.h (if any) using a
1233965Sjdp   macro. */
1389857Sobrien#define sys_nerr sys_nerr__
1433965Sjdp#define sys_errlist sys_errlist__
1533965Sjdp#endif
1633965Sjdp
17218822Sdim#include "ansidecl.h"
18218822Sdim#include "libiberty.h"
19218822Sdim
2033965Sjdp#include <stdio.h>
2133965Sjdp#include <errno.h>
2233965Sjdp
2360484Sobrien#ifdef HAVE_SYS_ERRLIST
2489857Sobrien#undef sys_nerr
2533965Sjdp#undef sys_errlist
2633965Sjdp#endif
2733965Sjdp
2833965Sjdp/*  Routines imported from standard C runtime libraries. */
2933965Sjdp
3077298Sobrien#ifdef HAVE_STDLIB_H
3177298Sobrien#include <stdlib.h>
3277298Sobrien#else
3377298Sobrienextern PTR malloc ();
3477298Sobrien#endif
3533965Sjdp
3677298Sobrien#ifdef HAVE_STRING_H
3777298Sobrien#include <string.h>
3877298Sobrien#else
3977298Sobrienextern PTR memset ();
4077298Sobrien#endif
4177298Sobrien
4233965Sjdp#ifndef MAX
4333965Sjdp#  define MAX(a,b) ((a) > (b) ? (a) : (b))
4433965Sjdp#endif
4533965Sjdp
46218822Sdimstatic void init_error_tables (void);
4733965Sjdp
4833965Sjdp/* Translation table for errno values.  See intro(2) in most UNIX systems
4933965Sjdp   Programmers Reference Manuals.
5033965Sjdp
5133965Sjdp   Note that this table is generally only accessed when it is used at runtime
5233965Sjdp   to initialize errno name and message tables that are indexed by errno
5333965Sjdp   value.
5433965Sjdp
5533965Sjdp   Not all of these errnos will exist on all systems.  This table is the only
5633965Sjdp   thing that should have to be updated as new error numbers are introduced.
5733965Sjdp   It's sort of ugly, but at least its portable. */
5833965Sjdp
5933965Sjdpstruct error_info
6033965Sjdp{
6189857Sobrien  const int value;		/* The numeric value from <errno.h> */
6289857Sobrien  const char *const name;	/* The equivalent symbolic value */
6360484Sobrien#ifndef HAVE_SYS_ERRLIST
6489857Sobrien  const char *const msg;	/* Short message about this value */
6533965Sjdp#endif
6633965Sjdp};
6733965Sjdp
6860484Sobrien#ifndef HAVE_SYS_ERRLIST
6933965Sjdp#   define ENTRY(value, name, msg)	{value, name, msg}
7033965Sjdp#else
7133965Sjdp#   define ENTRY(value, name, msg)	{value, name}
7233965Sjdp#endif
7333965Sjdp
7433965Sjdpstatic const struct error_info error_table[] =
7533965Sjdp{
7633965Sjdp#if defined (EPERM)
7733965Sjdp  ENTRY(EPERM, "EPERM", "Not owner"),
7833965Sjdp#endif
7933965Sjdp#if defined (ENOENT)
8033965Sjdp  ENTRY(ENOENT, "ENOENT", "No such file or directory"),
8133965Sjdp#endif
8233965Sjdp#if defined (ESRCH)
8333965Sjdp  ENTRY(ESRCH, "ESRCH", "No such process"),
8433965Sjdp#endif
8533965Sjdp#if defined (EINTR)
8633965Sjdp  ENTRY(EINTR, "EINTR", "Interrupted system call"),
8733965Sjdp#endif
8833965Sjdp#if defined (EIO)
8933965Sjdp  ENTRY(EIO, "EIO", "I/O error"),
9033965Sjdp#endif
9133965Sjdp#if defined (ENXIO)
9233965Sjdp  ENTRY(ENXIO, "ENXIO", "No such device or address"),
9333965Sjdp#endif
9433965Sjdp#if defined (E2BIG)
9533965Sjdp  ENTRY(E2BIG, "E2BIG", "Arg list too long"),
9633965Sjdp#endif
9733965Sjdp#if defined (ENOEXEC)
9833965Sjdp  ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
9933965Sjdp#endif
10033965Sjdp#if defined (EBADF)
10133965Sjdp  ENTRY(EBADF, "EBADF", "Bad file number"),
10233965Sjdp#endif
10333965Sjdp#if defined (ECHILD)
10433965Sjdp  ENTRY(ECHILD, "ECHILD", "No child processes"),
10533965Sjdp#endif
10633965Sjdp#if defined (EWOULDBLOCK)	/* Put before EAGAIN, sometimes aliased */
10733965Sjdp  ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
10833965Sjdp#endif
10933965Sjdp#if defined (EAGAIN)
11033965Sjdp  ENTRY(EAGAIN, "EAGAIN", "No more processes"),
11133965Sjdp#endif
11233965Sjdp#if defined (ENOMEM)
11333965Sjdp  ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
11433965Sjdp#endif
11533965Sjdp#if defined (EACCES)
11633965Sjdp  ENTRY(EACCES, "EACCES", "Permission denied"),
11733965Sjdp#endif
11833965Sjdp#if defined (EFAULT)
11933965Sjdp  ENTRY(EFAULT, "EFAULT", "Bad address"),
12033965Sjdp#endif
12133965Sjdp#if defined (ENOTBLK)
12233965Sjdp  ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
12333965Sjdp#endif
12433965Sjdp#if defined (EBUSY)
12533965Sjdp  ENTRY(EBUSY, "EBUSY", "Device busy"),
12633965Sjdp#endif
12733965Sjdp#if defined (EEXIST)
12833965Sjdp  ENTRY(EEXIST, "EEXIST", "File exists"),
12933965Sjdp#endif
13033965Sjdp#if defined (EXDEV)
13133965Sjdp  ENTRY(EXDEV, "EXDEV", "Cross-device link"),
13233965Sjdp#endif
13333965Sjdp#if defined (ENODEV)
13433965Sjdp  ENTRY(ENODEV, "ENODEV", "No such device"),
13533965Sjdp#endif
13633965Sjdp#if defined (ENOTDIR)
13733965Sjdp  ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
13833965Sjdp#endif
13933965Sjdp#if defined (EISDIR)
14033965Sjdp  ENTRY(EISDIR, "EISDIR", "Is a directory"),
14133965Sjdp#endif
14233965Sjdp#if defined (EINVAL)
14333965Sjdp  ENTRY(EINVAL, "EINVAL", "Invalid argument"),
14433965Sjdp#endif
14533965Sjdp#if defined (ENFILE)
14633965Sjdp  ENTRY(ENFILE, "ENFILE", "File table overflow"),
14733965Sjdp#endif
14833965Sjdp#if defined (EMFILE)
14933965Sjdp  ENTRY(EMFILE, "EMFILE", "Too many open files"),
15033965Sjdp#endif
15133965Sjdp#if defined (ENOTTY)
15233965Sjdp  ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
15333965Sjdp#endif
15433965Sjdp#if defined (ETXTBSY)
15533965Sjdp  ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
15633965Sjdp#endif
15733965Sjdp#if defined (EFBIG)
15833965Sjdp  ENTRY(EFBIG, "EFBIG", "File too large"),
15933965Sjdp#endif
16033965Sjdp#if defined (ENOSPC)
16133965Sjdp  ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
16233965Sjdp#endif
16333965Sjdp#if defined (ESPIPE)
16433965Sjdp  ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
16533965Sjdp#endif
16633965Sjdp#if defined (EROFS)
16733965Sjdp  ENTRY(EROFS, "EROFS", "Read-only file system"),
16833965Sjdp#endif
16933965Sjdp#if defined (EMLINK)
17033965Sjdp  ENTRY(EMLINK, "EMLINK", "Too many links"),
17133965Sjdp#endif
17233965Sjdp#if defined (EPIPE)
17333965Sjdp  ENTRY(EPIPE, "EPIPE", "Broken pipe"),
17433965Sjdp#endif
17533965Sjdp#if defined (EDOM)
17633965Sjdp  ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
17733965Sjdp#endif
17833965Sjdp#if defined (ERANGE)
17933965Sjdp  ENTRY(ERANGE, "ERANGE", "Math result not representable"),
18033965Sjdp#endif
18133965Sjdp#if defined (ENOMSG)
18233965Sjdp  ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
18333965Sjdp#endif
18433965Sjdp#if defined (EIDRM)
18533965Sjdp  ENTRY(EIDRM, "EIDRM", "Identifier removed"),
18633965Sjdp#endif
18733965Sjdp#if defined (ECHRNG)
18833965Sjdp  ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
18933965Sjdp#endif
19033965Sjdp#if defined (EL2NSYNC)
19133965Sjdp  ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
19233965Sjdp#endif
19333965Sjdp#if defined (EL3HLT)
19433965Sjdp  ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
19533965Sjdp#endif
19633965Sjdp#if defined (EL3RST)
19733965Sjdp  ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
19833965Sjdp#endif
19933965Sjdp#if defined (ELNRNG)
20033965Sjdp  ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
20133965Sjdp#endif
20233965Sjdp#if defined (EUNATCH)
20333965Sjdp  ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
20433965Sjdp#endif
20533965Sjdp#if defined (ENOCSI)
20633965Sjdp  ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
20733965Sjdp#endif
20833965Sjdp#if defined (EL2HLT)
20933965Sjdp  ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
21033965Sjdp#endif
21133965Sjdp#if defined (EDEADLK)
21233965Sjdp  ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
21333965Sjdp#endif
21433965Sjdp#if defined (ENOLCK)
21533965Sjdp  ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
21633965Sjdp#endif
21733965Sjdp#if defined (EBADE)
21833965Sjdp  ENTRY(EBADE, "EBADE", "Invalid exchange"),
21933965Sjdp#endif
22033965Sjdp#if defined (EBADR)
22133965Sjdp  ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
22233965Sjdp#endif
22333965Sjdp#if defined (EXFULL)
22433965Sjdp  ENTRY(EXFULL, "EXFULL", "Exchange full"),
22533965Sjdp#endif
22633965Sjdp#if defined (ENOANO)
22733965Sjdp  ENTRY(ENOANO, "ENOANO", "No anode"),
22833965Sjdp#endif
22933965Sjdp#if defined (EBADRQC)
23033965Sjdp  ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
23133965Sjdp#endif
23233965Sjdp#if defined (EBADSLT)
23333965Sjdp  ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
23433965Sjdp#endif
23533965Sjdp#if defined (EDEADLOCK)
23633965Sjdp  ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
23733965Sjdp#endif
23833965Sjdp#if defined (EBFONT)
23933965Sjdp  ENTRY(EBFONT, "EBFONT", "Bad font file format"),
24033965Sjdp#endif
24133965Sjdp#if defined (ENOSTR)
24233965Sjdp  ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
24333965Sjdp#endif
24433965Sjdp#if defined (ENODATA)
24533965Sjdp  ENTRY(ENODATA, "ENODATA", "No data available"),
24633965Sjdp#endif
24733965Sjdp#if defined (ETIME)
24833965Sjdp  ENTRY(ETIME, "ETIME", "Timer expired"),
24933965Sjdp#endif
25033965Sjdp#if defined (ENOSR)
25133965Sjdp  ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
25233965Sjdp#endif
25333965Sjdp#if defined (ENONET)
25433965Sjdp  ENTRY(ENONET, "ENONET", "Machine is not on the network"),
25533965Sjdp#endif
25633965Sjdp#if defined (ENOPKG)
25733965Sjdp  ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
25833965Sjdp#endif
25933965Sjdp#if defined (EREMOTE)
26033965Sjdp  ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
26133965Sjdp#endif
26233965Sjdp#if defined (ENOLINK)
26333965Sjdp  ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
26433965Sjdp#endif
26533965Sjdp#if defined (EADV)
26633965Sjdp  ENTRY(EADV, "EADV", "Advertise error"),
26733965Sjdp#endif
26833965Sjdp#if defined (ESRMNT)
26933965Sjdp  ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
27033965Sjdp#endif
27133965Sjdp#if defined (ECOMM)
27233965Sjdp  ENTRY(ECOMM, "ECOMM", "Communication error on send"),
27333965Sjdp#endif
27433965Sjdp#if defined (EPROTO)
27533965Sjdp  ENTRY(EPROTO, "EPROTO", "Protocol error"),
27633965Sjdp#endif
27733965Sjdp#if defined (EMULTIHOP)
27833965Sjdp  ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
27933965Sjdp#endif
28033965Sjdp#if defined (EDOTDOT)
28133965Sjdp  ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
28233965Sjdp#endif
28333965Sjdp#if defined (EBADMSG)
28433965Sjdp  ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
28533965Sjdp#endif
28633965Sjdp#if defined (ENAMETOOLONG)
28733965Sjdp  ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
28833965Sjdp#endif
28933965Sjdp#if defined (EOVERFLOW)
29033965Sjdp  ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
29133965Sjdp#endif
29233965Sjdp#if defined (ENOTUNIQ)
29333965Sjdp  ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
29433965Sjdp#endif
29533965Sjdp#if defined (EBADFD)
29633965Sjdp  ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
29733965Sjdp#endif
29833965Sjdp#if defined (EREMCHG)
29933965Sjdp  ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
30033965Sjdp#endif
30133965Sjdp#if defined (ELIBACC)
30233965Sjdp  ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
30333965Sjdp#endif
30433965Sjdp#if defined (ELIBBAD)
30533965Sjdp  ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
30633965Sjdp#endif
30733965Sjdp#if defined (ELIBSCN)
30833965Sjdp  ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
30933965Sjdp#endif
31033965Sjdp#if defined (ELIBMAX)
31133965Sjdp  ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
31233965Sjdp#endif
31333965Sjdp#if defined (ELIBEXEC)
31433965Sjdp  ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
31533965Sjdp#endif
31633965Sjdp#if defined (EILSEQ)
31733965Sjdp  ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
31833965Sjdp#endif
31933965Sjdp#if defined (ENOSYS)
32033965Sjdp  ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
32133965Sjdp#endif
32233965Sjdp#if defined (ELOOP)
32333965Sjdp  ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
32433965Sjdp#endif
32533965Sjdp#if defined (ERESTART)
32633965Sjdp  ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
32733965Sjdp#endif
32833965Sjdp#if defined (ESTRPIPE)
32933965Sjdp  ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
33033965Sjdp#endif
33133965Sjdp#if defined (ENOTEMPTY)
33233965Sjdp  ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
33333965Sjdp#endif
33433965Sjdp#if defined (EUSERS)
33533965Sjdp  ENTRY(EUSERS, "EUSERS", "Too many users"),
33633965Sjdp#endif
33733965Sjdp#if defined (ENOTSOCK)
33833965Sjdp  ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
33933965Sjdp#endif
34033965Sjdp#if defined (EDESTADDRREQ)
34133965Sjdp  ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
34233965Sjdp#endif
34333965Sjdp#if defined (EMSGSIZE)
34433965Sjdp  ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
34533965Sjdp#endif
34633965Sjdp#if defined (EPROTOTYPE)
34733965Sjdp  ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
34833965Sjdp#endif
34933965Sjdp#if defined (ENOPROTOOPT)
35033965Sjdp  ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
35133965Sjdp#endif
35233965Sjdp#if defined (EPROTONOSUPPORT)
35333965Sjdp  ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
35433965Sjdp#endif
35533965Sjdp#if defined (ESOCKTNOSUPPORT)
35633965Sjdp  ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
35733965Sjdp#endif
35833965Sjdp#if defined (EOPNOTSUPP)
35933965Sjdp  ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
36033965Sjdp#endif
36133965Sjdp#if defined (EPFNOSUPPORT)
36233965Sjdp  ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
36333965Sjdp#endif
36433965Sjdp#if defined (EAFNOSUPPORT)
36533965Sjdp  ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
36633965Sjdp#endif
36733965Sjdp#if defined (EADDRINUSE)
36833965Sjdp  ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
36933965Sjdp#endif
37033965Sjdp#if defined (EADDRNOTAVAIL)
37133965Sjdp  ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
37233965Sjdp#endif
37333965Sjdp#if defined (ENETDOWN)
37433965Sjdp  ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
37533965Sjdp#endif
37633965Sjdp#if defined (ENETUNREACH)
37733965Sjdp  ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
37833965Sjdp#endif
37933965Sjdp#if defined (ENETRESET)
38033965Sjdp  ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
38133965Sjdp#endif
38233965Sjdp#if defined (ECONNABORTED)
38333965Sjdp  ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
38433965Sjdp#endif
38533965Sjdp#if defined (ECONNRESET)
38633965Sjdp  ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
38733965Sjdp#endif
38833965Sjdp#if defined (ENOBUFS)
38933965Sjdp  ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
39033965Sjdp#endif
39133965Sjdp#if defined (EISCONN)
39233965Sjdp  ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
39333965Sjdp#endif
39433965Sjdp#if defined (ENOTCONN)
39533965Sjdp  ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
39633965Sjdp#endif
39733965Sjdp#if defined (ESHUTDOWN)
39833965Sjdp  ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
39933965Sjdp#endif
40033965Sjdp#if defined (ETOOMANYREFS)
40133965Sjdp  ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
40233965Sjdp#endif
40333965Sjdp#if defined (ETIMEDOUT)
40433965Sjdp  ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
40533965Sjdp#endif
40633965Sjdp#if defined (ECONNREFUSED)
40733965Sjdp  ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
40833965Sjdp#endif
40933965Sjdp#if defined (EHOSTDOWN)
41033965Sjdp  ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
41133965Sjdp#endif
41233965Sjdp#if defined (EHOSTUNREACH)
41333965Sjdp  ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
41433965Sjdp#endif
41533965Sjdp#if defined (EALREADY)
41633965Sjdp  ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
41733965Sjdp#endif
41833965Sjdp#if defined (EINPROGRESS)
41933965Sjdp  ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
42033965Sjdp#endif
42133965Sjdp#if defined (ESTALE)
42233965Sjdp  ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
42333965Sjdp#endif
42433965Sjdp#if defined (EUCLEAN)
42533965Sjdp  ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
42633965Sjdp#endif
42733965Sjdp#if defined (ENOTNAM)
42833965Sjdp  ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
42933965Sjdp#endif
43033965Sjdp#if defined (ENAVAIL)
43133965Sjdp  ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
43233965Sjdp#endif
43333965Sjdp#if defined (EISNAM)
43433965Sjdp  ENTRY(EISNAM, "EISNAM", "Is a named type file"),
43533965Sjdp#endif
43633965Sjdp#if defined (EREMOTEIO)
43733965Sjdp  ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
43833965Sjdp#endif
43933965Sjdp  ENTRY(0, NULL, NULL)
44033965Sjdp};
44133965Sjdp
44233965Sjdp#ifdef EVMSERR
44333965Sjdp/* This is not in the table, because the numeric value of EVMSERR (32767)
44433965Sjdp   lies outside the range of sys_errlist[].  */
44533965Sjdpstatic struct { int value; const char *name, *msg; }
44633965Sjdp  evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
44733965Sjdp#endif
44833965Sjdp
44933965Sjdp/* Translation table allocated and initialized at runtime.  Indexed by the
45033965Sjdp   errno value to find the equivalent symbolic value. */
45133965Sjdp
45233965Sjdpstatic const char **error_names;
45333965Sjdpstatic int num_error_names = 0;
45433965Sjdp
45533965Sjdp/* Translation table allocated and initialized at runtime, if it does not
45633965Sjdp   already exist in the host environment.  Indexed by the errno value to find
45733965Sjdp   the descriptive string.
45833965Sjdp
45933965Sjdp   We don't export it for use in other modules because even though it has the
46033965Sjdp   same name, it differs from other implementations in that it is dynamically
46133965Sjdp   initialized rather than statically initialized. */
46233965Sjdp
46360484Sobrien#ifndef HAVE_SYS_ERRLIST
46433965Sjdp
465130561Sobrien#define sys_nerr sys_nerr__
466130561Sobrien#define sys_errlist sys_errlist__
46733965Sjdpstatic int sys_nerr;
46833965Sjdpstatic const char **sys_errlist;
46933965Sjdp
47033965Sjdp#else
47133965Sjdp
47233965Sjdpextern int sys_nerr;
47333965Sjdpextern char *sys_errlist[];
47433965Sjdp
47533965Sjdp#endif
47633965Sjdp
47733965Sjdp/*
47833965Sjdp
47933965SjdpNAME
48033965Sjdp
48133965Sjdp	init_error_tables -- initialize the name and message tables
48233965Sjdp
48333965SjdpSYNOPSIS
48433965Sjdp
48533965Sjdp	static void init_error_tables ();
48633965Sjdp
48733965SjdpDESCRIPTION
48833965Sjdp
48933965Sjdp	Using the error_table, which is initialized at compile time, generate
49033965Sjdp	the error_names and the sys_errlist (if needed) tables, which are
49133965Sjdp	indexed at runtime by a specific errno value.
49233965Sjdp
49333965SjdpBUGS
49433965Sjdp
49533965Sjdp	The initialization of the tables may fail under low memory conditions,
49633965Sjdp	in which case we don't do anything particularly useful, but we don't
49733965Sjdp	bomb either.  Who knows, it might succeed at a later point if we free
49833965Sjdp	some memory in the meantime.  In any case, the other routines know
49933965Sjdp	how to deal with lack of a table after trying to initialize it.  This
50033965Sjdp	may or may not be considered to be a bug, that we don't specifically
50133965Sjdp	warn about this particular failure mode.
50233965Sjdp
50333965Sjdp*/
50433965Sjdp
50533965Sjdpstatic void
506218822Sdiminit_error_tables (void)
50733965Sjdp{
50833965Sjdp  const struct error_info *eip;
50933965Sjdp  int nbytes;
51033965Sjdp
51133965Sjdp  /* If we haven't already scanned the error_table once to find the maximum
51233965Sjdp     errno value, then go find it now. */
51333965Sjdp
51433965Sjdp  if (num_error_names == 0)
51533965Sjdp    {
51633965Sjdp      for (eip = error_table; eip -> name != NULL; eip++)
51733965Sjdp	{
51833965Sjdp	  if (eip -> value >= num_error_names)
51933965Sjdp	    {
52033965Sjdp	      num_error_names = eip -> value + 1;
52133965Sjdp	    }
52233965Sjdp	}
52333965Sjdp    }
52433965Sjdp
52533965Sjdp  /* Now attempt to allocate the error_names table, zero it out, and then
52633965Sjdp     initialize it from the statically initialized error_table. */
52733965Sjdp
52833965Sjdp  if (error_names == NULL)
52933965Sjdp    {
53033965Sjdp      nbytes = num_error_names * sizeof (char *);
53133965Sjdp      if ((error_names = (const char **) malloc (nbytes)) != NULL)
53233965Sjdp	{
53333965Sjdp	  memset (error_names, 0, nbytes);
53433965Sjdp	  for (eip = error_table; eip -> name != NULL; eip++)
53533965Sjdp	    {
53633965Sjdp	      error_names[eip -> value] = eip -> name;
53733965Sjdp	    }
53833965Sjdp	}
53933965Sjdp    }
54033965Sjdp
54160484Sobrien#ifndef HAVE_SYS_ERRLIST
54233965Sjdp
54333965Sjdp  /* Now attempt to allocate the sys_errlist table, zero it out, and then
54433965Sjdp     initialize it from the statically initialized error_table. */
54533965Sjdp
54633965Sjdp  if (sys_errlist == NULL)
54733965Sjdp    {
54833965Sjdp      nbytes = num_error_names * sizeof (char *);
54933965Sjdp      if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
55033965Sjdp	{
55133965Sjdp	  memset (sys_errlist, 0, nbytes);
55233965Sjdp	  sys_nerr = num_error_names;
55333965Sjdp	  for (eip = error_table; eip -> name != NULL; eip++)
55433965Sjdp	    {
55533965Sjdp	      sys_errlist[eip -> value] = eip -> msg;
55633965Sjdp	    }
55733965Sjdp	}
55833965Sjdp    }
55933965Sjdp
56033965Sjdp#endif
56133965Sjdp
56233965Sjdp}
56333965Sjdp
56433965Sjdp/*
56533965Sjdp
56633965Sjdp
56789857Sobrien@deftypefn Extension int errno_max (void)
56833965Sjdp
56989857SobrienReturns the maximum @code{errno} value for which a corresponding
57089857Sobriensymbolic name or message is available.  Note that in the case where we
57189857Sobrienuse the @code{sys_errlist} supplied by the system, it is possible for
57289857Sobrienthere to be more symbolic names than messages, or vice versa.  In
57389857Sobrienfact, the manual page for @code{perror(3C)} explicitly warns that one
57489857Sobrienshould check the size of the table (@code{sys_nerr}) before indexing
57589857Sobrienit, since new error codes may be added to the system before they are
57689857Sobrienadded to the table.  Thus @code{sys_nerr} might be smaller than value
57789857Sobrienimplied by the largest @code{errno} value defined in @code{<errno.h>}.
57833965Sjdp
57989857SobrienWe return the maximum value that can be used to obtain a meaningful
58089857Sobriensymbolic name or message.
58133965Sjdp
58289857Sobrien@end deftypefn
58333965Sjdp
58433965Sjdp*/
58533965Sjdp
58633965Sjdpint
587218822Sdimerrno_max (void)
58833965Sjdp{
58933965Sjdp  int maxsize;
59033965Sjdp
59133965Sjdp  if (error_names == NULL)
59233965Sjdp    {
59333965Sjdp      init_error_tables ();
59433965Sjdp    }
59533965Sjdp  maxsize = MAX (sys_nerr, num_error_names);
59633965Sjdp  return (maxsize - 1);
59733965Sjdp}
59833965Sjdp
59960484Sobrien#ifndef HAVE_STRERROR
60033965Sjdp
60133965Sjdp/*
60233965Sjdp
60389857Sobrien@deftypefn Supplemental char* strerror (int @var{errnoval})
60433965Sjdp
60589857SobrienMaps an @code{errno} number to an error message string, the contents
60689857Sobrienof which are implementation defined.  On systems which have the
60789857Sobrienexternal variables @code{sys_nerr} and @code{sys_errlist}, these
60889857Sobrienstrings will be the same as the ones used by @code{perror}.
60933965Sjdp
61089857SobrienIf the supplied error number is within the valid range of indices for
61189857Sobrienthe @code{sys_errlist}, but no message is available for the particular
61289857Sobrienerror number, then returns the string @samp{Error @var{num}}, where
61389857Sobrien@var{num} is the error number.
61433965Sjdp
61589857SobrienIf the supplied error number is not a valid index into
61689857Sobrien@code{sys_errlist}, returns @code{NULL}.
61733965Sjdp
61889857SobrienThe returned string is only guaranteed to be valid only until the
61989857Sobriennext call to @code{strerror}.
62033965Sjdp
62189857Sobrien@end deftypefn
62233965Sjdp
62333965Sjdp*/
62433965Sjdp
62533965Sjdpchar *
626218822Sdimstrerror (int errnoval)
62733965Sjdp{
62889857Sobrien  const char *msg;
62933965Sjdp  static char buf[32];
63033965Sjdp
63160484Sobrien#ifndef HAVE_SYS_ERRLIST
63233965Sjdp
63333965Sjdp  if (error_names == NULL)
63433965Sjdp    {
63533965Sjdp      init_error_tables ();
63633965Sjdp    }
63733965Sjdp
63833965Sjdp#endif
63933965Sjdp
64033965Sjdp  if ((errnoval < 0) || (errnoval >= sys_nerr))
64133965Sjdp    {
64233965Sjdp#ifdef EVMSERR
64333965Sjdp      if (errnoval == evmserr.value)
64433965Sjdp	msg = evmserr.msg;
64533965Sjdp      else
64633965Sjdp#endif
64733965Sjdp      /* Out of range, just return NULL */
64833965Sjdp      msg = NULL;
64933965Sjdp    }
65033965Sjdp  else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
65133965Sjdp    {
65233965Sjdp      /* In range, but no sys_errlist or no entry at this index. */
65333965Sjdp      sprintf (buf, "Error %d", errnoval);
65433965Sjdp      msg = buf;
65533965Sjdp    }
65633965Sjdp  else
65733965Sjdp    {
65833965Sjdp      /* In range, and a valid message.  Just return the message. */
65933965Sjdp      msg = (char *) sys_errlist[errnoval];
66033965Sjdp    }
66133965Sjdp
66233965Sjdp  return (msg);
66333965Sjdp}
66433965Sjdp
66560484Sobrien#endif	/* ! HAVE_STRERROR */
66633965Sjdp
66733965Sjdp
66833965Sjdp/*
66933965Sjdp
67089857Sobrien@deftypefn Replacement {const char*} strerrno (int @var{errnum})
67133965Sjdp
67289857SobrienGiven an error number returned from a system call (typically returned
67389857Sobrienin @code{errno}), returns a pointer to a string containing the
67489857Sobriensymbolic name of that error number, as found in @code{<errno.h>}.
67533965Sjdp
67689857SobrienIf the supplied error number is within the valid range of indices for
67789857Sobriensymbolic names, but no name is available for the particular error
67889857Sobriennumber, then returns the string @samp{Error @var{num}}, where @var{num}
67989857Sobrienis the error number.
68033965Sjdp
68189857SobrienIf the supplied error number is not within the range of valid
68289857Sobrienindices, then returns @code{NULL}.
68333965Sjdp
68489857SobrienThe contents of the location pointed to are only guaranteed to be
68589857Sobrienvalid until the next call to @code{strerrno}.
68633965Sjdp
68789857Sobrien@end deftypefn
68833965Sjdp
68933965Sjdp*/
69033965Sjdp
69133965Sjdpconst char *
692218822Sdimstrerrno (int errnoval)
69333965Sjdp{
69433965Sjdp  const char *name;
69533965Sjdp  static char buf[32];
69633965Sjdp
69733965Sjdp  if (error_names == NULL)
69833965Sjdp    {
69933965Sjdp      init_error_tables ();
70033965Sjdp    }
70133965Sjdp
70233965Sjdp  if ((errnoval < 0) || (errnoval >= num_error_names))
70333965Sjdp    {
70433965Sjdp#ifdef EVMSERR
70533965Sjdp      if (errnoval == evmserr.value)
70633965Sjdp	name = evmserr.name;
70733965Sjdp      else
70833965Sjdp#endif
70933965Sjdp      /* Out of range, just return NULL */
71033965Sjdp      name = NULL;
71133965Sjdp    }
71233965Sjdp  else if ((error_names == NULL) || (error_names[errnoval] == NULL))
71333965Sjdp    {
71433965Sjdp      /* In range, but no error_names or no entry at this index. */
71533965Sjdp      sprintf (buf, "Error %d", errnoval);
71633965Sjdp      name = (const char *) buf;
71733965Sjdp    }
71833965Sjdp  else
71933965Sjdp    {
72033965Sjdp      /* In range, and a valid name.  Just return the name. */
72133965Sjdp      name = error_names[errnoval];
72233965Sjdp    }
72333965Sjdp
72433965Sjdp  return (name);
72533965Sjdp}
72633965Sjdp
72733965Sjdp/*
72833965Sjdp
72989857Sobrien@deftypefn Extension int strtoerrno (const char *@var{name})
73033965Sjdp
73189857SobrienGiven the symbolic name of a error number (e.g., @code{EACCES}), map it
73289857Sobriento an errno value.  If no translation is found, returns 0.
73333965Sjdp
73489857Sobrien@end deftypefn
73533965Sjdp
73633965Sjdp*/
73733965Sjdp
73833965Sjdpint
739218822Sdimstrtoerrno (const char *name)
74033965Sjdp{
74133965Sjdp  int errnoval = 0;
74233965Sjdp
74333965Sjdp  if (name != NULL)
74433965Sjdp    {
74533965Sjdp      if (error_names == NULL)
74633965Sjdp	{
74733965Sjdp	  init_error_tables ();
74833965Sjdp	}
74933965Sjdp      for (errnoval = 0; errnoval < num_error_names; errnoval++)
75033965Sjdp	{
75133965Sjdp	  if ((error_names[errnoval] != NULL) &&
75233965Sjdp	      (strcmp (name, error_names[errnoval]) == 0))
75333965Sjdp	    {
75433965Sjdp	      break;
75533965Sjdp	    }
75633965Sjdp	}
75733965Sjdp      if (errnoval == num_error_names)
75833965Sjdp	{
75933965Sjdp#ifdef EVMSERR
76033965Sjdp	  if (strcmp (name, evmserr.name) == 0)
76133965Sjdp	    errnoval = evmserr.value;
76233965Sjdp	  else
76333965Sjdp#endif
76433965Sjdp	  errnoval = 0;
76533965Sjdp	}
76633965Sjdp    }
76733965Sjdp  return (errnoval);
76833965Sjdp}
76933965Sjdp
77033965Sjdp
77133965Sjdp/* A simple little main that does nothing but print all the errno translations
77233965Sjdp   if MAIN is defined and this file is compiled and linked. */
77333965Sjdp
77433965Sjdp#ifdef MAIN
77533965Sjdp
77633965Sjdp#include <stdio.h>
77733965Sjdp
77833965Sjdpint
779218822Sdimmain (void)
78033965Sjdp{
78133965Sjdp  int errn;
78233965Sjdp  int errnmax;
78333965Sjdp  const char *name;
78489857Sobrien  const char *msg;
78533965Sjdp  char *strerror ();
78633965Sjdp
78733965Sjdp  errnmax = errno_max ();
78833965Sjdp  printf ("%d entries in names table.\n", num_error_names);
78933965Sjdp  printf ("%d entries in messages table.\n", sys_nerr);
79033965Sjdp  printf ("%d is max useful index.\n", errnmax);
79133965Sjdp
79233965Sjdp  /* Keep printing values until we get to the end of *both* tables, not
79333965Sjdp     *either* table.  Note that knowing the maximum useful index does *not*
79433965Sjdp     relieve us of the responsibility of testing the return pointer for
79533965Sjdp     NULL. */
79633965Sjdp
79733965Sjdp  for (errn = 0; errn <= errnmax; errn++)
79833965Sjdp    {
79933965Sjdp      name = strerrno (errn);
80033965Sjdp      name = (name == NULL) ? "<NULL>" : name;
80133965Sjdp      msg = strerror (errn);
80233965Sjdp      msg = (msg == NULL) ? "<NULL>" : msg;
80333965Sjdp      printf ("%-4d%-18s%s\n", errn, name, msg);
80433965Sjdp    }
80533965Sjdp
80633965Sjdp  return 0;
80733965Sjdp}
80833965Sjdp
80933965Sjdp#endif
810