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