Rev 5191 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5191 | serge | 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 |
||
21 | #include |
||
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 |
||
32 | #else |
||
33 | extern PTR malloc (); |
||
34 | #endif |
||
35 | |||
36 | #ifdef HAVE_STRING_H |
||
37 | #include |
||
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 |
||
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 | |||
6324 | serge | 472 | |
473 | #ifndef sys_nerr |
||
5191 | serge | 474 | extern int sys_nerr; |
6324 | serge | 475 | #endif |
476 | #ifndef sys_errlist |
||
5191 | serge | 477 | extern char *sys_errlist[]; |
6324 | serge | 478 | #endif |
5191 | serge | 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{ |
||
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{ |
||
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 |
||
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) ? " |
||
806 | msg = strerror (errn); |
||
807 | msg = (msg == NULL) ? " |
||
808 | printf ("%-4d%-18s%s\n", errn, name, msg); |
||
809 | } |
||
810 | |||
811 | return 0; |
||
812 | } |
||
813 | |||
814 | #endif=>>>> |