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