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