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