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