1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $Id: error.c,v 1.2 1994/09/24 02:57:27 davidg Exp $ 37 */ 38 39 #ifndef lint 40 static char sccsid[] = "@(#)error.c 8.1 (Berkeley) 5/31/93"; 41 #endif /* not lint */ 42 43 /* 44 * Errors and exceptions. 45 */ 46 47 #include "shell.h" 48 #include "main.h" 49 #include "options.h" 50 #include "output.h" 51 #include "error.h" 52 #include <signal.h> 53 #ifdef __STDC__ 54 #include "stdarg.h" 55 #else 56 #include <varargs.h> 57 #endif 58 #include <errno.h> 59 60 61 /* 62 * Code to handle exceptions in C. 63 */ 64 65 struct jmploc *handler; 66 int exception; 67 volatile int suppressint; 68 volatile int intpending; 69 char *commandname; 70 71 72 /* 73 * Called to raise an exception. Since C doesn't include exceptions, we 74 * just do a longjmp to the exception handler. The type of exception is 75 * stored in the global variable "exception". 76 */ 77 78 void 79 exraise(e) { 80 if (handler == NULL) 81 abort(); 82 exception = e; 83 longjmp(handler->loc, 1); 84 } 85 86 87 /* 88 * Called from trap.c when a SIGINT is received. (If the user specifies 89 * that SIGINT is to be trapped or ignored using the trap builtin, then 90 * this routine is not called.) Suppressint is nonzero when interrupts 91 * are held using the INTOFF macro. The call to _exit is necessary because 92 * there is a short period after a fork before the signal handlers are 93 * set to the appropriate value for the child. (The test for iflag is 94 * just defensive programming.) 95 */ 96 97 void 98 onint() { 99 if (suppressint) { 100 intpending++; 101 return; 102 } 103 intpending = 0; 104 #ifdef BSD 105 sigsetmask(0); 106 #endif 107 if (rootshell && iflag) 108 exraise(EXINT); 109 else 110 _exit(128 + SIGINT); 111 } 112 113 114 115 void 116 error2(a, b) 117 char *a, *b; 118 { 119 error("%s: %s", a, b); 120 } 121 122 123 /* 124 * Error is called to raise the error exception. If the first argument 125 * is not NULL then error prints an error message using printf style 126 * formatting. It then raises the error exception. 127 */ 128 129 #ifdef __STDC__ 130 void 131 error(char *msg, ...) { 132 #else 133 void 134 error(va_alist) 135 va_dcl 136 { 137 char *msg; 138 #endif 139 va_list ap; 140 141 CLEAR_PENDING_INT; 142 INTOFF; 143 #ifdef __STDC__ 144 va_start(ap, msg); 145 #else 146 va_start(ap); 147 msg = va_arg(ap, char *); 148 #endif 149 #ifdef DEBUG 150 if (msg) 151 TRACE(("error(\"%s\") pid=%d\n", msg, getpid())); 152 else 153 TRACE(("error(NULL) pid=%d\n", getpid())); 154 #endif 155 if (msg) { 156 if (commandname) 157 outfmt(&errout, "%s: ", commandname); 158 doformat(&errout, msg, ap); 159 out2c('\n'); 160 } 161 va_end(ap); 162 flushall(); 163 exraise(EXERROR); 164 } 165 166 167 168 /* 169 * Table of error messages. 170 */ 171 172 struct errname { 173 short errcode; /* error number */ 174 short action; /* operation which encountered the error */ 175 char *msg; /* text describing the error */ 176 }; 177 178 179 #define ALL (E_OPEN|E_CREAT|E_EXEC) 180 181 STATIC const struct errname errormsg[] = { 182 EINTR, ALL, "interrupted", 183 EACCES, ALL, "permission denied", 184 EIO, ALL, "I/O error", 185 ENOENT, E_OPEN, "no such file", 186 ENOENT, E_CREAT, "directory nonexistent", 187 ENOENT, E_EXEC, "not found", 188 ENOTDIR, E_OPEN, "no such file", 189 ENOTDIR, E_CREAT, "directory nonexistent", 190 ENOTDIR, E_EXEC, "not found", 191 EISDIR, ALL, "is a directory", 192 /* EMFILE, ALL, "too many open files", */ 193 ENFILE, ALL, "file table overflow", 194 ENOSPC, ALL, "file system full", 195 #ifdef EDQUOT 196 EDQUOT, ALL, "disk quota exceeded", 197 #endif 198 #ifdef ENOSR 199 ENOSR, ALL, "no streams resources", 200 #endif 201 ENXIO, ALL, "no such device or address", 202 EROFS, ALL, "read-only file system", 203 ETXTBSY, ALL, "text busy", 204 #ifdef SYSV 205 EAGAIN, E_EXEC, "not enough memory", 206 #endif 207 ENOMEM, ALL, "not enough memory", 208 #ifdef ENOLINK 209 ENOLINK, ALL, "remote access failed", 210 #endif 211 #ifdef EMULTIHOP 212 EMULTIHOP, ALL, "remote access failed", 213 #endif 214 #ifdef ECOMM 215 ECOMM, ALL, "remote access failed", 216 #endif 217 #ifdef ESTALE 218 ESTALE, ALL, "remote access failed", 219 #endif 220 #ifdef ETIMEDOUT 221 ETIMEDOUT, ALL, "remote access failed", 222 #endif 223 #ifdef ELOOP 224 ELOOP, ALL, "symbolic link loop", 225 #endif 226 E2BIG, E_EXEC, "argument list too long", 227 #ifdef ELIBACC 228 ELIBACC, E_EXEC, "shared library missing", 229 #endif 230 0, 0, NULL 231 }; 232 233 234 /* 235 * Return a string describing an error. The returned string may be a 236 * pointer to a static buffer that will be overwritten on the next call. 237 * Action describes the operation that got the error. 238 */ 239 240 char * 241 errmsg(e, action) { 242 struct errname const *ep; 243 static char buf[12]; 244 245 for (ep = errormsg ; ep->errcode ; ep++) { 246 if (ep->errcode == e && (ep->action & action) != 0) 247 return ep->msg; 248 } 249 fmtstr(buf, sizeof buf, "error %d", e); 250 return buf; 251 } 252