xref: /csrg-svn/bin/sh/error.c (revision 60698)
147110Sbostic /*-
2*60698Sbostic  * Copyright (c) 1991, 1993
3*60698Sbostic  *	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*60698Sbostic static char sccsid[] = "@(#)error.c	8.1 (Berkeley) 05/31/93";
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"
2447110Sbostic #include <signal.h>
2547110Sbostic #ifdef __STDC__
2647110Sbostic #include "stdarg.h"
2747110Sbostic #else
2847110Sbostic #include <varargs.h>
2947110Sbostic #endif
3047110Sbostic #include <errno.h>
3147110Sbostic 
3247110Sbostic 
3347110Sbostic /*
3447110Sbostic  * Code to handle exceptions in C.
3547110Sbostic  */
3647110Sbostic 
3747110Sbostic struct jmploc *handler;
3847110Sbostic int exception;
3947110Sbostic volatile int suppressint;
4047110Sbostic volatile int intpending;
4147110Sbostic char *commandname;
4247110Sbostic 
4347110Sbostic 
4447110Sbostic /*
4547110Sbostic  * Called to raise an exception.  Since C doesn't include exceptions, we
4647110Sbostic  * just do a longjmp to the exception handler.  The type of exception is
4747110Sbostic  * stored in the global variable "exception".
4847110Sbostic  */
4947110Sbostic 
5047110Sbostic void
5147110Sbostic exraise(e) {
5247110Sbostic 	if (handler == NULL)
5347110Sbostic 		abort();
5447110Sbostic 	exception = e;
5547110Sbostic 	longjmp(handler->loc, 1);
5647110Sbostic }
5747110Sbostic 
5847110Sbostic 
5947110Sbostic /*
6047110Sbostic  * Called from trap.c when a SIGINT is received.  (If the user specifies
6147110Sbostic  * that SIGINT is to be trapped or ignored using the trap builtin, then
6247110Sbostic  * this routine is not called.)  Suppressint is nonzero when interrupts
6347110Sbostic  * are held using the INTOFF macro.  The call to _exit is necessary because
6447110Sbostic  * there is a short period after a fork before the signal handlers are
6547110Sbostic  * set to the appropriate value for the child.  (The test for iflag is
6647110Sbostic  * just defensive programming.)
6747110Sbostic  */
6847110Sbostic 
6947110Sbostic void
7047110Sbostic onint() {
7147110Sbostic 	if (suppressint) {
7247110Sbostic 		intpending++;
7347110Sbostic 		return;
7447110Sbostic 	}
7547110Sbostic 	intpending = 0;
7647110Sbostic #ifdef BSD
7747110Sbostic 	sigsetmask(0);
7847110Sbostic #endif
7947110Sbostic 	if (rootshell && iflag)
8047110Sbostic 		exraise(EXINT);
8147110Sbostic 	else
8247110Sbostic 		_exit(128 + SIGINT);
8347110Sbostic }
8447110Sbostic 
8547110Sbostic 
8647110Sbostic 
8747110Sbostic void
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 
10147110Sbostic #ifdef __STDC__
10247110Sbostic void
10347110Sbostic error(char *msg, ...) {
10447110Sbostic #else
10547110Sbostic void
10647110Sbostic error(va_alist)
10747110Sbostic 	va_dcl
10847110Sbostic 	{
10947110Sbostic 	char *msg;
11047110Sbostic #endif
11147110Sbostic 	va_list ap;
11247110Sbostic 
11347110Sbostic 	CLEAR_PENDING_INT;
11447110Sbostic 	INTOFF;
11547110Sbostic #ifdef __STDC__
11647110Sbostic 	va_start(ap, msg);
11747110Sbostic #else
11847110Sbostic 	va_start(ap);
11947110Sbostic 	msg = va_arg(ap, char *);
12047110Sbostic #endif
12147110Sbostic #ifdef DEBUG
12247110Sbostic 	if (msg)
12347110Sbostic 		TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
12447110Sbostic 	else
12547110Sbostic 		TRACE(("error(NULL) pid=%d\n", getpid()));
12647110Sbostic #endif
12747110Sbostic 	if (msg) {
12847110Sbostic 		if (commandname)
12947110Sbostic 			outfmt(&errout, "%s: ", commandname);
13047110Sbostic 		doformat(&errout, msg, ap);
13147110Sbostic 		out2c('\n');
13247110Sbostic 	}
13347110Sbostic 	va_end(ap);
13447110Sbostic 	flushall();
13547110Sbostic 	exraise(EXERROR);
13647110Sbostic }
13747110Sbostic 
13847110Sbostic 
13947110Sbostic 
14047110Sbostic /*
14147110Sbostic  * Table of error messages.
14247110Sbostic  */
14347110Sbostic 
14447110Sbostic struct errname {
14547110Sbostic 	short errcode;		/* error number */
14647110Sbostic 	short action;		/* operation which encountered the error */
14747110Sbostic 	char *msg;		/* text describing the error */
14847110Sbostic };
14947110Sbostic 
15047110Sbostic 
15147110Sbostic #define ALL (E_OPEN|E_CREAT|E_EXEC)
15247110Sbostic 
15347110Sbostic STATIC const struct errname errormsg[] = {
15447110Sbostic 	EINTR, ALL,	"interrupted",
15547110Sbostic 	EACCES, ALL,	"permission denied",
15647110Sbostic 	EIO, ALL,		"I/O error",
15747110Sbostic 	ENOENT, E_OPEN,	"no such file",
15847110Sbostic 	ENOENT, E_CREAT,	"directory nonexistent",
15947110Sbostic 	ENOENT, E_EXEC,	"not found",
16047110Sbostic 	ENOTDIR, E_OPEN,	"no such file",
16147110Sbostic 	ENOTDIR, E_CREAT,	"directory nonexistent",
16247110Sbostic 	ENOTDIR, E_EXEC,	"not found",
16347110Sbostic 	EISDIR, ALL,	"is a directory",
16447110Sbostic /*    EMFILE, ALL,	"too many open files", */
16547110Sbostic 	ENFILE, ALL,	"file table overflow",
16647110Sbostic 	ENOSPC, ALL,	"file system full",
16747110Sbostic #ifdef EDQUOT
16847110Sbostic 	EDQUOT, ALL,	"disk quota exceeded",
16947110Sbostic #endif
17047110Sbostic #ifdef ENOSR
17147110Sbostic 	ENOSR, ALL,	"no streams resources",
17247110Sbostic #endif
17347110Sbostic 	ENXIO, ALL,	"no such device or address",
17447110Sbostic 	EROFS, ALL,	"read-only file system",
17547110Sbostic 	ETXTBSY, ALL,	"text busy",
17647110Sbostic #ifdef SYSV
17747110Sbostic 	EAGAIN, E_EXEC,	"not enough memory",
17847110Sbostic #endif
17947110Sbostic 	ENOMEM, ALL,	"not enough memory",
18047110Sbostic #ifdef ENOLINK
18156921Sbostic 	ENOLINK, ALL,	"remote access failed",
18247110Sbostic #endif
18347110Sbostic #ifdef EMULTIHOP
18447110Sbostic 	EMULTIHOP, ALL,	"remote access failed",
18547110Sbostic #endif
18647110Sbostic #ifdef ECOMM
18747110Sbostic 	ECOMM, ALL,	"remote access failed",
18847110Sbostic #endif
18947110Sbostic #ifdef ESTALE
19047110Sbostic 	ESTALE, ALL,	"remote access failed",
19147110Sbostic #endif
19247110Sbostic #ifdef ETIMEDOUT
19347110Sbostic 	ETIMEDOUT, ALL,	"remote access failed",
19447110Sbostic #endif
19547110Sbostic #ifdef ELOOP
19647110Sbostic 	ELOOP, ALL,	"symbolic link loop",
19747110Sbostic #endif
19847110Sbostic 	E2BIG, E_EXEC,	"argument list too long",
19947110Sbostic #ifdef ELIBACC
20047110Sbostic 	ELIBACC, E_EXEC,	"shared library missing",
20147110Sbostic #endif
20247110Sbostic 	0, 0,		NULL
20347110Sbostic };
20447110Sbostic 
20547110Sbostic 
20647110Sbostic /*
20747110Sbostic  * Return a string describing an error.  The returned string may be a
20847110Sbostic  * pointer to a static buffer that will be overwritten on the next call.
20947110Sbostic  * Action describes the operation that got the error.
21047110Sbostic  */
21147110Sbostic 
21247110Sbostic char *
21347110Sbostic errmsg(e, action) {
21447110Sbostic 	struct errname const *ep;
21547110Sbostic 	static char buf[12];
21647110Sbostic 
21747110Sbostic 	for (ep = errormsg ; ep->errcode ; ep++) {
21847110Sbostic 		if (ep->errcode == e && (ep->action & action) != 0)
21947110Sbostic 			return ep->msg;
22047110Sbostic 	}
22147110Sbostic 	fmtstr(buf, sizeof buf, "error %d", e);
22247110Sbostic 	return buf;
22347110Sbostic }
224