1169695Skan/* Extended support for using errno values.
2169695Skan   Written by Fred Fish.  fnf@cygnus.com
3169695Skan   This file is in the public domain.  --Per Bothner.  */
4169695Skan
5169695Skan#include "config.h"
6169695Skan
7169695Skan#ifdef HAVE_SYS_ERRLIST
8169695Skan/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
9169695Skan   might declare sys_errlist in a way that the compiler might consider
10169695Skan   incompatible with our later declaration, perhaps by using const
11169695Skan   attributes.  So we hide the declaration in errno.h (if any) using a
12169695Skan   macro. */
13169695Skan#define sys_nerr sys_nerr__
14169695Skan#define sys_errlist sys_errlist__
15169695Skan#endif
16169695Skan
17169695Skan#include "ansidecl.h"
18169695Skan#include "libiberty.h"
19169695Skan
20169695Skan#include <stdio.h>
21169695Skan#include <errno.h>
22169695Skan
23169695Skan#ifdef HAVE_SYS_ERRLIST
24169695Skan#undef sys_nerr
25169695Skan#undef sys_errlist
26169695Skan#endif
27169695Skan
28169695Skan/*  Routines imported from standard C runtime libraries. */
29169695Skan
30169695Skan#ifdef HAVE_STDLIB_H
31169695Skan#include <stdlib.h>
32169695Skan#else
33169695Skanextern PTR malloc ();
34169695Skan#endif
35169695Skan
36169695Skan#ifdef HAVE_STRING_H
37169695Skan#include <string.h>
38169695Skan#else
39169695Skanextern PTR memset ();
40169695Skan#endif
41169695Skan
42169695Skan#ifndef MAX
43169695Skan#  define MAX(a,b) ((a) > (b) ? (a) : (b))
44169695Skan#endif
45169695Skan
46169695Skanstatic void init_error_tables (void);
47169695Skan
48169695Skan/* Translation table for errno values.  See intro(2) in most UNIX systems
49169695Skan   Programmers Reference Manuals.
50169695Skan
51169695Skan   Note that this table is generally only accessed when it is used at runtime
52169695Skan   to initialize errno name and message tables that are indexed by errno
53169695Skan   value.
54169695Skan
55169695Skan   Not all of these errnos will exist on all systems.  This table is the only
56169695Skan   thing that should have to be updated as new error numbers are introduced.
57169695Skan   It's sort of ugly, but at least its portable. */
58169695Skan
59169695Skanstruct error_info
60169695Skan{
61169695Skan  const int value;		/* The numeric value from <errno.h> */
62169695Skan  const char *const name;	/* The equivalent symbolic value */
63169695Skan#ifndef HAVE_SYS_ERRLIST
64169695Skan  const char *const msg;	/* Short message about this value */
65169695Skan#endif
66169695Skan};
67169695Skan
68169695Skan#ifndef HAVE_SYS_ERRLIST
69169695Skan#   define ENTRY(value, name, msg)	{value, name, msg}
70169695Skan#else
71169695Skan#   define ENTRY(value, name, msg)	{value, name}
72169695Skan#endif
73169695Skan
74169695Skanstatic const struct error_info error_table[] =
75169695Skan{
76169695Skan#if defined (EPERM)
77169695Skan  ENTRY(EPERM, "EPERM", "Not owner"),
78169695Skan#endif
79169695Skan#if defined (ENOENT)
80169695Skan  ENTRY(ENOENT, "ENOENT", "No such file or directory"),
81169695Skan#endif
82169695Skan#if defined (ESRCH)
83169695Skan  ENTRY(ESRCH, "ESRCH", "No such process"),
84169695Skan#endif
85169695Skan#if defined (EINTR)
86169695Skan  ENTRY(EINTR, "EINTR", "Interrupted system call"),
87169695Skan#endif
88169695Skan#if defined (EIO)
89169695Skan  ENTRY(EIO, "EIO", "I/O error"),
90169695Skan#endif
91169695Skan#if defined (ENXIO)
92169695Skan  ENTRY(ENXIO, "ENXIO", "No such device or address"),
93169695Skan#endif
94169695Skan#if defined (E2BIG)
95169695Skan  ENTRY(E2BIG, "E2BIG", "Arg list too long"),
96169695Skan#endif
97169695Skan#if defined (ENOEXEC)
98169695Skan  ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
99169695Skan#endif
100169695Skan#if defined (EBADF)
101169695Skan  ENTRY(EBADF, "EBADF", "Bad file number"),
102169695Skan#endif
103169695Skan#if defined (ECHILD)
104169695Skan  ENTRY(ECHILD, "ECHILD", "No child processes"),
105169695Skan#endif
106169695Skan#if defined (EWOULDBLOCK)	/* Put before EAGAIN, sometimes aliased */
107169695Skan  ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
108169695Skan#endif
109169695Skan#if defined (EAGAIN)
110169695Skan  ENTRY(EAGAIN, "EAGAIN", "No more processes"),
111169695Skan#endif
112169695Skan#if defined (ENOMEM)
113169695Skan  ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
114169695Skan#endif
115169695Skan#if defined (EACCES)
116169695Skan  ENTRY(EACCES, "EACCES", "Permission denied"),
117169695Skan#endif
118169695Skan#if defined (EFAULT)
119169695Skan  ENTRY(EFAULT, "EFAULT", "Bad address"),
120169695Skan#endif
121169695Skan#if defined (ENOTBLK)
122169695Skan  ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
123169695Skan#endif
124169695Skan#if defined (EBUSY)
125169695Skan  ENTRY(EBUSY, "EBUSY", "Device busy"),
126169695Skan#endif
127169695Skan#if defined (EEXIST)
128169695Skan  ENTRY(EEXIST, "EEXIST", "File exists"),
129169695Skan#endif
130169695Skan#if defined (EXDEV)
131169695Skan  ENTRY(EXDEV, "EXDEV", "Cross-device link"),
132169695Skan#endif
133169695Skan#if defined (ENODEV)
134169695Skan  ENTRY(ENODEV, "ENODEV", "No such device"),
135169695Skan#endif
136169695Skan#if defined (ENOTDIR)
137169695Skan  ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
138169695Skan#endif
139169695Skan#if defined (EISDIR)
140169695Skan  ENTRY(EISDIR, "EISDIR", "Is a directory"),
141169695Skan#endif
142169695Skan#if defined (EINVAL)
143169695Skan  ENTRY(EINVAL, "EINVAL", "Invalid argument"),
144169695Skan#endif
145169695Skan#if defined (ENFILE)
146169695Skan  ENTRY(ENFILE, "ENFILE", "File table overflow"),
147169695Skan#endif
148169695Skan#if defined (EMFILE)
149169695Skan  ENTRY(EMFILE, "EMFILE", "Too many open files"),
150169695Skan#endif
151169695Skan#if defined (ENOTTY)
152169695Skan  ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
153169695Skan#endif
154169695Skan#if defined (ETXTBSY)
155169695Skan  ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
156169695Skan#endif
157169695Skan#if defined (EFBIG)
158169695Skan  ENTRY(EFBIG, "EFBIG", "File too large"),
159169695Skan#endif
160169695Skan#if defined (ENOSPC)
161169695Skan  ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
162169695Skan#endif
163169695Skan#if defined (ESPIPE)
164169695Skan  ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
165169695Skan#endif
166169695Skan#if defined (EROFS)
167169695Skan  ENTRY(EROFS, "EROFS", "Read-only file system"),
168169695Skan#endif
169169695Skan#if defined (EMLINK)
170169695Skan  ENTRY(EMLINK, "EMLINK", "Too many links"),
171169695Skan#endif
172169695Skan#if defined (EPIPE)
173169695Skan  ENTRY(EPIPE, "EPIPE", "Broken pipe"),
174169695Skan#endif
175169695Skan#if defined (EDOM)
176169695Skan  ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
177169695Skan#endif
178169695Skan#if defined (ERANGE)
179169695Skan  ENTRY(ERANGE, "ERANGE", "Math result not representable"),
180169695Skan#endif
181169695Skan#if defined (ENOMSG)
182169695Skan  ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
183169695Skan#endif
184169695Skan#if defined (EIDRM)
185169695Skan  ENTRY(EIDRM, "EIDRM", "Identifier removed"),
186169695Skan#endif
187169695Skan#if defined (ECHRNG)
188169695Skan  ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
189169695Skan#endif
190169695Skan#if defined (EL2NSYNC)
191169695Skan  ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
192169695Skan#endif
193169695Skan#if defined (EL3HLT)
194169695Skan  ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
195169695Skan#endif
196169695Skan#if defined (EL3RST)
197169695Skan  ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
198169695Skan#endif
199169695Skan#if defined (ELNRNG)
200169695Skan  ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
201169695Skan#endif
202169695Skan#if defined (EUNATCH)
203169695Skan  ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
204169695Skan#endif
205169695Skan#if defined (ENOCSI)
206169695Skan  ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
207169695Skan#endif
208169695Skan#if defined (EL2HLT)
209169695Skan  ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
210169695Skan#endif
211169695Skan#if defined (EDEADLK)
212169695Skan  ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
213169695Skan#endif
214169695Skan#if defined (ENOLCK)
215169695Skan  ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
216169695Skan#endif
217169695Skan#if defined (EBADE)
218169695Skan  ENTRY(EBADE, "EBADE", "Invalid exchange"),
219169695Skan#endif
220169695Skan#if defined (EBADR)
221169695Skan  ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
222169695Skan#endif
223169695Skan#if defined (EXFULL)
224169695Skan  ENTRY(EXFULL, "EXFULL", "Exchange full"),
225169695Skan#endif
226169695Skan#if defined (ENOANO)
227169695Skan  ENTRY(ENOANO, "ENOANO", "No anode"),
228169695Skan#endif
229169695Skan#if defined (EBADRQC)
230169695Skan  ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
231169695Skan#endif
232169695Skan#if defined (EBADSLT)
233169695Skan  ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
234169695Skan#endif
235169695Skan#if defined (EDEADLOCK)
236169695Skan  ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
237169695Skan#endif
238169695Skan#if defined (EBFONT)
239169695Skan  ENTRY(EBFONT, "EBFONT", "Bad font file format"),
240169695Skan#endif
241169695Skan#if defined (ENOSTR)
242169695Skan  ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
243169695Skan#endif
244169695Skan#if defined (ENODATA)
245169695Skan  ENTRY(ENODATA, "ENODATA", "No data available"),
246169695Skan#endif
247169695Skan#if defined (ETIME)
248169695Skan  ENTRY(ETIME, "ETIME", "Timer expired"),
249169695Skan#endif
250169695Skan#if defined (ENOSR)
251169695Skan  ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
252169695Skan#endif
253169695Skan#if defined (ENONET)
254169695Skan  ENTRY(ENONET, "ENONET", "Machine is not on the network"),
255169695Skan#endif
256169695Skan#if defined (ENOPKG)
257169695Skan  ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
258169695Skan#endif
259169695Skan#if defined (EREMOTE)
260169695Skan  ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
261169695Skan#endif
262169695Skan#if defined (ENOLINK)
263169695Skan  ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
264169695Skan#endif
265169695Skan#if defined (EADV)
266169695Skan  ENTRY(EADV, "EADV", "Advertise error"),
267169695Skan#endif
268169695Skan#if defined (ESRMNT)
269169695Skan  ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
270169695Skan#endif
271169695Skan#if defined (ECOMM)
272169695Skan  ENTRY(ECOMM, "ECOMM", "Communication error on send"),
273169695Skan#endif
274169695Skan#if defined (EPROTO)
275169695Skan  ENTRY(EPROTO, "EPROTO", "Protocol error"),
276169695Skan#endif
277169695Skan#if defined (EMULTIHOP)
278169695Skan  ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
279169695Skan#endif
280169695Skan#if defined (EDOTDOT)
281169695Skan  ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
282169695Skan#endif
283169695Skan#if defined (EBADMSG)
284169695Skan  ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
285169695Skan#endif
286169695Skan#if defined (ENAMETOOLONG)
287169695Skan  ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
288169695Skan#endif
289169695Skan#if defined (EOVERFLOW)
290169695Skan  ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
291169695Skan#endif
292169695Skan#if defined (ENOTUNIQ)
293169695Skan  ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
294169695Skan#endif
295169695Skan#if defined (EBADFD)
296169695Skan  ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
297169695Skan#endif
298169695Skan#if defined (EREMCHG)
299169695Skan  ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
300169695Skan#endif
301169695Skan#if defined (ELIBACC)
302169695Skan  ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
303169695Skan#endif
304169695Skan#if defined (ELIBBAD)
305169695Skan  ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
306169695Skan#endif
307169695Skan#if defined (ELIBSCN)
308169695Skan  ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
309169695Skan#endif
310169695Skan#if defined (ELIBMAX)
311169695Skan  ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
312169695Skan#endif
313169695Skan#if defined (ELIBEXEC)
314169695Skan  ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
315169695Skan#endif
316169695Skan#if defined (EILSEQ)
317169695Skan  ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
318169695Skan#endif
319169695Skan#if defined (ENOSYS)
320169695Skan  ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
321169695Skan#endif
322169695Skan#if defined (ELOOP)
323169695Skan  ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
324169695Skan#endif
325169695Skan#if defined (ERESTART)
326169695Skan  ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
327169695Skan#endif
328169695Skan#if defined (ESTRPIPE)
329169695Skan  ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
330169695Skan#endif
331169695Skan#if defined (ENOTEMPTY)
332169695Skan  ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
333169695Skan#endif
334169695Skan#if defined (EUSERS)
335169695Skan  ENTRY(EUSERS, "EUSERS", "Too many users"),
336169695Skan#endif
337169695Skan#if defined (ENOTSOCK)
338169695Skan  ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
339169695Skan#endif
340169695Skan#if defined (EDESTADDRREQ)
341169695Skan  ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
342169695Skan#endif
343169695Skan#if defined (EMSGSIZE)
344169695Skan  ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
345169695Skan#endif
346169695Skan#if defined (EPROTOTYPE)
347169695Skan  ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
348169695Skan#endif
349169695Skan#if defined (ENOPROTOOPT)
350169695Skan  ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
351169695Skan#endif
352169695Skan#if defined (EPROTONOSUPPORT)
353169695Skan  ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
354169695Skan#endif
355169695Skan#if defined (ESOCKTNOSUPPORT)
356169695Skan  ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
357169695Skan#endif
358169695Skan#if defined (EOPNOTSUPP)
359169695Skan  ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
360169695Skan#endif
361169695Skan#if defined (EPFNOSUPPORT)
362169695Skan  ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
363169695Skan#endif
364169695Skan#if defined (EAFNOSUPPORT)
365169695Skan  ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
366169695Skan#endif
367169695Skan#if defined (EADDRINUSE)
368169695Skan  ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
369169695Skan#endif
370169695Skan#if defined (EADDRNOTAVAIL)
371169695Skan  ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
372169695Skan#endif
373169695Skan#if defined (ENETDOWN)
374169695Skan  ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
375169695Skan#endif
376169695Skan#if defined (ENETUNREACH)
377169695Skan  ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
378169695Skan#endif
379169695Skan#if defined (ENETRESET)
380169695Skan  ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
381169695Skan#endif
382169695Skan#if defined (ECONNABORTED)
383169695Skan  ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
384169695Skan#endif
385169695Skan#if defined (ECONNRESET)
386169695Skan  ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
387169695Skan#endif
388169695Skan#if defined (ENOBUFS)
389169695Skan  ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
390169695Skan#endif
391169695Skan#if defined (EISCONN)
392169695Skan  ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
393169695Skan#endif
394169695Skan#if defined (ENOTCONN)
395169695Skan  ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
396169695Skan#endif
397169695Skan#if defined (ESHUTDOWN)
398169695Skan  ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
399169695Skan#endif
400169695Skan#if defined (ETOOMANYREFS)
401169695Skan  ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
402169695Skan#endif
403169695Skan#if defined (ETIMEDOUT)
404169695Skan  ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
405169695Skan#endif
406169695Skan#if defined (ECONNREFUSED)
407169695Skan  ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
408169695Skan#endif
409169695Skan#if defined (EHOSTDOWN)
410169695Skan  ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
411169695Skan#endif
412169695Skan#if defined (EHOSTUNREACH)
413169695Skan  ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
414169695Skan#endif
415169695Skan#if defined (EALREADY)
416169695Skan  ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
417169695Skan#endif
418169695Skan#if defined (EINPROGRESS)
419169695Skan  ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
420169695Skan#endif
421169695Skan#if defined (ESTALE)
422169695Skan  ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
423169695Skan#endif
424169695Skan#if defined (EUCLEAN)
425169695Skan  ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
426169695Skan#endif
427169695Skan#if defined (ENOTNAM)
428169695Skan  ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
429169695Skan#endif
430169695Skan#if defined (ENAVAIL)
431169695Skan  ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
432169695Skan#endif
433169695Skan#if defined (EISNAM)
434169695Skan  ENTRY(EISNAM, "EISNAM", "Is a named type file"),
435169695Skan#endif
436169695Skan#if defined (EREMOTEIO)
437169695Skan  ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
438169695Skan#endif
439169695Skan  ENTRY(0, NULL, NULL)
440169695Skan};
441169695Skan
442169695Skan#ifdef EVMSERR
443169695Skan/* This is not in the table, because the numeric value of EVMSERR (32767)
444169695Skan   lies outside the range of sys_errlist[].  */
445169695Skanstatic struct { int value; const char *name, *msg; }
446169695Skan  evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
447169695Skan#endif
448169695Skan
449169695Skan/* Translation table allocated and initialized at runtime.  Indexed by the
450169695Skan   errno value to find the equivalent symbolic value. */
451169695Skan
452169695Skanstatic const char **error_names;
453169695Skanstatic int num_error_names = 0;
454169695Skan
455169695Skan/* Translation table allocated and initialized at runtime, if it does not
456169695Skan   already exist in the host environment.  Indexed by the errno value to find
457169695Skan   the descriptive string.
458169695Skan
459169695Skan   We don't export it for use in other modules because even though it has the
460169695Skan   same name, it differs from other implementations in that it is dynamically
461169695Skan   initialized rather than statically initialized. */
462169695Skan
463169695Skan#ifndef HAVE_SYS_ERRLIST
464169695Skan
465169695Skan#define sys_nerr sys_nerr__
466169695Skan#define sys_errlist sys_errlist__
467169695Skanstatic int sys_nerr;
468169695Skanstatic const char **sys_errlist;
469169695Skan
470169695Skan#else
471169695Skan
472169695Skanextern int sys_nerr;
473169695Skanextern char *sys_errlist[];
474169695Skan
475169695Skan#endif
476169695Skan
477169695Skan/*
478169695Skan
479169695SkanNAME
480169695Skan
481169695Skan	init_error_tables -- initialize the name and message tables
482169695Skan
483169695SkanSYNOPSIS
484169695Skan
485169695Skan	static void init_error_tables ();
486169695Skan
487169695SkanDESCRIPTION
488169695Skan
489169695Skan	Using the error_table, which is initialized at compile time, generate
490169695Skan	the error_names and the sys_errlist (if needed) tables, which are
491169695Skan	indexed at runtime by a specific errno value.
492169695Skan
493169695SkanBUGS
494169695Skan
495169695Skan	The initialization of the tables may fail under low memory conditions,
496169695Skan	in which case we don't do anything particularly useful, but we don't
497169695Skan	bomb either.  Who knows, it might succeed at a later point if we free
498169695Skan	some memory in the meantime.  In any case, the other routines know
499169695Skan	how to deal with lack of a table after trying to initialize it.  This
500169695Skan	may or may not be considered to be a bug, that we don't specifically
501169695Skan	warn about this particular failure mode.
502169695Skan
503169695Skan*/
504169695Skan
505169695Skanstatic void
506169695Skaninit_error_tables (void)
507169695Skan{
508169695Skan  const struct error_info *eip;
509169695Skan  int nbytes;
510169695Skan
511169695Skan  /* If we haven't already scanned the error_table once to find the maximum
512169695Skan     errno value, then go find it now. */
513169695Skan
514169695Skan  if (num_error_names == 0)
515169695Skan    {
516169695Skan      for (eip = error_table; eip -> name != NULL; eip++)
517169695Skan	{
518169695Skan	  if (eip -> value >= num_error_names)
519169695Skan	    {
520169695Skan	      num_error_names = eip -> value + 1;
521169695Skan	    }
522169695Skan	}
523169695Skan    }
524169695Skan
525169695Skan  /* Now attempt to allocate the error_names table, zero it out, and then
526169695Skan     initialize it from the statically initialized error_table. */
527169695Skan
528169695Skan  if (error_names == NULL)
529169695Skan    {
530169695Skan      nbytes = num_error_names * sizeof (char *);
531169695Skan      if ((error_names = (const char **) malloc (nbytes)) != NULL)
532169695Skan	{
533169695Skan	  memset (error_names, 0, nbytes);
534169695Skan	  for (eip = error_table; eip -> name != NULL; eip++)
535169695Skan	    {
536169695Skan	      error_names[eip -> value] = eip -> name;
537169695Skan	    }
538169695Skan	}
539169695Skan    }
540169695Skan
541169695Skan#ifndef HAVE_SYS_ERRLIST
542169695Skan
543169695Skan  /* Now attempt to allocate the sys_errlist table, zero it out, and then
544169695Skan     initialize it from the statically initialized error_table. */
545169695Skan
546169695Skan  if (sys_errlist == NULL)
547169695Skan    {
548169695Skan      nbytes = num_error_names * sizeof (char *);
549169695Skan      if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
550169695Skan	{
551169695Skan	  memset (sys_errlist, 0, nbytes);
552169695Skan	  sys_nerr = num_error_names;
553169695Skan	  for (eip = error_table; eip -> name != NULL; eip++)
554169695Skan	    {
555169695Skan	      sys_errlist[eip -> value] = eip -> msg;
556169695Skan	    }
557169695Skan	}
558169695Skan    }
559169695Skan
560169695Skan#endif
561169695Skan
562169695Skan}
563169695Skan
564169695Skan/*
565169695Skan
566169695Skan
567169695Skan@deftypefn Extension int errno_max (void)
568169695Skan
569169695SkanReturns the maximum @code{errno} value for which a corresponding
570169695Skansymbolic name or message is available.  Note that in the case where we
571169695Skanuse the @code{sys_errlist} supplied by the system, it is possible for
572169695Skanthere to be more symbolic names than messages, or vice versa.  In
573169695Skanfact, the manual page for @code{perror(3C)} explicitly warns that one
574169695Skanshould check the size of the table (@code{sys_nerr}) before indexing
575169695Skanit, since new error codes may be added to the system before they are
576169695Skanadded to the table.  Thus @code{sys_nerr} might be smaller than value
577169695Skanimplied by the largest @code{errno} value defined in @code{<errno.h>}.
578169695Skan
579169695SkanWe return the maximum value that can be used to obtain a meaningful
580169695Skansymbolic name or message.
581169695Skan
582169695Skan@end deftypefn
583169695Skan
584169695Skan*/
585169695Skan
586169695Skanint
587169695Skanerrno_max (void)
588169695Skan{
589169695Skan  int maxsize;
590169695Skan
591169695Skan  if (error_names == NULL)
592169695Skan    {
593169695Skan      init_error_tables ();
594169695Skan    }
595169695Skan  maxsize = MAX (sys_nerr, num_error_names);
596169695Skan  return (maxsize - 1);
597169695Skan}
598169695Skan
599169695Skan#ifndef HAVE_STRERROR
600169695Skan
601169695Skan/*
602169695Skan
603169695Skan@deftypefn Supplemental char* strerror (int @var{errnoval})
604169695Skan
605169695SkanMaps an @code{errno} number to an error message string, the contents
606169695Skanof which are implementation defined.  On systems which have the
607169695Skanexternal variables @code{sys_nerr} and @code{sys_errlist}, these
608169695Skanstrings will be the same as the ones used by @code{perror}.
609169695Skan
610169695SkanIf the supplied error number is within the valid range of indices for
611169695Skanthe @code{sys_errlist}, but no message is available for the particular
612169695Skanerror number, then returns the string @samp{Error @var{num}}, where
613169695Skan@var{num} is the error number.
614169695Skan
615169695SkanIf the supplied error number is not a valid index into
616169695Skan@code{sys_errlist}, returns @code{NULL}.
617169695Skan
618169695SkanThe returned string is only guaranteed to be valid only until the
619169695Skannext call to @code{strerror}.
620169695Skan
621169695Skan@end deftypefn
622169695Skan
623169695Skan*/
624169695Skan
625169695Skanchar *
626169695Skanstrerror (int errnoval)
627169695Skan{
628169695Skan  const char *msg;
629169695Skan  static char buf[32];
630169695Skan
631169695Skan#ifndef HAVE_SYS_ERRLIST
632169695Skan
633169695Skan  if (error_names == NULL)
634169695Skan    {
635169695Skan      init_error_tables ();
636169695Skan    }
637169695Skan
638169695Skan#endif
639169695Skan
640169695Skan  if ((errnoval < 0) || (errnoval >= sys_nerr))
641169695Skan    {
642169695Skan#ifdef EVMSERR
643169695Skan      if (errnoval == evmserr.value)
644169695Skan	msg = evmserr.msg;
645169695Skan      else
646169695Skan#endif
647169695Skan      /* Out of range, just return NULL */
648169695Skan      msg = NULL;
649169695Skan    }
650169695Skan  else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
651169695Skan    {
652169695Skan      /* In range, but no sys_errlist or no entry at this index. */
653169695Skan      sprintf (buf, "Error %d", errnoval);
654169695Skan      msg = buf;
655169695Skan    }
656169695Skan  else
657169695Skan    {
658169695Skan      /* In range, and a valid message.  Just return the message. */
659169695Skan      msg = (char *) sys_errlist[errnoval];
660169695Skan    }
661169695Skan
662169695Skan  return (msg);
663169695Skan}
664169695Skan
665169695Skan#endif	/* ! HAVE_STRERROR */
666169695Skan
667169695Skan
668169695Skan/*
669169695Skan
670169695Skan@deftypefn Replacement {const char*} strerrno (int @var{errnum})
671169695Skan
672169695SkanGiven an error number returned from a system call (typically returned
673169695Skanin @code{errno}), returns a pointer to a string containing the
674169695Skansymbolic name of that error number, as found in @code{<errno.h>}.
675169695Skan
676169695SkanIf the supplied error number is within the valid range of indices for
677169695Skansymbolic names, but no name is available for the particular error
678169695Skannumber, then returns the string @samp{Error @var{num}}, where @var{num}
679169695Skanis the error number.
680169695Skan
681169695SkanIf the supplied error number is not within the range of valid
682169695Skanindices, then returns @code{NULL}.
683169695Skan
684169695SkanThe contents of the location pointed to are only guaranteed to be
685169695Skanvalid until the next call to @code{strerrno}.
686169695Skan
687169695Skan@end deftypefn
688169695Skan
689169695Skan*/
690169695Skan
691169695Skanconst char *
692169695Skanstrerrno (int errnoval)
693169695Skan{
694169695Skan  const char *name;
695169695Skan  static char buf[32];
696169695Skan
697169695Skan  if (error_names == NULL)
698169695Skan    {
699169695Skan      init_error_tables ();
700169695Skan    }
701169695Skan
702169695Skan  if ((errnoval < 0) || (errnoval >= num_error_names))
703169695Skan    {
704169695Skan#ifdef EVMSERR
705169695Skan      if (errnoval == evmserr.value)
706169695Skan	name = evmserr.name;
707169695Skan      else
708169695Skan#endif
709169695Skan      /* Out of range, just return NULL */
710169695Skan      name = NULL;
711169695Skan    }
712169695Skan  else if ((error_names == NULL) || (error_names[errnoval] == NULL))
713169695Skan    {
714169695Skan      /* In range, but no error_names or no entry at this index. */
715169695Skan      sprintf (buf, "Error %d", errnoval);
716169695Skan      name = (const char *) buf;
717169695Skan    }
718169695Skan  else
719169695Skan    {
720169695Skan      /* In range, and a valid name.  Just return the name. */
721169695Skan      name = error_names[errnoval];
722169695Skan    }
723169695Skan
724169695Skan  return (name);
725169695Skan}
726169695Skan
727169695Skan/*
728169695Skan
729169695Skan@deftypefn Extension int strtoerrno (const char *@var{name})
730169695Skan
731169695SkanGiven the symbolic name of a error number (e.g., @code{EACCES}), map it
732169695Skanto an errno value.  If no translation is found, returns 0.
733169695Skan
734169695Skan@end deftypefn
735169695Skan
736169695Skan*/
737169695Skan
738169695Skanint
739169695Skanstrtoerrno (const char *name)
740169695Skan{
741169695Skan  int errnoval = 0;
742169695Skan
743169695Skan  if (name != NULL)
744169695Skan    {
745169695Skan      if (error_names == NULL)
746169695Skan	{
747169695Skan	  init_error_tables ();
748169695Skan	}
749169695Skan      for (errnoval = 0; errnoval < num_error_names; errnoval++)
750169695Skan	{
751169695Skan	  if ((error_names[errnoval] != NULL) &&
752169695Skan	      (strcmp (name, error_names[errnoval]) == 0))
753169695Skan	    {
754169695Skan	      break;
755169695Skan	    }
756169695Skan	}
757169695Skan      if (errnoval == num_error_names)
758169695Skan	{
759169695Skan#ifdef EVMSERR
760169695Skan	  if (strcmp (name, evmserr.name) == 0)
761169695Skan	    errnoval = evmserr.value;
762169695Skan	  else
763169695Skan#endif
764169695Skan	  errnoval = 0;
765169695Skan	}
766169695Skan    }
767169695Skan  return (errnoval);
768169695Skan}
769169695Skan
770169695Skan
771169695Skan/* A simple little main that does nothing but print all the errno translations
772169695Skan   if MAIN is defined and this file is compiled and linked. */
773169695Skan
774169695Skan#ifdef MAIN
775169695Skan
776169695Skan#include <stdio.h>
777169695Skan
778169695Skanint
779169695Skanmain (void)
780169695Skan{
781169695Skan  int errn;
782169695Skan  int errnmax;
783169695Skan  const char *name;
784169695Skan  const char *msg;
785169695Skan  char *strerror ();
786169695Skan
787169695Skan  errnmax = errno_max ();
788169695Skan  printf ("%d entries in names table.\n", num_error_names);
789169695Skan  printf ("%d entries in messages table.\n", sys_nerr);
790169695Skan  printf ("%d is max useful index.\n", errnmax);
791169695Skan
792169695Skan  /* Keep printing values until we get to the end of *both* tables, not
793169695Skan     *either* table.  Note that knowing the maximum useful index does *not*
794169695Skan     relieve us of the responsibility of testing the return pointer for
795169695Skan     NULL. */
796169695Skan
797169695Skan  for (errn = 0; errn <= errnmax; errn++)
798169695Skan    {
799169695Skan      name = strerrno (errn);
800169695Skan      name = (name == NULL) ? "<NULL>" : name;
801169695Skan      msg = strerror (errn);
802169695Skan      msg = (msg == NULL) ? "<NULL>" : msg;
803169695Skan      printf ("%-4d%-18s%s\n", errn, name, msg);
804169695Skan    }
805169695Skan
806169695Skan  return 0;
807169695Skan}
808169695Skan
809169695Skan#endif
810