1169695Skan/* Extended support for using errno values. 2169695Skan Written by Fred Fish. fnf@cygnus.com 3169695Skan This file is in the public domain. --Per Bothner. */ 4169695Skan 5169695Skan#include "config.h" 6169695Skan 7169695Skan#ifdef HAVE_SYS_ERRLIST 8169695Skan/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least) 9169695Skan might declare sys_errlist in a way that the compiler might consider 10169695Skan incompatible with our later declaration, perhaps by using const 11169695Skan attributes. So we hide the declaration in errno.h (if any) using a 12169695Skan macro. */ 13169695Skan#define sys_nerr sys_nerr__ 14169695Skan#define sys_errlist sys_errlist__ 15169695Skan#endif 16169695Skan 17169695Skan#include "ansidecl.h" 18169695Skan#include "libiberty.h" 19169695Skan 20169695Skan#include <stdio.h> 21169695Skan#include <errno.h> 22169695Skan 23169695Skan#ifdef HAVE_SYS_ERRLIST 24169695Skan#undef sys_nerr 25169695Skan#undef sys_errlist 26169695Skan#endif 27169695Skan 28169695Skan/* Routines imported from standard C runtime libraries. */ 29169695Skan 30169695Skan#ifdef HAVE_STDLIB_H 31169695Skan#include <stdlib.h> 32169695Skan#else 33169695Skanextern PTR malloc (); 34169695Skan#endif 35169695Skan 36169695Skan#ifdef HAVE_STRING_H 37169695Skan#include <string.h> 38169695Skan#else 39169695Skanextern PTR memset (); 40169695Skan#endif 41169695Skan 42169695Skan#ifndef MAX 43169695Skan# define MAX(a,b) ((a) > (b) ? (a) : (b)) 44169695Skan#endif 45169695Skan 46169695Skanstatic void init_error_tables (void); 47169695Skan 48169695Skan/* Translation table for errno values. See intro(2) in most UNIX systems 49169695Skan Programmers Reference Manuals. 50169695Skan 51169695Skan Note that this table is generally only accessed when it is used at runtime 52169695Skan to initialize errno name and message tables that are indexed by errno 53169695Skan value. 54169695Skan 55169695Skan Not all of these errnos will exist on all systems. This table is the only 56169695Skan thing that should have to be updated as new error numbers are introduced. 57169695Skan It's sort of ugly, but at least its portable. */ 58169695Skan 59169695Skanstruct error_info 60169695Skan{ 61169695Skan const int value; /* The numeric value from <errno.h> */ 62169695Skan const char *const name; /* The equivalent symbolic value */ 63169695Skan#ifndef HAVE_SYS_ERRLIST 64169695Skan const char *const msg; /* Short message about this value */ 65169695Skan#endif 66169695Skan}; 67169695Skan 68169695Skan#ifndef HAVE_SYS_ERRLIST 69169695Skan# define ENTRY(value, name, msg) {value, name, msg} 70169695Skan#else 71169695Skan# define ENTRY(value, name, msg) {value, name} 72169695Skan#endif 73169695Skan 74169695Skanstatic const struct error_info error_table[] = 75169695Skan{ 76169695Skan#if defined (EPERM) 77169695Skan ENTRY(EPERM, "EPERM", "Not owner"), 78169695Skan#endif 79169695Skan#if defined (ENOENT) 80169695Skan ENTRY(ENOENT, "ENOENT", "No such file or directory"), 81169695Skan#endif 82169695Skan#if defined (ESRCH) 83169695Skan ENTRY(ESRCH, "ESRCH", "No such process"), 84169695Skan#endif 85169695Skan#if defined (EINTR) 86169695Skan ENTRY(EINTR, "EINTR", "Interrupted system call"), 87169695Skan#endif 88169695Skan#if defined (EIO) 89169695Skan ENTRY(EIO, "EIO", "I/O error"), 90169695Skan#endif 91169695Skan#if defined (ENXIO) 92169695Skan ENTRY(ENXIO, "ENXIO", "No such device or address"), 93169695Skan#endif 94169695Skan#if defined (E2BIG) 95169695Skan ENTRY(E2BIG, "E2BIG", "Arg list too long"), 96169695Skan#endif 97169695Skan#if defined (ENOEXEC) 98169695Skan ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"), 99169695Skan#endif 100169695Skan#if defined (EBADF) 101169695Skan ENTRY(EBADF, "EBADF", "Bad file number"), 102169695Skan#endif 103169695Skan#if defined (ECHILD) 104169695Skan ENTRY(ECHILD, "ECHILD", "No child processes"), 105169695Skan#endif 106169695Skan#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */ 107169695Skan ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"), 108169695Skan#endif 109169695Skan#if defined (EAGAIN) 110169695Skan ENTRY(EAGAIN, "EAGAIN", "No more processes"), 111169695Skan#endif 112169695Skan#if defined (ENOMEM) 113169695Skan ENTRY(ENOMEM, "ENOMEM", "Not enough space"), 114169695Skan#endif 115169695Skan#if defined (EACCES) 116169695Skan ENTRY(EACCES, "EACCES", "Permission denied"), 117169695Skan#endif 118169695Skan#if defined (EFAULT) 119169695Skan ENTRY(EFAULT, "EFAULT", "Bad address"), 120169695Skan#endif 121169695Skan#if defined (ENOTBLK) 122169695Skan ENTRY(ENOTBLK, "ENOTBLK", "Block device required"), 123169695Skan#endif 124169695Skan#if defined (EBUSY) 125169695Skan ENTRY(EBUSY, "EBUSY", "Device busy"), 126169695Skan#endif 127169695Skan#if defined (EEXIST) 128169695Skan ENTRY(EEXIST, "EEXIST", "File exists"), 129169695Skan#endif 130169695Skan#if defined (EXDEV) 131169695Skan ENTRY(EXDEV, "EXDEV", "Cross-device link"), 132169695Skan#endif 133169695Skan#if defined (ENODEV) 134169695Skan ENTRY(ENODEV, "ENODEV", "No such device"), 135169695Skan#endif 136169695Skan#if defined (ENOTDIR) 137169695Skan ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"), 138169695Skan#endif 139169695Skan#if defined (EISDIR) 140169695Skan ENTRY(EISDIR, "EISDIR", "Is a directory"), 141169695Skan#endif 142169695Skan#if defined (EINVAL) 143169695Skan ENTRY(EINVAL, "EINVAL", "Invalid argument"), 144169695Skan#endif 145169695Skan#if defined (ENFILE) 146169695Skan ENTRY(ENFILE, "ENFILE", "File table overflow"), 147169695Skan#endif 148169695Skan#if defined (EMFILE) 149169695Skan ENTRY(EMFILE, "EMFILE", "Too many open files"), 150169695Skan#endif 151169695Skan#if defined (ENOTTY) 152169695Skan ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"), 153169695Skan#endif 154169695Skan#if defined (ETXTBSY) 155169695Skan ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"), 156169695Skan#endif 157169695Skan#if defined (EFBIG) 158169695Skan ENTRY(EFBIG, "EFBIG", "File too large"), 159169695Skan#endif 160169695Skan#if defined (ENOSPC) 161169695Skan ENTRY(ENOSPC, "ENOSPC", "No space left on device"), 162169695Skan#endif 163169695Skan#if defined (ESPIPE) 164169695Skan ENTRY(ESPIPE, "ESPIPE", "Illegal seek"), 165169695Skan#endif 166169695Skan#if defined (EROFS) 167169695Skan ENTRY(EROFS, "EROFS", "Read-only file system"), 168169695Skan#endif 169169695Skan#if defined (EMLINK) 170169695Skan ENTRY(EMLINK, "EMLINK", "Too many links"), 171169695Skan#endif 172169695Skan#if defined (EPIPE) 173169695Skan ENTRY(EPIPE, "EPIPE", "Broken pipe"), 174169695Skan#endif 175169695Skan#if defined (EDOM) 176169695Skan ENTRY(EDOM, "EDOM", "Math argument out of domain of func"), 177169695Skan#endif 178169695Skan#if defined (ERANGE) 179169695Skan ENTRY(ERANGE, "ERANGE", "Math result not representable"), 180169695Skan#endif 181169695Skan#if defined (ENOMSG) 182169695Skan ENTRY(ENOMSG, "ENOMSG", "No message of desired type"), 183169695Skan#endif 184169695Skan#if defined (EIDRM) 185169695Skan ENTRY(EIDRM, "EIDRM", "Identifier removed"), 186169695Skan#endif 187169695Skan#if defined (ECHRNG) 188169695Skan ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"), 189169695Skan#endif 190169695Skan#if defined (EL2NSYNC) 191169695Skan ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"), 192169695Skan#endif 193169695Skan#if defined (EL3HLT) 194169695Skan ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"), 195169695Skan#endif 196169695Skan#if defined (EL3RST) 197169695Skan ENTRY(EL3RST, "EL3RST", "Level 3 reset"), 198169695Skan#endif 199169695Skan#if defined (ELNRNG) 200169695Skan ENTRY(ELNRNG, "ELNRNG", "Link number out of range"), 201169695Skan#endif 202169695Skan#if defined (EUNATCH) 203169695Skan ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"), 204169695Skan#endif 205169695Skan#if defined (ENOCSI) 206169695Skan ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"), 207169695Skan#endif 208169695Skan#if defined (EL2HLT) 209169695Skan ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"), 210169695Skan#endif 211169695Skan#if defined (EDEADLK) 212169695Skan ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"), 213169695Skan#endif 214169695Skan#if defined (ENOLCK) 215169695Skan ENTRY(ENOLCK, "ENOLCK", "No record locks available"), 216169695Skan#endif 217169695Skan#if defined (EBADE) 218169695Skan ENTRY(EBADE, "EBADE", "Invalid exchange"), 219169695Skan#endif 220169695Skan#if defined (EBADR) 221169695Skan ENTRY(EBADR, "EBADR", "Invalid request descriptor"), 222169695Skan#endif 223169695Skan#if defined (EXFULL) 224169695Skan ENTRY(EXFULL, "EXFULL", "Exchange full"), 225169695Skan#endif 226169695Skan#if defined (ENOANO) 227169695Skan ENTRY(ENOANO, "ENOANO", "No anode"), 228169695Skan#endif 229169695Skan#if defined (EBADRQC) 230169695Skan ENTRY(EBADRQC, "EBADRQC", "Invalid request code"), 231169695Skan#endif 232169695Skan#if defined (EBADSLT) 233169695Skan ENTRY(EBADSLT, "EBADSLT", "Invalid slot"), 234169695Skan#endif 235169695Skan#if defined (EDEADLOCK) 236169695Skan ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"), 237169695Skan#endif 238169695Skan#if defined (EBFONT) 239169695Skan ENTRY(EBFONT, "EBFONT", "Bad font file format"), 240169695Skan#endif 241169695Skan#if defined (ENOSTR) 242169695Skan ENTRY(ENOSTR, "ENOSTR", "Device not a stream"), 243169695Skan#endif 244169695Skan#if defined (ENODATA) 245169695Skan ENTRY(ENODATA, "ENODATA", "No data available"), 246169695Skan#endif 247169695Skan#if defined (ETIME) 248169695Skan ENTRY(ETIME, "ETIME", "Timer expired"), 249169695Skan#endif 250169695Skan#if defined (ENOSR) 251169695Skan ENTRY(ENOSR, "ENOSR", "Out of streams resources"), 252169695Skan#endif 253169695Skan#if defined (ENONET) 254169695Skan ENTRY(ENONET, "ENONET", "Machine is not on the network"), 255169695Skan#endif 256169695Skan#if defined (ENOPKG) 257169695Skan ENTRY(ENOPKG, "ENOPKG", "Package not installed"), 258169695Skan#endif 259169695Skan#if defined (EREMOTE) 260169695Skan ENTRY(EREMOTE, "EREMOTE", "Object is remote"), 261169695Skan#endif 262169695Skan#if defined (ENOLINK) 263169695Skan ENTRY(ENOLINK, "ENOLINK", "Link has been severed"), 264169695Skan#endif 265169695Skan#if defined (EADV) 266169695Skan ENTRY(EADV, "EADV", "Advertise error"), 267169695Skan#endif 268169695Skan#if defined (ESRMNT) 269169695Skan ENTRY(ESRMNT, "ESRMNT", "Srmount error"), 270169695Skan#endif 271169695Skan#if defined (ECOMM) 272169695Skan ENTRY(ECOMM, "ECOMM", "Communication error on send"), 273169695Skan#endif 274169695Skan#if defined (EPROTO) 275169695Skan ENTRY(EPROTO, "EPROTO", "Protocol error"), 276169695Skan#endif 277169695Skan#if defined (EMULTIHOP) 278169695Skan ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"), 279169695Skan#endif 280169695Skan#if defined (EDOTDOT) 281169695Skan ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"), 282169695Skan#endif 283169695Skan#if defined (EBADMSG) 284169695Skan ENTRY(EBADMSG, "EBADMSG", "Not a data message"), 285169695Skan#endif 286169695Skan#if defined (ENAMETOOLONG) 287169695Skan ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"), 288169695Skan#endif 289169695Skan#if defined (EOVERFLOW) 290169695Skan ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"), 291169695Skan#endif 292169695Skan#if defined (ENOTUNIQ) 293169695Skan ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"), 294169695Skan#endif 295169695Skan#if defined (EBADFD) 296169695Skan ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"), 297169695Skan#endif 298169695Skan#if defined (EREMCHG) 299169695Skan ENTRY(EREMCHG, "EREMCHG", "Remote address changed"), 300169695Skan#endif 301169695Skan#if defined (ELIBACC) 302169695Skan ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"), 303169695Skan#endif 304169695Skan#if defined (ELIBBAD) 305169695Skan ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"), 306169695Skan#endif 307169695Skan#if defined (ELIBSCN) 308169695Skan ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"), 309169695Skan#endif 310169695Skan#if defined (ELIBMAX) 311169695Skan ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"), 312169695Skan#endif 313169695Skan#if defined (ELIBEXEC) 314169695Skan ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"), 315169695Skan#endif 316169695Skan#if defined (EILSEQ) 317169695Skan ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"), 318169695Skan#endif 319169695Skan#if defined (ENOSYS) 320169695Skan ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"), 321169695Skan#endif 322169695Skan#if defined (ELOOP) 323169695Skan ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"), 324169695Skan#endif 325169695Skan#if defined (ERESTART) 326169695Skan ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"), 327169695Skan#endif 328169695Skan#if defined (ESTRPIPE) 329169695Skan ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"), 330169695Skan#endif 331169695Skan#if defined (ENOTEMPTY) 332169695Skan ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"), 333169695Skan#endif 334169695Skan#if defined (EUSERS) 335169695Skan ENTRY(EUSERS, "EUSERS", "Too many users"), 336169695Skan#endif 337169695Skan#if defined (ENOTSOCK) 338169695Skan ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"), 339169695Skan#endif 340169695Skan#if defined (EDESTADDRREQ) 341169695Skan ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"), 342169695Skan#endif 343169695Skan#if defined (EMSGSIZE) 344169695Skan ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"), 345169695Skan#endif 346169695Skan#if defined (EPROTOTYPE) 347169695Skan ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"), 348169695Skan#endif 349169695Skan#if defined (ENOPROTOOPT) 350169695Skan ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"), 351169695Skan#endif 352169695Skan#if defined (EPROTONOSUPPORT) 353169695Skan ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"), 354169695Skan#endif 355169695Skan#if defined (ESOCKTNOSUPPORT) 356169695Skan ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"), 357169695Skan#endif 358169695Skan#if defined (EOPNOTSUPP) 359169695Skan ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"), 360169695Skan#endif 361169695Skan#if defined (EPFNOSUPPORT) 362169695Skan ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"), 363169695Skan#endif 364169695Skan#if defined (EAFNOSUPPORT) 365169695Skan ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"), 366169695Skan#endif 367169695Skan#if defined (EADDRINUSE) 368169695Skan ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"), 369169695Skan#endif 370169695Skan#if defined (EADDRNOTAVAIL) 371169695Skan ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"), 372169695Skan#endif 373169695Skan#if defined (ENETDOWN) 374169695Skan ENTRY(ENETDOWN, "ENETDOWN", "Network is down"), 375169695Skan#endif 376169695Skan#if defined (ENETUNREACH) 377169695Skan ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"), 378169695Skan#endif 379169695Skan#if defined (ENETRESET) 380169695Skan ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"), 381169695Skan#endif 382169695Skan#if defined (ECONNABORTED) 383169695Skan ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"), 384169695Skan#endif 385169695Skan#if defined (ECONNRESET) 386169695Skan ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"), 387169695Skan#endif 388169695Skan#if defined (ENOBUFS) 389169695Skan ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"), 390169695Skan#endif 391169695Skan#if defined (EISCONN) 392169695Skan ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"), 393169695Skan#endif 394169695Skan#if defined (ENOTCONN) 395169695Skan ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"), 396169695Skan#endif 397169695Skan#if defined (ESHUTDOWN) 398169695Skan ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"), 399169695Skan#endif 400169695Skan#if defined (ETOOMANYREFS) 401169695Skan ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"), 402169695Skan#endif 403169695Skan#if defined (ETIMEDOUT) 404169695Skan ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"), 405169695Skan#endif 406169695Skan#if defined (ECONNREFUSED) 407169695Skan ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"), 408169695Skan#endif 409169695Skan#if defined (EHOSTDOWN) 410169695Skan ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"), 411169695Skan#endif 412169695Skan#if defined (EHOSTUNREACH) 413169695Skan ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"), 414169695Skan#endif 415169695Skan#if defined (EALREADY) 416169695Skan ENTRY(EALREADY, "EALREADY", "Operation already in progress"), 417169695Skan#endif 418169695Skan#if defined (EINPROGRESS) 419169695Skan ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"), 420169695Skan#endif 421169695Skan#if defined (ESTALE) 422169695Skan ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"), 423169695Skan#endif 424169695Skan#if defined (EUCLEAN) 425169695Skan ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"), 426169695Skan#endif 427169695Skan#if defined (ENOTNAM) 428169695Skan ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"), 429169695Skan#endif 430169695Skan#if defined (ENAVAIL) 431169695Skan ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"), 432169695Skan#endif 433169695Skan#if defined (EISNAM) 434169695Skan ENTRY(EISNAM, "EISNAM", "Is a named type file"), 435169695Skan#endif 436169695Skan#if defined (EREMOTEIO) 437169695Skan ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"), 438169695Skan#endif 439169695Skan ENTRY(0, NULL, NULL) 440169695Skan}; 441169695Skan 442169695Skan#ifdef EVMSERR 443169695Skan/* This is not in the table, because the numeric value of EVMSERR (32767) 444169695Skan lies outside the range of sys_errlist[]. */ 445169695Skanstatic struct { int value; const char *name, *msg; } 446169695Skan evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" }; 447169695Skan#endif 448169695Skan 449169695Skan/* Translation table allocated and initialized at runtime. Indexed by the 450169695Skan errno value to find the equivalent symbolic value. */ 451169695Skan 452169695Skanstatic const char **error_names; 453169695Skanstatic int num_error_names = 0; 454169695Skan 455169695Skan/* Translation table allocated and initialized at runtime, if it does not 456169695Skan already exist in the host environment. Indexed by the errno value to find 457169695Skan the descriptive string. 458169695Skan 459169695Skan We don't export it for use in other modules because even though it has the 460169695Skan same name, it differs from other implementations in that it is dynamically 461169695Skan initialized rather than statically initialized. */ 462169695Skan 463169695Skan#ifndef HAVE_SYS_ERRLIST 464169695Skan 465169695Skan#define sys_nerr sys_nerr__ 466169695Skan#define sys_errlist sys_errlist__ 467169695Skanstatic int sys_nerr; 468169695Skanstatic const char **sys_errlist; 469169695Skan 470169695Skan#else 471169695Skan 472169695Skanextern int sys_nerr; 473169695Skanextern char *sys_errlist[]; 474169695Skan 475169695Skan#endif 476169695Skan 477169695Skan/* 478169695Skan 479169695SkanNAME 480169695Skan 481169695Skan init_error_tables -- initialize the name and message tables 482169695Skan 483169695SkanSYNOPSIS 484169695Skan 485169695Skan static void init_error_tables (); 486169695Skan 487169695SkanDESCRIPTION 488169695Skan 489169695Skan Using the error_table, which is initialized at compile time, generate 490169695Skan the error_names and the sys_errlist (if needed) tables, which are 491169695Skan indexed at runtime by a specific errno value. 492169695Skan 493169695SkanBUGS 494169695Skan 495169695Skan The initialization of the tables may fail under low memory conditions, 496169695Skan in which case we don't do anything particularly useful, but we don't 497169695Skan bomb either. Who knows, it might succeed at a later point if we free 498169695Skan some memory in the meantime. In any case, the other routines know 499169695Skan how to deal with lack of a table after trying to initialize it. This 500169695Skan may or may not be considered to be a bug, that we don't specifically 501169695Skan warn about this particular failure mode. 502169695Skan 503169695Skan*/ 504169695Skan 505169695Skanstatic void 506169695Skaninit_error_tables (void) 507169695Skan{ 508169695Skan const struct error_info *eip; 509169695Skan int nbytes; 510169695Skan 511169695Skan /* If we haven't already scanned the error_table once to find the maximum 512169695Skan errno value, then go find it now. */ 513169695Skan 514169695Skan if (num_error_names == 0) 515169695Skan { 516169695Skan for (eip = error_table; eip -> name != NULL; eip++) 517169695Skan { 518169695Skan if (eip -> value >= num_error_names) 519169695Skan { 520169695Skan num_error_names = eip -> value + 1; 521169695Skan } 522169695Skan } 523169695Skan } 524169695Skan 525169695Skan /* Now attempt to allocate the error_names table, zero it out, and then 526169695Skan initialize it from the statically initialized error_table. */ 527169695Skan 528169695Skan if (error_names == NULL) 529169695Skan { 530169695Skan nbytes = num_error_names * sizeof (char *); 531169695Skan if ((error_names = (const char **) malloc (nbytes)) != NULL) 532169695Skan { 533169695Skan memset (error_names, 0, nbytes); 534169695Skan for (eip = error_table; eip -> name != NULL; eip++) 535169695Skan { 536169695Skan error_names[eip -> value] = eip -> name; 537169695Skan } 538169695Skan } 539169695Skan } 540169695Skan 541169695Skan#ifndef HAVE_SYS_ERRLIST 542169695Skan 543169695Skan /* Now attempt to allocate the sys_errlist table, zero it out, and then 544169695Skan initialize it from the statically initialized error_table. */ 545169695Skan 546169695Skan if (sys_errlist == NULL) 547169695Skan { 548169695Skan nbytes = num_error_names * sizeof (char *); 549169695Skan if ((sys_errlist = (const char **) malloc (nbytes)) != NULL) 550169695Skan { 551169695Skan memset (sys_errlist, 0, nbytes); 552169695Skan sys_nerr = num_error_names; 553169695Skan for (eip = error_table; eip -> name != NULL; eip++) 554169695Skan { 555169695Skan sys_errlist[eip -> value] = eip -> msg; 556169695Skan } 557169695Skan } 558169695Skan } 559169695Skan 560169695Skan#endif 561169695Skan 562169695Skan} 563169695Skan 564169695Skan/* 565169695Skan 566169695Skan 567169695Skan@deftypefn Extension int errno_max (void) 568169695Skan 569169695SkanReturns the maximum @code{errno} value for which a corresponding 570169695Skansymbolic name or message is available. Note that in the case where we 571169695Skanuse the @code{sys_errlist} supplied by the system, it is possible for 572169695Skanthere to be more symbolic names than messages, or vice versa. In 573169695Skanfact, the manual page for @code{perror(3C)} explicitly warns that one 574169695Skanshould check the size of the table (@code{sys_nerr}) before indexing 575169695Skanit, since new error codes may be added to the system before they are 576169695Skanadded to the table. Thus @code{sys_nerr} might be smaller than value 577169695Skanimplied by the largest @code{errno} value defined in @code{<errno.h>}. 578169695Skan 579169695SkanWe return the maximum value that can be used to obtain a meaningful 580169695Skansymbolic name or message. 581169695Skan 582169695Skan@end deftypefn 583169695Skan 584169695Skan*/ 585169695Skan 586169695Skanint 587169695Skanerrno_max (void) 588169695Skan{ 589169695Skan int maxsize; 590169695Skan 591169695Skan if (error_names == NULL) 592169695Skan { 593169695Skan init_error_tables (); 594169695Skan } 595169695Skan maxsize = MAX (sys_nerr, num_error_names); 596169695Skan return (maxsize - 1); 597169695Skan} 598169695Skan 599169695Skan#ifndef HAVE_STRERROR 600169695Skan 601169695Skan/* 602169695Skan 603169695Skan@deftypefn Supplemental char* strerror (int @var{errnoval}) 604169695Skan 605169695SkanMaps an @code{errno} number to an error message string, the contents 606169695Skanof which are implementation defined. On systems which have the 607169695Skanexternal variables @code{sys_nerr} and @code{sys_errlist}, these 608169695Skanstrings will be the same as the ones used by @code{perror}. 609169695Skan 610169695SkanIf the supplied error number is within the valid range of indices for 611169695Skanthe @code{sys_errlist}, but no message is available for the particular 612169695Skanerror number, then returns the string @samp{Error @var{num}}, where 613169695Skan@var{num} is the error number. 614169695Skan 615169695SkanIf the supplied error number is not a valid index into 616169695Skan@code{sys_errlist}, returns @code{NULL}. 617169695Skan 618169695SkanThe returned string is only guaranteed to be valid only until the 619169695Skannext call to @code{strerror}. 620169695Skan 621169695Skan@end deftypefn 622169695Skan 623169695Skan*/ 624169695Skan 625169695Skanchar * 626169695Skanstrerror (int errnoval) 627169695Skan{ 628169695Skan const char *msg; 629169695Skan static char buf[32]; 630169695Skan 631169695Skan#ifndef HAVE_SYS_ERRLIST 632169695Skan 633169695Skan if (error_names == NULL) 634169695Skan { 635169695Skan init_error_tables (); 636169695Skan } 637169695Skan 638169695Skan#endif 639169695Skan 640169695Skan if ((errnoval < 0) || (errnoval >= sys_nerr)) 641169695Skan { 642169695Skan#ifdef EVMSERR 643169695Skan if (errnoval == evmserr.value) 644169695Skan msg = evmserr.msg; 645169695Skan else 646169695Skan#endif 647169695Skan /* Out of range, just return NULL */ 648169695Skan msg = NULL; 649169695Skan } 650169695Skan else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL)) 651169695Skan { 652169695Skan /* In range, but no sys_errlist or no entry at this index. */ 653169695Skan sprintf (buf, "Error %d", errnoval); 654169695Skan msg = buf; 655169695Skan } 656169695Skan else 657169695Skan { 658169695Skan /* In range, and a valid message. Just return the message. */ 659169695Skan msg = (char *) sys_errlist[errnoval]; 660169695Skan } 661169695Skan 662169695Skan return (msg); 663169695Skan} 664169695Skan 665169695Skan#endif /* ! HAVE_STRERROR */ 666169695Skan 667169695Skan 668169695Skan/* 669169695Skan 670169695Skan@deftypefn Replacement {const char*} strerrno (int @var{errnum}) 671169695Skan 672169695SkanGiven an error number returned from a system call (typically returned 673169695Skanin @code{errno}), returns a pointer to a string containing the 674169695Skansymbolic name of that error number, as found in @code{<errno.h>}. 675169695Skan 676169695SkanIf the supplied error number is within the valid range of indices for 677169695Skansymbolic names, but no name is available for the particular error 678169695Skannumber, then returns the string @samp{Error @var{num}}, where @var{num} 679169695Skanis the error number. 680169695Skan 681169695SkanIf the supplied error number is not within the range of valid 682169695Skanindices, then returns @code{NULL}. 683169695Skan 684169695SkanThe contents of the location pointed to are only guaranteed to be 685169695Skanvalid until the next call to @code{strerrno}. 686169695Skan 687169695Skan@end deftypefn 688169695Skan 689169695Skan*/ 690169695Skan 691169695Skanconst char * 692169695Skanstrerrno (int errnoval) 693169695Skan{ 694169695Skan const char *name; 695169695Skan static char buf[32]; 696169695Skan 697169695Skan if (error_names == NULL) 698169695Skan { 699169695Skan init_error_tables (); 700169695Skan } 701169695Skan 702169695Skan if ((errnoval < 0) || (errnoval >= num_error_names)) 703169695Skan { 704169695Skan#ifdef EVMSERR 705169695Skan if (errnoval == evmserr.value) 706169695Skan name = evmserr.name; 707169695Skan else 708169695Skan#endif 709169695Skan /* Out of range, just return NULL */ 710169695Skan name = NULL; 711169695Skan } 712169695Skan else if ((error_names == NULL) || (error_names[errnoval] == NULL)) 713169695Skan { 714169695Skan /* In range, but no error_names or no entry at this index. */ 715169695Skan sprintf (buf, "Error %d", errnoval); 716169695Skan name = (const char *) buf; 717169695Skan } 718169695Skan else 719169695Skan { 720169695Skan /* In range, and a valid name. Just return the name. */ 721169695Skan name = error_names[errnoval]; 722169695Skan } 723169695Skan 724169695Skan return (name); 725169695Skan} 726169695Skan 727169695Skan/* 728169695Skan 729169695Skan@deftypefn Extension int strtoerrno (const char *@var{name}) 730169695Skan 731169695SkanGiven the symbolic name of a error number (e.g., @code{EACCES}), map it 732169695Skanto an errno value. If no translation is found, returns 0. 733169695Skan 734169695Skan@end deftypefn 735169695Skan 736169695Skan*/ 737169695Skan 738169695Skanint 739169695Skanstrtoerrno (const char *name) 740169695Skan{ 741169695Skan int errnoval = 0; 742169695Skan 743169695Skan if (name != NULL) 744169695Skan { 745169695Skan if (error_names == NULL) 746169695Skan { 747169695Skan init_error_tables (); 748169695Skan } 749169695Skan for (errnoval = 0; errnoval < num_error_names; errnoval++) 750169695Skan { 751169695Skan if ((error_names[errnoval] != NULL) && 752169695Skan (strcmp (name, error_names[errnoval]) == 0)) 753169695Skan { 754169695Skan break; 755169695Skan } 756169695Skan } 757169695Skan if (errnoval == num_error_names) 758169695Skan { 759169695Skan#ifdef EVMSERR 760169695Skan if (strcmp (name, evmserr.name) == 0) 761169695Skan errnoval = evmserr.value; 762169695Skan else 763169695Skan#endif 764169695Skan errnoval = 0; 765169695Skan } 766169695Skan } 767169695Skan return (errnoval); 768169695Skan} 769169695Skan 770169695Skan 771169695Skan/* A simple little main that does nothing but print all the errno translations 772169695Skan if MAIN is defined and this file is compiled and linked. */ 773169695Skan 774169695Skan#ifdef MAIN 775169695Skan 776169695Skan#include <stdio.h> 777169695Skan 778169695Skanint 779169695Skanmain (void) 780169695Skan{ 781169695Skan int errn; 782169695Skan int errnmax; 783169695Skan const char *name; 784169695Skan const char *msg; 785169695Skan char *strerror (); 786169695Skan 787169695Skan errnmax = errno_max (); 788169695Skan printf ("%d entries in names table.\n", num_error_names); 789169695Skan printf ("%d entries in messages table.\n", sys_nerr); 790169695Skan printf ("%d is max useful index.\n", errnmax); 791169695Skan 792169695Skan /* Keep printing values until we get to the end of *both* tables, not 793169695Skan *either* table. Note that knowing the maximum useful index does *not* 794169695Skan relieve us of the responsibility of testing the return pointer for 795169695Skan NULL. */ 796169695Skan 797169695Skan for (errn = 0; errn <= errnmax; errn++) 798169695Skan { 799169695Skan name = strerrno (errn); 800169695Skan name = (name == NULL) ? "<NULL>" : name; 801169695Skan msg = strerror (errn); 802169695Skan msg = (msg == NULL) ? "<NULL>" : msg; 803169695Skan printf ("%-4d%-18s%s\n", errn, name, msg); 804169695Skan } 805169695Skan 806169695Skan return 0; 807169695Skan} 808169695Skan 809169695Skan#endif 810