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