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