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 37 #ifndef lint 38 /*static char sccsid[] = "from: @(#)error.c 8.1 (Berkeley) 5/31/93";*/ 39 static char *rcsid = "$Id: error.c,v 1.10 1994/12/05 19:07:35 cgd Exp $"; 40 #endif /* not lint */ 41 42 /* 43 * Errors and exceptions. 44 */ 45 46 #include "shell.h" 47 #include "main.h" 48 #include "options.h" 49 #include "output.h" 50 #include "error.h" 51 #include <signal.h> 52 #ifdef __STDC__ 53 #include "stdarg.h" 54 #else 55 #include <varargs.h> 56 #endif 57 #include <unistd.h> 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 int e; 81 { 82 if (handler == NULL) 83 abort(); 84 exception = e; 85 longjmp(handler->loc, 1); 86 } 87 88 89 /* 90 * Called from trap.c when a SIGINT is received. (If the user specifies 91 * that SIGINT is to be trapped or ignored using the trap builtin, then 92 * this routine is not called.) Suppressint is nonzero when interrupts 93 * are held using the INTOFF macro. The call to _exit is necessary because 94 * there is a short period after a fork before the signal handlers are 95 * set to the appropriate value for the child. (The test for iflag is 96 * just defensive programming.) 97 */ 98 99 void 100 onint() { 101 if (suppressint) { 102 intpending++; 103 return; 104 } 105 intpending = 0; 106 #ifdef BSD 107 sigsetmask(0); 108 #endif 109 if (rootshell && iflag) 110 exraise(EXINT); 111 else 112 _exit(128 + SIGINT); 113 } 114 115 116 117 void 118 error2(a, b) 119 char *a, *b; 120 { 121 error("%s: %s", a, b); 122 } 123 124 125 /* 126 * Error is called to raise the error exception. If the first argument 127 * is not NULL then error prints an error message using printf style 128 * formatting. It then raises the error exception. 129 */ 130 131 #ifdef __STDC__ 132 void 133 error(char *msg, ...) { 134 #else 135 void 136 error(va_alist) 137 va_dcl 138 { 139 char *msg; 140 #endif 141 va_list ap; 142 143 CLEAR_PENDING_INT; 144 INTOFF; 145 #ifdef __STDC__ 146 va_start(ap, msg); 147 #else 148 va_start(ap); 149 msg = va_arg(ap, char *); 150 #endif 151 #ifdef DEBUG 152 if (msg) 153 TRACE(("error(\"%s\") pid=%d\n", msg, getpid())); 154 else 155 TRACE(("error(NULL) pid=%d\n", getpid())); 156 #endif 157 if (msg) { 158 if (commandname) 159 outfmt(&errout, "%s: ", commandname); 160 doformat(&errout, msg, ap); 161 out2c('\n'); 162 } 163 va_end(ap); 164 flushall(); 165 exraise(EXERROR); 166 } 167 168 169 170 /* 171 * Table of error messages. 172 */ 173 174 struct errname { 175 short errcode; /* error number */ 176 short action; /* operation which encountered the error */ 177 char *msg; /* text describing the error */ 178 }; 179 180 181 #define ALL (E_OPEN|E_CREAT|E_EXEC) 182 183 STATIC const struct errname errormsg[] = { 184 EINTR, ALL, "interrupted", 185 EACCES, ALL, "permission denied", 186 EIO, ALL, "I/O error", 187 ENOENT, E_OPEN, "no such file", 188 ENOENT, E_CREAT, "directory nonexistent", 189 ENOENT, E_EXEC, "not found", 190 ENOTDIR, E_OPEN, "no such file", 191 ENOTDIR, E_CREAT, "directory nonexistent", 192 ENOTDIR, E_EXEC, "not found", 193 EISDIR, ALL, "is a directory", 194 /* EMFILE, ALL, "too many open files", */ 195 ENFILE, ALL, "file table overflow", 196 ENOSPC, ALL, "file system full", 197 #ifdef EDQUOT 198 EDQUOT, ALL, "disk quota exceeded", 199 #endif 200 #ifdef ENOSR 201 ENOSR, ALL, "no streams resources", 202 #endif 203 ENXIO, ALL, "no such device or address", 204 EROFS, ALL, "read-only file system", 205 ETXTBSY, ALL, "text busy", 206 #ifdef SYSV 207 EAGAIN, E_EXEC, "not enough memory", 208 #endif 209 ENOMEM, ALL, "not enough memory", 210 #ifdef ENOLINK 211 ENOLINK, ALL, "remote access failed", 212 #endif 213 #ifdef EMULTIHOP 214 EMULTIHOP, ALL, "remote access failed", 215 #endif 216 #ifdef ECOMM 217 ECOMM, ALL, "remote access failed", 218 #endif 219 #ifdef ESTALE 220 ESTALE, ALL, "remote access failed", 221 #endif 222 #ifdef ETIMEDOUT 223 ETIMEDOUT, ALL, "remote access failed", 224 #endif 225 #ifdef ELOOP 226 ELOOP, ALL, "symbolic link loop", 227 #endif 228 E2BIG, E_EXEC, "argument list too long", 229 #ifdef ELIBACC 230 ELIBACC, E_EXEC, "shared library missing", 231 #endif 232 0, 0, NULL 233 }; 234 235 236 /* 237 * Return a string describing an error. The returned string may be a 238 * pointer to a static buffer that will be overwritten on the next call. 239 * Action describes the operation that got the error. 240 */ 241 242 char * 243 errmsg(e, action) 244 int e; 245 int action; 246 { 247 struct errname const *ep; 248 static char buf[12]; 249 250 for (ep = errormsg ; ep->errcode ; ep++) { 251 if (ep->errcode == e && (ep->action & action) != 0) 252 return ep->msg; 253 } 254 fmtstr(buf, sizeof buf, "error %d", e); 255 return buf; 256 } 257