error.c revision 1556
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
38static char sccsid[] = "@(#)error.c	8.1 (Berkeley) 5/31/93";
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}
250