Home | History | Annotate | Line # | Download | only in sh
error.c revision 1.12
      1 /*	$NetBSD: error.c,v 1.12 1995/03/21 15:40:16 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.12 1995/03/21 15:40:16 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 set;
    107 
    108 	if (suppressint) {
    109 		intpending++;
    110 		return;
    111 	}
    112 	intpending = 0;
    113 	sigemptyset(&set);
    114 	sigprocmask(SIG_SETMASK, &set);
    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