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