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