home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Source / GNU / debug / gdb / libiberty / strerror.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  19.8 KB  |  812 lines

  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. You should have received a copy of the GNU Library General Public
  17. License along with libiberty; see the file COPYING.LIB.  If
  18. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  19. Cambridge, MA 02139, USA.  */
  20.  
  21. //#include "config.h"
  22.  
  23. #include <stdio.h>
  24. #ifndef NEED_sys_errlist
  25. /* Note that errno.h might declare sys_errlist in a way that the
  26.  * compiler might consider incompatible with our later declaration,
  27.  * perhaps by using const attributes.  So we hide the declaration
  28.  * in errno.h (if any) using a macro. */
  29. #define sys_errlist sys_errlist__
  30. #endif
  31. #include <errno.h>
  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>
  40. extern void *malloc (size_t size);                /* 4.10.3.3 */
  41. extern void *memset (void *s, int c, size_t n);            /* 4.11.6.1 */
  42. #else    /* !__STDC__ */
  43. extern char *malloc ();        /* Standard memory allocater */
  44. extern char *memset ();
  45. #endif    /* __STDC__ */
  46.  
  47. #ifndef NULL
  48. #  ifdef __STDC__
  49. #    define NULL (void *) 0
  50. #  else
  51. #    define NULL 0
  52. #  endif
  53. #endif
  54.  
  55. #ifndef MAX
  56. #  define MAX(a,b) ((a) > (b) ? (a) : (b))
  57. #endif
  58.  
  59. /* Translation table for errno values.  See intro(2) in most UNIX systems
  60.    Programmers Reference Manuals.
  61.  
  62.    Note that this table is generally only accessed when it is used at runtime
  63.    to initialize errno name and message tables that are indexed by errno
  64.    value.
  65.  
  66.    Not all of these errnos will exist on all systems.  This table is the only
  67.    thing that should have to be updated as new error numbers are introduced.
  68.    It's sort of ugly, but at least its portable. */
  69.  
  70. static struct error_info
  71. {
  72.   int value;        /* The numeric value from <errno.h> */
  73.   char *name;        /* The equivalent symbolic value */
  74.   char *msg;        /* Short message about this value */
  75. } error_table[] =
  76. {
  77. #if defined (EPERM)
  78.   EPERM, "EPERM", "Not owner",
  79. #endif
  80. #if defined (ENOENT)
  81.   ENOENT, "ENOENT", "No such file or directory",
  82. #endif
  83. #if defined (ESRCH)
  84.   ESRCH, "ESRCH", "No such process",
  85. #endif
  86. #if defined (EINTR)
  87.   EINTR, "EINTR", "Interrupted system call",
  88. #endif
  89. #if defined (EIO)
  90.   EIO, "EIO", "I/O error",
  91. #endif
  92. #if defined (ENXIO)
  93.   ENXIO, "ENXIO", "No such device or address",
  94. #endif
  95. #if defined (E2BIG)
  96.   E2BIG, "E2BIG", "Arg list too long",
  97. #endif
  98. #if defined (ENOEXEC)
  99.   ENOEXEC, "ENOEXEC", "Exec format error",
  100. #endif
  101. #if defined (EBADF)
  102.   EBADF, "EBADF", "Bad file number",
  103. #endif
  104. #if defined (ECHILD)
  105.   ECHILD, "ECHILD", "No child processes",
  106. #endif
  107. #if defined (EWOULDBLOCK)    /* Put before EAGAIN, sometimes aliased */
  108.   EWOULDBLOCK, "EWOULDBLOCK", "Operation would block",
  109. #endif
  110. #if defined (EAGAIN)
  111.   EAGAIN, "EAGAIN", "No more processes",
  112. #endif
  113. #if defined (ENOMEM)
  114.   ENOMEM, "ENOMEM", "Not enough space",
  115. #endif
  116. #if defined (EACCES)
  117.   EACCES, "EACCES", "Permission denied",
  118. #endif
  119. #if defined (EFAULT)
  120.   EFAULT, "EFAULT", "Bad address",
  121. #endif
  122. #if defined (ENOTBLK)
  123.   ENOTBLK, "ENOTBLK", "Block device required",
  124. #endif
  125. #if defined (EBUSY)
  126.   EBUSY, "EBUSY", "Device busy",
  127. #endif
  128. #if defined (EEXIST)
  129.   EEXIST, "EEXIST", "File exists",
  130. #endif
  131. #if defined (EXDEV)
  132.   EXDEV, "EXDEV", "Cross-device link",
  133. #endif
  134. #if defined (ENODEV)
  135.   ENODEV, "ENODEV", "No such device",
  136. #endif
  137. #if defined (ENOTDIR)
  138.   ENOTDIR, "ENOTDIR", "Not a directory",
  139. #endif
  140. #if defined (EISDIR)
  141.   EISDIR, "EISDIR", "Is a directory",
  142. #endif
  143. #if defined (EINVAL)
  144.   EINVAL, "EINVAL", "Invalid argument",
  145. #endif
  146. #if defined (ENFILE)
  147.   ENFILE, "ENFILE", "File table overflow",
  148. #endif
  149. #if defined (EMFILE)
  150.   EMFILE, "EMFILE", "Too many open files",
  151. #endif
  152. #if defined (ENOTTY)
  153.   ENOTTY, "ENOTTY", "Not a typewriter",
  154. #endif
  155. #if defined (ETXTBSY)
  156.   ETXTBSY, "ETXTBSY", "Text file busy",
  157. #endif
  158. #if defined (EFBIG)
  159.   EFBIG, "EFBIG", "File too large",
  160. #endif
  161. #if defined (ENOSPC)
  162.   ENOSPC, "ENOSPC", "No space left on device",
  163. #endif
  164. #if defined (ESPIPE)
  165.   ESPIPE, "ESPIPE", "Illegal seek",
  166. #endif
  167. #if defined (EROFS)
  168.   EROFS, "EROFS", "Read-only file system",
  169. #endif
  170. #if defined (EMLINK)
  171.   EMLINK, "EMLINK", "Too many links",
  172. #endif
  173. #if defined (EPIPE)
  174.   EPIPE, "EPIPE", "Broken pipe",
  175. #endif
  176. #if defined (EDOM)
  177.   EDOM, "EDOM", "Math argument out of domain of func",
  178. #endif
  179. #if defined (ERANGE)
  180.   ERANGE, "ERANGE", "Math result not representable",
  181. #endif
  182. #if defined (ENOMSG)
  183.   ENOMSG, "ENOMSG", "No message of desired type",
  184. #endif
  185. #if defined (EIDRM)
  186.   EIDRM, "EIDRM", "Identifier removed",
  187. #endif
  188. #if defined (ECHRNG)
  189.   ECHRNG, "ECHRNG", "Channel number out of range",
  190. #endif
  191. #if defined (EL2NSYNC)
  192.   EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized",
  193. #endif
  194. #if defined (EL3HLT)
  195.   EL3HLT, "EL3HLT", "Level 3 halted",
  196. #endif
  197. #if defined (EL3RST)
  198.   EL3RST, "EL3RST", "Level 3 reset",
  199. #endif
  200. #if defined (ELNRNG)
  201.   ELNRNG, "ELNRNG", "Link number out of range",
  202. #endif
  203. #if defined (EUNATCH)
  204.   EUNATCH, "EUNATCH", "Protocol driver not attached",
  205. #endif
  206. #if defined (ENOCSI)
  207.   ENOCSI, "ENOCSI", "No CSI structure available",
  208. #endif
  209. #if defined (EL2HLT)
  210.   EL2HLT, "EL2HLT", "Level 2 halted",
  211. #endif
  212. #if defined (EDEADLK)
  213.   EDEADLK, "EDEADLK", "Deadlock condition",
  214. #endif
  215. #if defined (ENOLCK)
  216.   ENOLCK, "ENOLCK", "No record locks available",
  217. #endif
  218. #if defined (EBADE)
  219.   EBADE, "EBADE", "Invalid exchange",
  220. #endif
  221. #if defined (EBADR)
  222.   EBADR, "EBADR", "Invalid request descriptor",
  223. #endif
  224. #if defined (EXFULL)
  225.   EXFULL, "EXFULL", "Exchange full",
  226. #endif
  227. #if defined (ENOANO)
  228.   ENOANO, "ENOANO", "No anode",
  229. #endif
  230. #if defined (EBADRQC)
  231.   EBADRQC, "EBADRQC", "Invalid request code",
  232. #endif
  233. #if defined (EBADSLT)
  234.   EBADSLT, "EBADSLT", "Invalid slot",
  235. #endif
  236. #if defined (EDEADLOCK)
  237.   EDEADLOCK, "EDEADLOCK", "File locking deadlock error",
  238. #endif
  239. #if defined (EBFONT)
  240.   EBFONT, "EBFONT", "Bad font file format",
  241. #endif
  242. #if defined (ENOSTR)
  243.   ENOSTR, "ENOSTR", "Device not a stream",
  244. #endif
  245. #if defined (ENODATA)
  246.   ENODATA, "ENODATA", "No data available",
  247. #endif
  248. #if defined (ETIME)
  249.   ETIME, "ETIME", "Timer expired",
  250. #endif
  251. #if defined (ENOSR)
  252.   ENOSR, "ENOSR", "Out of streams resources",
  253. #endif
  254. #if defined (ENONET)
  255.   ENONET, "ENONET", "Machine is not on the network",
  256. #endif
  257. #if defined (ENOPKG)
  258.   ENOPKG, "ENOPKG", "Package not installed",
  259. #endif
  260. #if defined (EREMOTE)
  261.   EREMOTE, "EREMOTE", "Object is remote",
  262. #endif
  263. #if defined (ENOLINK)
  264.   ENOLINK, "ENOLINK", "Link has been severed",
  265. #endif
  266. #if defined (EADV)
  267.   EADV, "EADV", "Advertise error",
  268. #endif
  269. #if defined (ESRMNT)
  270.   ESRMNT, "ESRMNT", "Srmount error",
  271. #endif
  272. #if defined (ECOMM)
  273.   ECOMM, "ECOMM", "Communication error on send",
  274. #endif
  275. #if defined (EPROTO)
  276.   EPROTO, "EPROTO", "Protocol error",
  277. #endif
  278. #if defined (EMULTIHOP)
  279.   EMULTIHOP, "EMULTIHOP", "Multihop attempted",
  280. #endif
  281. #if defined (EDOTDOT)
  282.   EDOTDOT, "EDOTDOT", "RFS specific error",
  283. #endif
  284. #if defined (EBADMSG)
  285.   EBADMSG, "EBADMSG", "Not a data message",
  286. #endif
  287. #if defined (ENAMETOOLONG)
  288.   ENAMETOOLONG, "ENAMETOOLONG", "File name too long",
  289. #endif
  290. #if defined (EOVERFLOW)
  291.   EOVERFLOW, "EOVERFLOW", "Value too large for defined data type",
  292. #endif
  293. #if defined (ENOTUNIQ)
  294.   ENOTUNIQ, "ENOTUNIQ", "Name not unique on network",
  295. #endif
  296. #if defined (EBADFD)
  297.   EBADFD, "EBADFD", "File descriptor in bad state",
  298. #endif
  299. #if defined (EREMCHG)
  300.   EREMCHG, "EREMCHG", "Remote address changed",
  301. #endif
  302. #if defined (ELIBACC)
  303.   ELIBACC, "ELIBACC", "Can not access a needed shared library",
  304. #endif
  305. #if defined (ELIBBAD)
  306.   ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library",
  307. #endif
  308. #if defined (ELIBSCN)
  309.   ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted",
  310. #endif
  311. #if defined (ELIBMAX)
  312.   ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries",
  313. #endif
  314. #if defined (ELIBEXEC)
  315.   ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly",
  316. #endif
  317. #if defined (EILSEQ)
  318.   EILSEQ, "EILSEQ", "Illegal byte sequence",
  319. #endif
  320. #if defined (ENOSYS)
  321.   ENOSYS, "ENOSYS", "Operation not applicable",
  322. #endif
  323. #if defined (ELOOP)
  324.   ELOOP, "ELOOP", "Too many symbolic links encountered",
  325. #endif
  326. #if defined (ERESTART)
  327.   ERESTART, "ERESTART", "Interrupted system call should be restarted",
  328. #endif
  329. #if defined (ESTRPIPE)
  330.   ESTRPIPE, "ESTRPIPE", "Streams pipe error",
  331. #endif
  332. #if defined (ENOTEMPTY)
  333.   ENOTEMPTY, "ENOTEMPTY", "Directory not empty",
  334. #endif
  335. #if defined (EUSERS)
  336.   EUSERS, "EUSERS", "Too many users",
  337. #endif
  338. #if defined (ENOTSOCK)
  339.   ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket",
  340. #endif
  341. #if defined (EDESTADDRREQ)
  342.   EDESTADDRREQ, "EDESTADDRREQ", "Destination address required",
  343. #endif
  344. #if defined (EMSGSIZE)
  345.   EMSGSIZE, "EMSGSIZE", "Message too long",
  346. #endif
  347. #if defined (EPROTOTYPE)
  348.   EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket",
  349. #endif
  350. #if defined (ENOPROTOOPT)
  351.   ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available",
  352. #endif
  353. #if defined (EPROTONOSUPPORT)
  354.   EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported",
  355. #endif
  356. #if defined (ESOCKTNOSUPPORT)
  357.   ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported",
  358. #endif
  359. #if defined (EOPNOTSUPP)
  360.   EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint",
  361. #endif
  362. #if defined (EPFNOSUPPORT)
  363.   EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported",
  364. #endif
  365. #if defined (EAFNOSUPPORT)
  366.   EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol",
  367. #endif
  368. #if defined (EADDRINUSE)
  369.   EADDRINUSE, "EADDRINUSE", "Address already in use",
  370. #endif
  371. #if defined (EADDRNOTAVAIL)
  372.   EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address",
  373. #endif
  374. #if defined (ENETDOWN)
  375.   ENETDOWN, "ENETDOWN", "Network is down",
  376. #endif
  377. #if defined (ENETUNREACH)
  378.   ENETUNREACH, "ENETUNREACH", "Network is unreachable",
  379. #endif
  380. #if defined (ENETRESET)
  381.   ENETRESET, "ENETRESET", "Network dropped connection because of reset",
  382. #endif
  383. #if defined (ECONNABORTED)
  384.   ECONNABORTED, "ECONNABORTED", "Software caused connection abort",
  385. #endif
  386. #if defined (ECONNRESET)
  387.   ECONNRESET, "ECONNRESET", "Connection reset by peer",
  388. #endif
  389. #if defined (ENOBUFS)
  390.   ENOBUFS, "ENOBUFS", "No buffer space available",
  391. #endif
  392. #if defined (EISCONN)
  393.   EISCONN, "EISCONN", "Transport endpoint is already connected",
  394. #endif
  395. #if defined (ENOTCONN)
  396.   ENOTCONN, "ENOTCONN", "Transport endpoint is not connected",
  397. #endif
  398. #if defined (ESHUTDOWN)
  399.   ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown",
  400. #endif
  401. #if defined (ETOOMANYREFS)
  402.   ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice",
  403. #endif
  404. #if defined (ETIMEDOUT)
  405.   ETIMEDOUT, "ETIMEDOUT", "Connection timed out",
  406. #endif
  407. #if defined (ECONNREFUSED)
  408.   ECONNREFUSED, "ECONNREFUSED", "Connection refused",
  409. #endif
  410. #if defined (EHOSTDOWN)
  411.   EHOSTDOWN, "EHOSTDOWN", "Host is down",
  412. #endif
  413. #if defined (EHOSTUNREACH)
  414.   EHOSTUNREACH, "EHOSTUNREACH", "No route to host",
  415. #endif
  416. #if defined (EALREADY)
  417.   EALREADY, "EALREADY", "Operation already in progress",
  418. #endif
  419. #if defined (EINPROGRESS)
  420.   EINPROGRESS, "EINPROGRESS", "Operation now in progress",
  421. #endif
  422. #if defined (ESTALE)
  423.   ESTALE, "ESTALE", "Stale NFS file handle",
  424. #endif
  425. #if defined (EUCLEAN)
  426.   EUCLEAN, "EUCLEAN", "Structure needs cleaning",
  427. #endif
  428. #if defined (ENOTNAM)
  429.   ENOTNAM, "ENOTNAM", "Not a XENIX named type file",
  430. #endif
  431. #if defined (ENAVAIL)
  432.   ENAVAIL, "ENAVAIL", "No XENIX semaphores available",
  433. #endif
  434. #if defined (EISNAM)
  435.   EISNAM, "EISNAM", "Is a named type file",
  436. #endif
  437. #if defined (EREMOTEIO)
  438.   EREMOTEIO, "EREMOTEIO", "Remote I/O error",
  439. #endif
  440.   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.   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. #ifdef NEED_strerror
  598.  
  599. /*
  600.  
  601. NAME
  602.  
  603.     strerror -- map an error number to an error message string
  604.  
  605. SYNOPSIS
  606.  
  607.     char *strerror (int errnoval)
  608.  
  609. DESCRIPTION
  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.  
  629. char *
  630. strerror (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. #endif    /* NEED_strerror */
  666.  
  667.  
  668. /*
  669.  
  670. NAME
  671.  
  672.     strerrno -- map an error number to a symbolic name string
  673.  
  674. SYNOPSIS
  675.  
  676.     char *strerrno (int errnoval)
  677.  
  678. DESCRIPTION
  679.  
  680.     Given an error number returned from a system call (typically
  681.     returned in errno), returns a pointer to a string containing the
  682.     symbolic name of that error number, as found in <errno.h>.
  683.  
  684.     If the supplied error number is within the valid range of indices
  685.     for symbolic names, but no name is available for the particular
  686.     error number, then returns the string "Error NUM", where NUM is
  687.     the error number.
  688.  
  689.     If the supplied error number is not within the range of valid
  690.     indices, then returns NULL.
  691.  
  692. BUGS
  693.  
  694.     The contents of the location pointed to are only guaranteed to be
  695.     valid until the next call to strerrno.
  696.  
  697. */
  698.  
  699. char *
  700. strerrno (errnoval)
  701.   int errnoval;
  702. {
  703.   char *name;
  704.   static char buf[32];
  705.  
  706.   if (error_names == NULL)
  707.     {
  708.       init_error_tables ();
  709.     }
  710.  
  711.   if ((errnoval < 0) || (errnoval >= num_error_names))
  712.     {
  713.       /* Out of range, just return NULL */
  714.       name = NULL;
  715.     }
  716.   else if ((error_names == NULL) || (error_names[errnoval] == NULL))
  717.     {
  718.       /* In range, but no error_names or no entry at this index. */
  719.       sprintf (buf, "Error %d", errnoval);
  720.       name = buf;
  721.     }
  722.   else
  723.     {
  724.       /* In range, and a valid name.  Just return the name. */
  725.       name = error_names[errnoval];
  726.     }
  727.  
  728.   return (name);
  729. }
  730.  
  731. /*
  732.  
  733. NAME
  734.  
  735.     strtoerrno -- map a symbolic errno name to a numeric value
  736.  
  737. SYNOPSIS
  738.  
  739.     int strtoerrno (char *name)
  740.  
  741. DESCRIPTION
  742.  
  743.     Given the symbolic name of a error number, map it to an errno value.
  744.     If no translation is found, returns 0.
  745.  
  746. */
  747.  
  748. int
  749. strtoerrno (name)
  750.   char *name;
  751. {
  752.   int errnoval = 0;
  753.  
  754.   if (name != NULL)
  755.     {
  756.       if (error_names == NULL)
  757.     {
  758.       init_error_tables ();
  759.     }
  760.       for (errnoval = 0; errnoval < num_error_names; errnoval++)
  761.     {
  762.       if ((error_names[errnoval] != NULL) &&
  763.           (strcmp (name, error_names[errnoval]) == 0))
  764.         {
  765.           break;
  766.         }
  767.     }
  768.       if (errnoval == num_error_names)
  769.     {
  770.       errnoval = 0;
  771.     }
  772.     }
  773.   return (errnoval);
  774. }
  775.  
  776.  
  777. /* A simple little main that does nothing but print all the errno translations
  778.    if MAIN is defined and this file is compiled and linked. */
  779.  
  780. #ifdef MAIN
  781.  
  782. main ()
  783. {
  784.   int errn;
  785.   int errnmax;
  786.   char *name;
  787.   char *msg;
  788.   char *strerrno ();
  789.   char *strerror ();
  790.  
  791.   errnmax = errno_max ();
  792.   printf ("%d entries in names table.\n", num_error_names);
  793.   printf ("%d entries in messages table.\n", sys_nerr);
  794.   printf ("%d is max useful index.\n", errnmax);
  795.  
  796.   /* Keep printing values until we get to the end of *both* tables, not
  797.      *either* table.  Note that knowing the maximum useful index does *not*
  798.      relieve us of the responsibility of testing the return pointer for
  799.      NULL. */
  800.  
  801.   for (errn = 0; errn <= errnmax; errn++)
  802.     {
  803.       name = strerrno (errn);
  804.       name = (name == NULL) ? "<NULL>" : name;
  805.       msg = strerror (errn);
  806.       msg = (msg == NULL) ? "<NULL>" : msg;
  807.       printf ("%-4d%-18s%s\n", errn, name, msg);
  808.     }
  809. }
  810.  
  811. #endif
  812.