xref: /csrg-svn/bin/sh/error.c (revision 69272)
147110Sbostic /*-
260698Sbostic  * Copyright (c) 1991, 1993
360698Sbostic  *	The Regents of the University of California.  All rights reserved.
447110Sbostic  *
547110Sbostic  * This code is derived from software contributed to Berkeley by
647110Sbostic  * Kenneth Almquist.
747110Sbostic  *
847110Sbostic  * %sccs.include.redist.c%
947110Sbostic  */
1047110Sbostic 
1147110Sbostic #ifndef lint
12*69272Schristos static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 05/04/95";
1347110Sbostic #endif /* not lint */
1447110Sbostic 
1547110Sbostic /*
1647110Sbostic  * Errors and exceptions.
1747110Sbostic  */
1847110Sbostic 
1947110Sbostic #include "shell.h"
2047110Sbostic #include "main.h"
2147110Sbostic #include "options.h"
2247110Sbostic #include "output.h"
2347110Sbostic #include "error.h"
24*69272Schristos #include "show.h"
2547110Sbostic #include <signal.h>
26*69272Schristos #include <unistd.h>
2747110Sbostic #include <errno.h>
2847110Sbostic 
2947110Sbostic 
3047110Sbostic /*
3147110Sbostic  * Code to handle exceptions in C.
3247110Sbostic  */
3347110Sbostic 
3447110Sbostic struct jmploc *handler;
3547110Sbostic int exception;
3647110Sbostic volatile int suppressint;
3747110Sbostic volatile int intpending;
3847110Sbostic char *commandname;
3947110Sbostic 
4047110Sbostic 
4147110Sbostic /*
4247110Sbostic  * Called to raise an exception.  Since C doesn't include exceptions, we
4347110Sbostic  * just do a longjmp to the exception handler.  The type of exception is
4447110Sbostic  * stored in the global variable "exception".
4547110Sbostic  */
4647110Sbostic 
4747110Sbostic void
exraise(e)48*69272Schristos exraise(e)
49*69272Schristos 	int e;
50*69272Schristos {
5147110Sbostic 	if (handler == NULL)
5247110Sbostic 		abort();
5347110Sbostic 	exception = e;
5447110Sbostic 	longjmp(handler->loc, 1);
5547110Sbostic }
5647110Sbostic 
5747110Sbostic 
5847110Sbostic /*
5947110Sbostic  * Called from trap.c when a SIGINT is received.  (If the user specifies
6047110Sbostic  * that SIGINT is to be trapped or ignored using the trap builtin, then
6147110Sbostic  * this routine is not called.)  Suppressint is nonzero when interrupts
6247110Sbostic  * are held using the INTOFF macro.  The call to _exit is necessary because
6347110Sbostic  * there is a short period after a fork before the signal handlers are
6447110Sbostic  * set to the appropriate value for the child.  (The test for iflag is
6547110Sbostic  * just defensive programming.)
6647110Sbostic  */
6747110Sbostic 
6847110Sbostic void
onint()6947110Sbostic onint() {
70*69272Schristos 	sigset_t sigset;
71*69272Schristos 
7247110Sbostic 	if (suppressint) {
7347110Sbostic 		intpending++;
7447110Sbostic 		return;
7547110Sbostic 	}
7647110Sbostic 	intpending = 0;
77*69272Schristos 	sigemptyset(&sigset);
78*69272Schristos 	sigprocmask(SIG_SETMASK, &sigset, NULL);
7947110Sbostic 	if (rootshell && iflag)
8047110Sbostic 		exraise(EXINT);
8147110Sbostic 	else
8247110Sbostic 		_exit(128 + SIGINT);
8347110Sbostic }
8447110Sbostic 
8547110Sbostic 
8647110Sbostic 
8747110Sbostic void
error2(a,b)8847110Sbostic error2(a, b)
8947110Sbostic 	char *a, *b;
9047110Sbostic 	{
9147110Sbostic 	error("%s: %s", a, b);
9247110Sbostic }
9347110Sbostic 
9447110Sbostic 
9547110Sbostic /*
9647110Sbostic  * Error is called to raise the error exception.  If the first argument
9747110Sbostic  * is not NULL then error prints an error message using printf style
9847110Sbostic  * formatting.  It then raises the error exception.
9947110Sbostic  */
10047110Sbostic 
101*69272Schristos #if __STDC__
10247110Sbostic void
error(char * msg,...)103*69272Schristos error(char *msg, ...)
10447110Sbostic #else
10547110Sbostic void
10647110Sbostic error(va_alist)
10747110Sbostic 	va_dcl
108*69272Schristos #endif
109*69272Schristos {
110*69272Schristos #if !__STDC__
11147110Sbostic 	char *msg;
11247110Sbostic #endif
11347110Sbostic 	va_list ap;
11447110Sbostic 	CLEAR_PENDING_INT;
11547110Sbostic 	INTOFF;
116*69272Schristos 
117*69272Schristos #if __STDC__
11847110Sbostic 	va_start(ap, msg);
11947110Sbostic #else
12047110Sbostic 	va_start(ap);
12147110Sbostic 	msg = va_arg(ap, char *);
12247110Sbostic #endif
12347110Sbostic #ifdef DEBUG
12447110Sbostic 	if (msg)
12547110Sbostic 		TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
12647110Sbostic 	else
12747110Sbostic 		TRACE(("error(NULL) pid=%d\n", getpid()));
12847110Sbostic #endif
12947110Sbostic 	if (msg) {
13047110Sbostic 		if (commandname)
13147110Sbostic 			outfmt(&errout, "%s: ", commandname);
13247110Sbostic 		doformat(&errout, msg, ap);
13347110Sbostic 		out2c('\n');
13447110Sbostic 	}
13547110Sbostic 	va_end(ap);
13647110Sbostic 	flushall();
13747110Sbostic 	exraise(EXERROR);
13847110Sbostic }
13947110Sbostic 
14047110Sbostic 
14147110Sbostic 
14247110Sbostic /*
14347110Sbostic  * Table of error messages.
14447110Sbostic  */
14547110Sbostic 
14647110Sbostic struct errname {
14747110Sbostic 	short errcode;		/* error number */
14847110Sbostic 	short action;		/* operation which encountered the error */
14947110Sbostic 	char *msg;		/* text describing the error */
15047110Sbostic };
15147110Sbostic 
15247110Sbostic 
15347110Sbostic #define ALL (E_OPEN|E_CREAT|E_EXEC)
15447110Sbostic 
15547110Sbostic STATIC const struct errname errormsg[] = {
156*69272Schristos 	{ EINTR,	ALL,	"interrupted" },
157*69272Schristos 	{ EACCES,	ALL,	"permission denied" },
158*69272Schristos 	{ EIO,		ALL,	"I/O error" },
159*69272Schristos 	{ ENOENT,	E_OPEN,	"no such file" },
160*69272Schristos 	{ ENOENT,	E_CREAT,"directory nonexistent" },
161*69272Schristos 	{ ENOENT,	E_EXEC,	"not found" },
162*69272Schristos 	{ ENOTDIR,	E_OPEN,	"no such file" },
163*69272Schristos 	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
164*69272Schristos 	{ ENOTDIR,	E_EXEC,	"not found" },
165*69272Schristos 	{ EISDIR,	ALL,	"is a directory" },
166*69272Schristos #ifdef notdef
167*69272Schristos 	{ EMFILE,	ALL,	"too many open files" },
168*69272Schristos #endif
169*69272Schristos 	{ ENFILE,	ALL,	"file table overflow" },
170*69272Schristos 	{ ENOSPC,	ALL,	"file system full" },
17147110Sbostic #ifdef EDQUOT
172*69272Schristos 	{ EDQUOT,	ALL,	"disk quota exceeded" },
17347110Sbostic #endif
17447110Sbostic #ifdef ENOSR
175*69272Schristos 	{ ENOSR,	ALL,	"no streams resources" },
17647110Sbostic #endif
177*69272Schristos 	{ ENXIO,	ALL,	"no such device or address" },
178*69272Schristos 	{ EROFS,	ALL,	"read-only file system" },
179*69272Schristos 	{ ETXTBSY,	ALL,	"text busy" },
18047110Sbostic #ifdef SYSV
181*69272Schristos 	{ EAGAIN,	E_EXEC,	"not enough memory" },
18247110Sbostic #endif
183*69272Schristos 	{ ENOMEM,	ALL,	"not enough memory" },
18447110Sbostic #ifdef ENOLINK
185*69272Schristos 	{ ENOLINK,	ALL,	"remote access failed" },
18647110Sbostic #endif
18747110Sbostic #ifdef EMULTIHOP
188*69272Schristos 	{ EMULTIHOP,	ALL,	"remote access failed" },
18947110Sbostic #endif
19047110Sbostic #ifdef ECOMM
191*69272Schristos 	{ ECOMM,	ALL,	"remote access failed" },
19247110Sbostic #endif
19347110Sbostic #ifdef ESTALE
194*69272Schristos 	{ ESTALE,	ALL,	"remote access failed" },
19547110Sbostic #endif
19647110Sbostic #ifdef ETIMEDOUT
197*69272Schristos 	{ ETIMEDOUT,	ALL,	"remote access failed" },
19847110Sbostic #endif
19947110Sbostic #ifdef ELOOP
200*69272Schristos 	{ ELOOP,	ALL,	"symbolic link loop" },
20147110Sbostic #endif
202*69272Schristos 	{ E2BIG,	E_EXEC,	"argument list too long" },
20347110Sbostic #ifdef ELIBACC
204*69272Schristos 	{ ELIBACC,	E_EXEC,	"shared library missing" },
20547110Sbostic #endif
206*69272Schristos 	{ 0,		0,	NULL },
20747110Sbostic };
20847110Sbostic 
20947110Sbostic 
21047110Sbostic /*
21147110Sbostic  * Return a string describing an error.  The returned string may be a
21247110Sbostic  * pointer to a static buffer that will be overwritten on the next call.
21347110Sbostic  * Action describes the operation that got the error.
21447110Sbostic  */
21547110Sbostic 
21647110Sbostic char *
errmsg(e,action)217*69272Schristos errmsg(e, action)
218*69272Schristos 	int e;
219*69272Schristos 	int action;
220*69272Schristos {
22147110Sbostic 	struct errname const *ep;
22247110Sbostic 	static char buf[12];
22347110Sbostic 
22447110Sbostic 	for (ep = errormsg ; ep->errcode ; ep++) {
22547110Sbostic 		if (ep->errcode == e && (ep->action & action) != 0)
22647110Sbostic 			return ep->msg;
22747110Sbostic 	}
22847110Sbostic 	fmtstr(buf, sizeof buf, "error %d", e);
22947110Sbostic 	return buf;
23047110Sbostic }
231