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