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