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