386BSD 0.1 development
[unix-history] / usr / src / bin / sh / error.c
CommitLineData
af3e82f7
WJ
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * 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
38static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
39#endif /* not lint */
40
41/*
42 * Errors and exceptions.
43 */
44
45#include "shell.h"
46#include "main.h"
47#include "options.h"
48#include "output.h"
49#include "error.h"
50#include <signal.h>
51#ifdef __STDC__
52#include "stdarg.h"
53#else
54#include <varargs.h>
55#endif
56#include <errno.h>
57
58
59/*
60 * Code to handle exceptions in C.
61 */
62
63struct jmploc *handler;
64int exception;
65volatile int suppressint;
66volatile int intpending;
67char *commandname;
68
69
70/*
71 * Called to raise an exception. Since C doesn't include exceptions, we
72 * just do a longjmp to the exception handler. The type of exception is
73 * stored in the global variable "exception".
74 */
75
76void
77exraise(e) {
78 if (handler == NULL)
79 abort();
80 exception = e;
81 longjmp(handler->loc, 1);
82}
83
84
85/*
86 * Called from trap.c when a SIGINT is received. (If the user specifies
87 * that SIGINT is to be trapped or ignored using the trap builtin, then
88 * this routine is not called.) Suppressint is nonzero when interrupts
89 * are held using the INTOFF macro. The call to _exit is necessary because
90 * there is a short period after a fork before the signal handlers are
91 * set to the appropriate value for the child. (The test for iflag is
92 * just defensive programming.)
93 */
94
95void
96onint() {
97 if (suppressint) {
98 intpending++;
99 return;
100 }
101 intpending = 0;
102#ifdef BSD
103 sigsetmask(0);
104#endif
105 if (rootshell && iflag)
106 exraise(EXINT);
107 else
108 _exit(128 + SIGINT);
109}
110
111
112
113void
114error2(a, b)
115 char *a, *b;
116 {
117 error("%s: %s", a, b);
118}
119
120
121/*
122 * Error is called to raise the error exception. If the first argument
123 * is not NULL then error prints an error message using printf style
124 * formatting. It then raises the error exception.
125 */
126
127#ifdef __STDC__
128void
129error(char *msg, ...) {
130#else
131void
132error(va_alist)
133 va_dcl
134 {
135 char *msg;
136#endif
137 va_list ap;
138
139 CLEAR_PENDING_INT;
140 INTOFF;
141#ifdef __STDC__
142 va_start(ap, msg);
143#else
144 va_start(ap);
145 msg = va_arg(ap, char *);
146#endif
147#ifdef DEBUG
148 if (msg)
149 TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
150 else
151 TRACE(("error(NULL) pid=%d\n", getpid()));
152#endif
153 if (msg) {
154 if (commandname)
155 outfmt(&errout, "%s: ", commandname);
156 doformat(&errout, msg, ap);
157 out2c('\n');
158 }
159 va_end(ap);
160 flushall();
161 exraise(EXERROR);
162}
163
164
165
166/*
167 * Table of error messages.
168 */
169
170struct errname {
171 short errcode; /* error number */
172 short action; /* operation which encountered the error */
173 char *msg; /* text describing the error */
174};
175
176
177#define ALL (E_OPEN|E_CREAT|E_EXEC)
178
179STATIC const struct errname errormsg[] = {
180 EINTR, ALL, "interrupted",
181 EACCES, ALL, "permission denied",
182 EIO, ALL, "I/O error",
183 ENOENT, E_OPEN, "no such file",
184 ENOENT, E_CREAT, "directory nonexistent",
185 ENOENT, E_EXEC, "not found",
186 ENOTDIR, E_OPEN, "no such file",
187 ENOTDIR, E_CREAT, "directory nonexistent",
188 ENOTDIR, E_EXEC, "not found",
189 EISDIR, ALL, "is a directory",
190/* EMFILE, ALL, "too many open files", */
191 ENFILE, ALL, "file table overflow",
192 ENOSPC, ALL, "file system full",
193#ifdef EDQUOT
194 EDQUOT, ALL, "disk quota exceeded",
195#endif
196#ifdef ENOSR
197 ENOSR, ALL, "no streams resources",
198#endif
199 ENXIO, ALL, "no such device or address",
200 EROFS, ALL, "read-only file system",
201 ETXTBSY, ALL, "text busy",
202#ifdef SYSV
203 EAGAIN, E_EXEC, "not enough memory",
204#endif
205 ENOMEM, ALL, "not enough memory",
206#ifdef ENOLINK
207 ENOLINK, ALL, "remote access failed"
208#endif
209#ifdef EMULTIHOP
210 EMULTIHOP, ALL, "remote access failed",
211#endif
212#ifdef ECOMM
213 ECOMM, ALL, "remote access failed",
214#endif
215#ifdef ESTALE
216 ESTALE, ALL, "remote access failed",
217#endif
218#ifdef ETIMEDOUT
219 ETIMEDOUT, ALL, "remote access failed",
220#endif
221#ifdef ELOOP
222 ELOOP, ALL, "symbolic link loop",
223#endif
224 E2BIG, E_EXEC, "argument list too long",
225#ifdef ELIBACC
226 ELIBACC, E_EXEC, "shared library missing",
227#endif
228 0, 0, NULL
229};
230
231
232/*
233 * Return a string describing an error. The returned string may be a
234 * pointer to a static buffer that will be overwritten on the next call.
235 * Action describes the operation that got the error.
236 */
237
238char *
239errmsg(e, action) {
240 struct errname const *ep;
241 static char buf[12];
242
243 for (ep = errormsg ; ep->errcode ; ep++) {
244 if (ep->errcode == e && (ep->action & action) != 0)
245 return ep->msg;
246 }
247 fmtstr(buf, sizeof buf, "error %d", e);
248 return buf;
249}