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