Rev 2714 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2714 | Rev 2782 | ||
---|---|---|---|
1 | /* $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $ */ |
1 | /* $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $ */ |
2 | 2 | ||
3 | /*- |
3 | /*- |
4 | * Copyright (c) 1991, 1993 |
4 | * Copyright (c) 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. |
5 | * The Regents of the University of California. All rights reserved. |
6 | * |
6 | * |
7 | * This code is derived from software contributed to Berkeley by |
7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. |
8 | * Kenneth Almquist. |
9 | * |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. All advertising materials mentioning features or use of this software |
18 | * 3. All advertising materials mentioning features or use of this software |
19 | * must display the following acknowledgement: |
19 | * must display the following acknowledgement: |
20 | * This product includes software developed by the University of |
20 | * This product includes software developed by the University of |
21 | * California, Berkeley and its contributors. |
21 | * California, Berkeley and its contributors. |
22 | * 4. Neither the name of the University nor the names of its contributors |
22 | * 4. Neither the name of the University nor the names of its contributors |
23 | * may be used to endorse or promote products derived from this software |
23 | * may be used to endorse or promote products derived from this software |
24 | * without specific prior written permission. |
24 | * without specific prior written permission. |
25 | * |
25 | * |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
36 | * SUCH DAMAGE. |
36 | * SUCH DAMAGE. |
37 | */ |
37 | */ |
38 | 38 | ||
39 | #include <sys/cdefs.h> |
39 | #include <sys/cdefs.h> |
40 | #ifndef lint |
40 | #ifndef lint |
41 | #if 0 |
41 | #if 0 |
42 | static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; |
42 | static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; |
43 | #else |
43 | #else |
44 | __RCSID("$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $"); |
44 | __RCSID("$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $"); |
45 | #endif |
45 | #endif |
46 | #endif /* not lint */ |
46 | #endif /* not lint */ |
47 | 47 | ||
48 | /* |
48 | /* |
49 | * Errors and exceptions. |
49 | * Errors and exceptions. |
50 | */ |
50 | */ |
51 | 51 | ||
52 | #include <signal.h> |
52 | #include <signal.h> |
53 | #include <stdlib.h> |
53 | #include <stdlib.h> |
54 | #include <unistd.h> |
54 | #include <unistd.h> |
55 | #include <errno.h> |
55 | #include <errno.h> |
56 | 56 | ||
57 | #include "shell.h" |
57 | #include "shell.h" |
58 | #include "main.h" |
58 | #include "main.h" |
59 | #include "options.h" |
59 | #include "options.h" |
60 | #include "output.h" |
60 | #include "output.h" |
61 | #include "error.h" |
61 | #include "error.h" |
62 | #include "show.h" |
62 | #include "show.h" |
63 | 63 | ||
64 | 64 | ||
65 | /* |
65 | /* |
66 | * Code to handle exceptions in C. |
66 | * Code to handle exceptions in C. |
67 | */ |
67 | */ |
68 | 68 | ||
69 | struct jmploc *handler; |
69 | struct jmploc *handler; |
70 | int exception; |
70 | int exception; |
71 | volatile int suppressint; |
71 | volatile int suppressint; |
72 | volatile int intpending; |
72 | volatile int intpending; |
73 | char *commandname; |
73 | char *commandname; |
74 | 74 | ||
75 | 75 | ||
76 | static void exverror (int, const char *, va_list) |
76 | static void exverror (int, const char *, va_list) |
77 | __attribute__((__noreturn__)); |
77 | __attribute__((__noreturn__)); |
78 | 78 | ||
79 | /* |
79 | /* |
80 | * Called to raise an exception. Since C doesn't include exceptions, we |
80 | * Called to raise an exception. Since C doesn't include exceptions, we |
81 | * just do a longjmp to the exception handler. The type of exception is |
81 | * just do a longjmp to the exception handler. The type of exception is |
82 | * stored in the global variable "exception". |
82 | * stored in the global variable "exception". |
83 | */ |
83 | */ |
84 | 84 | ||
85 | void |
85 | void |
86 | exraise(e) |
86 | exraise(e) |
87 | int e; |
87 | int e; |
88 | { |
88 | { |
89 | if (handler == NULL) |
89 | if (handler == NULL) |
90 | abort(); |
90 | abort(); |
91 | exception = e; |
91 | exception = e; |
92 | longjmp(handler->loc, 1); |
92 | longjmp(handler->loc, 1); |
93 | } |
93 | } |
94 | 94 | ||
95 | 95 | ||
96 | /* |
96 | /* |
97 | * Called from trap.c when a SIGINT is received. (If the user specifies |
97 | * Called from trap.c when a SIGINT is received. (If the user specifies |
98 | * that SIGINT is to be trapped or ignored using the trap builtin, then |
98 | * that SIGINT is to be trapped or ignored using the trap builtin, then |
99 | * this routine is not called.) Suppressint is nonzero when interrupts |
99 | * this routine is not called.) Suppressint is nonzero when interrupts |
100 | * are held using the INTOFF macro. The call to _exit is necessary because |
100 | * are held using the INTOFF macro. The call to _exit is necessary because |
101 | * there is a short period after a fork before the signal handlers are |
101 | * there is a short period after a fork before the signal handlers are |
102 | * set to the appropriate value for the child. (The test for iflag is |
102 | * set to the appropriate value for the child. (The test for iflag is |
103 | * just defensive programming.) |
103 | * just defensive programming.) |
104 | */ |
104 | */ |
105 | 105 | ||
106 | void |
106 | void |
107 | onint() { |
107 | onint() { |
108 | sigset_t sigset; |
108 | sigset_t sigset; |
109 | 109 | ||
110 | if (suppressint) { |
110 | if (suppressint) { |
111 | intpending++; |
111 | intpending++; |
112 | return; |
112 | return; |
113 | } |
113 | } |
114 | intpending = 0; |
114 | intpending = 0; |
115 | sigemptyset(&sigset); |
115 | sigemptyset(&sigset); |
116 | sigprocmask(SIG_SETMASK, &sigset, NULL); |
116 | sigprocmask(SIG_SETMASK, &sigset, NULL); |
117 | if (rootshell && iflag) |
117 | if (rootshell && iflag) |
118 | exraise(EXINT); |
118 | exraise(EXINT); |
119 | else { |
119 | else { |
120 | signal(SIGINT, SIG_DFL); |
120 | signal(SIGINT, SIG_DFL); |
121 | raise(SIGINT); |
121 | raise(SIGINT); |
122 | } |
122 | } |
123 | /* NOTREACHED */ |
123 | /* NOTREACHED */ |
124 | } |
124 | } |
125 | 125 | ||
126 | 126 | ||
127 | /* |
127 | /* |
128 | * Exverror is called to raise the error exception. If the first argument |
128 | * Exverror is called to raise the error exception. If the first argument |
129 | * is not NULL then error prints an error message using printf style |
129 | * is not NULL then error prints an error message using printf style |
130 | * formatting. It then raises the error exception. |
130 | * formatting. It then raises the error exception. |
131 | */ |
131 | */ |
132 | static void |
132 | static void |
133 | exverror(cond, msg, ap) |
133 | exverror(cond, msg, ap) |
134 | int cond; |
134 | int cond; |
135 | const char *msg; |
135 | const char *msg; |
136 | va_list ap; |
136 | va_list ap; |
137 | { |
137 | { |
138 | CLEAR_PENDING_INT; |
138 | CLEAR_PENDING_INT; |
139 | INTOFF; |
139 | INTOFF; |
140 | 140 | ||
141 | #ifdef DEBUG |
141 | #ifdef DEBUG |
142 | if (msg) |
142 | if (msg) |
143 | TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); |
143 | TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); |
144 | else |
144 | else |
145 | TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); |
145 | TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); |
146 | #endif |
146 | #endif |
147 | if (msg) { |
147 | if (msg) { |
148 | if (commandname) |
148 | if (commandname) |
149 | outfmt(&errout, "%s: ", commandname); |
149 | outfmt(&errout, "%s: ", commandname); |
150 | doformat(&errout, msg, ap); |
150 | doformat(&errout, msg, ap); |
151 | out2c('\n'); |
151 | out2c('\n'); |
152 | } |
152 | } |
153 | flushall(); |
153 | flushall(); |
154 | exraise(cond); |
154 | exraise(cond); |
155 | /* NOTREACHED */ |
155 | /* NOTREACHED */ |
156 | } |
156 | } |
157 | 157 | ||
158 | 158 | ||
159 | #ifdef __STDC__ |
159 | #ifdef __STDC__ |
160 | void |
160 | void |
161 | error(const char *msg, ...) |
161 | error(const char *msg, ...) |
162 | #else |
162 | #else |
163 | void |
163 | void |
164 | error(va_alist) |
164 | error(va_alist) |
165 | va_dcl |
165 | va_dcl |
166 | #endif |
166 | #endif |
167 | { |
167 | { |
168 | #ifndef __STDC__ |
168 | #ifndef __STDC__ |
169 | const char *msg; |
169 | const char *msg; |
170 | #endif |
170 | #endif |
171 | va_list ap; |
171 | va_list ap; |
172 | #ifdef __STDC__ |
172 | #ifdef __STDC__ |
173 | va_start(ap, msg); |
173 | va_start(ap, msg); |
174 | #else |
174 | #else |
175 | va_start(ap); |
175 | va_start(ap); |
176 | msg = va_arg(ap, const char *); |
176 | msg = va_arg(ap, const char *); |
177 | #endif |
177 | #endif |
178 | exverror(EXERROR, msg, ap); |
178 | exverror(EXERROR, msg, ap); |
179 | /* NOTREACHED */ |
179 | /* NOTREACHED */ |
180 | va_end(ap); |
180 | va_end(ap); |
181 | } |
181 | } |
182 | 182 | ||
183 | 183 | ||
184 | #ifdef __STDC__ |
184 | #ifdef __STDC__ |
185 | void |
185 | void |
186 | exerror(int cond, const char *msg, ...) |
186 | exerror(int cond, const char *msg, ...) |
187 | #else |
187 | #else |
188 | void |
188 | void |
189 | exerror(va_alist) |
189 | exerror(va_alist) |
190 | va_dcl |
190 | va_dcl |
191 | #endif |
191 | #endif |
192 | { |
192 | { |
193 | #ifndef __STDC__ |
193 | #ifndef __STDC__ |
194 | int cond; |
194 | int cond; |
195 | const char *msg; |
195 | const char *msg; |
196 | #endif |
196 | #endif |
197 | va_list ap; |
197 | va_list ap; |
198 | #ifdef __STDC__ |
198 | #ifdef __STDC__ |
199 | va_start(ap, msg); |
199 | va_start(ap, msg); |
200 | #else |
200 | #else |
201 | va_start(ap); |
201 | va_start(ap); |
202 | cond = va_arg(ap, int); |
202 | cond = va_arg(ap, int); |
203 | msg = va_arg(ap, const char *); |
203 | msg = va_arg(ap, const char *); |
204 | #endif |
204 | #endif |
205 | exverror(cond, msg, ap); |
205 | exverror(cond, msg, ap); |
206 | /* NOTREACHED */ |
206 | /* NOTREACHED */ |
207 | va_end(ap); |
207 | va_end(ap); |
208 | } |
208 | } |
209 | 209 | ||
210 | 210 | ||
211 | 211 | ||
212 | /* |
212 | /* |
213 | * Table of error messages. |
213 | * Table of error messages. |
214 | */ |
214 | */ |
215 | 215 | ||
216 | struct errname { |
216 | struct errname { |
217 | short errcode; /* error number */ |
217 | short errcode; /* error number */ |
218 | short action; /* operation which encountered the error */ |
218 | short action; /* operation which encountered the error */ |
219 | const char *msg; /* text describing the error */ |
219 | const char *msg; /* text describing the error */ |
220 | }; |
220 | }; |
221 | 221 | ||
222 | 222 | ||
223 | #define ALL (E_OPEN|E_CREAT|E_EXEC) |
223 | #define ALL (E_OPEN|E_CREAT|E_EXEC) |
224 | 224 | ||
225 | STATIC const struct errname errormsg[] = { |
225 | STATIC const struct errname errormsg[] = { |
226 | { EINTR, ALL, "interrupted" }, |
226 | { EINTR, ALL, "interrupted" }, |
227 | { EACCES, ALL, "permission denied" }, |
227 | { EACCES, ALL, "permission denied" }, |
228 | { EIO, ALL, "I/O error" }, |
228 | { EIO, ALL, "I/O error" }, |
229 | { ENOENT, E_OPEN, "no such file" }, |
229 | { ENOENT, E_OPEN, "no such file" }, |
230 | { ENOENT, E_CREAT,"directory nonexistent" }, |
230 | { ENOENT, E_CREAT,"directory nonexistent" }, |
231 | { ENOENT, E_EXEC, "not found" }, |
231 | { ENOENT, E_EXEC, "not found" }, |
232 | { ENOTDIR, E_OPEN, "no such file" }, |
232 | { ENOTDIR, E_OPEN, "no such file" }, |
233 | { ENOTDIR, E_CREAT,"directory nonexistent" }, |
233 | { ENOTDIR, E_CREAT,"directory nonexistent" }, |
234 | { ENOTDIR, E_EXEC, "not found" }, |
234 | { ENOTDIR, E_EXEC, "not found" }, |
235 | { EISDIR, ALL, "is a directory" }, |
235 | { EISDIR, ALL, "is a directory" }, |
236 | { EEXIST, E_CREAT,"file exists" }, |
236 | { EEXIST, E_CREAT,"file exists" }, |
237 | #ifdef notdef |
237 | #ifdef notdef |
238 | { EMFILE, ALL, "too many open files" }, |
238 | { EMFILE, ALL, "too many open files" }, |
239 | #endif |
239 | #endif |
240 | { ENFILE, ALL, "file table overflow" }, |
240 | { ENFILE, ALL, "file table overflow" }, |
241 | { ENOSPC, ALL, "file system full" }, |
241 | { ENOSPC, ALL, "file system full" }, |
242 | #ifdef EDQUOT |
242 | #ifdef EDQUOT |
243 | { EDQUOT, ALL, "disk quota exceeded" }, |
243 | { EDQUOT, ALL, "disk quota exceeded" }, |
244 | #endif |
244 | #endif |
245 | #ifdef ENOSR |
245 | #ifdef ENOSR |
246 | { ENOSR, ALL, "no streams resources" }, |
246 | { ENOSR, ALL, "no streams resources" }, |
247 | #endif |
247 | #endif |
248 | { ENXIO, ALL, "no such device or address" }, |
248 | { ENXIO, ALL, "no such device or address" }, |
249 | { EROFS, ALL, "read-only file system" }, |
249 | { EROFS, ALL, "read-only file system" }, |
250 | { ETXTBSY, ALL, "text busy" }, |
250 | { ETXTBSY, ALL, "text busy" }, |
251 | #ifdef SYSV |
251 | #ifdef SYSV |
252 | { EAGAIN, E_EXEC, "not enough memory" }, |
252 | { EAGAIN, E_EXEC, "not enough memory" }, |
253 | #endif |
253 | #endif |
254 | { ENOMEM, ALL, "not enough memory" }, |
254 | { ENOMEM, ALL, "not enough memory" }, |
255 | #ifdef ENOLINK |
255 | #ifdef ENOLINK |
256 | { ENOLINK, ALL, "remote access failed" }, |
256 | { ENOLINK, ALL, "remote access failed" }, |
257 | #endif |
257 | #endif |
258 | #ifdef EMULTIHOP |
258 | #ifdef EMULTIHOP |
259 | { EMULTIHOP, ALL, "remote access failed" }, |
259 | { EMULTIHOP, ALL, "remote access failed" }, |
260 | #endif |
260 | #endif |
261 | #ifdef ECOMM |
261 | #ifdef ECOMM |
262 | { ECOMM, ALL, "remote access failed" }, |
262 | { ECOMM, ALL, "remote access failed" }, |
263 | #endif |
263 | #endif |
264 | #ifdef ESTALE |
264 | #ifdef ESTALE |
265 | { ESTALE, ALL, "remote access failed" }, |
265 | { ESTALE, ALL, "remote access failed" }, |
266 | #endif |
266 | #endif |
267 | #ifdef ETIMEDOUT |
267 | #ifdef ETIMEDOUT |
268 | { ETIMEDOUT, ALL, "remote access failed" }, |
268 | { ETIMEDOUT, ALL, "remote access failed" }, |
269 | #endif |
269 | #endif |
270 | #ifdef ELOOP |
270 | #ifdef ELOOP |
271 | { ELOOP, ALL, "symbolic link loop" }, |
271 | { ELOOP, ALL, "symbolic link loop" }, |
272 | #endif |
272 | #endif |
273 | { E2BIG, E_EXEC, "argument list too long" }, |
273 | { E2BIG, E_EXEC, "argument list too long" }, |
274 | #ifdef ELIBACC |
274 | #ifdef ELIBACC |
275 | { ELIBACC, E_EXEC, "shared library missing" }, |
275 | { ELIBACC, E_EXEC, "shared library missing" }, |
276 | #endif |
276 | #endif |
277 | { 0, 0, NULL }, |
277 | { 0, 0, NULL }, |
278 | }; |
278 | }; |
279 | 279 | ||
280 | 280 | ||
281 | /* |
281 | /* |
282 | * Return a string describing an error. The returned string may be a |
282 | * Return a string describing an error. The returned string may be a |
283 | * pointer to a static buffer that will be overwritten on the next call. |
283 | * pointer to a static buffer that will be overwritten on the next call. |
284 | * Action describes the operation that got the error. |
284 | * Action describes the operation that got the error. |
285 | */ |
285 | */ |
286 | 286 | ||
287 | const char * |
287 | const char * |
288 | errmsg(e, action) |
288 | errmsg(e, action) |
289 | int e; |
289 | int e; |
290 | int action; |
290 | int action; |
291 | { |
291 | { |
292 | struct errname const *ep; |
292 | struct errname const *ep; |
293 | static char buf[12]; |
293 | static char buf[12]; |
294 | 294 | ||
295 | for (ep = errormsg ; ep->errcode ; ep++) { |
295 | for (ep = errormsg ; ep->errcode ; ep++) { |
296 | if (ep->errcode == e && (ep->action & action) != 0) |
296 | if (ep->errcode == e && (ep->action & action) != 0) |
297 | return ep->msg; |
297 | return ep->msg; |
298 | } |
298 | } |
299 | fmtstr(buf, sizeof buf, "error %d", e); |
299 | fmtstr(buf, sizeof buf, "error %d", e); |
300 | return buf; |
300 | return buf; |
301 | } |
301 | } |
302 | 302 |