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