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