error.c revision 36150
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 3. All advertising materials mentioning features or use of this software
171556Srgrimes *    must display the following acknowledgement:
181556Srgrimes *	This product includes software developed by the University of
191556Srgrimes *	California, Berkeley and its contributors.
201556Srgrimes * 4. Neither the name of the University nor the names of its contributors
211556Srgrimes *    may be used to endorse or promote products derived from this software
221556Srgrimes *    without specific prior written permission.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341556Srgrimes * SUCH DAMAGE.
351556Srgrimes */
361556Srgrimes
371556Srgrimes#ifndef lint
3836150Scharnier#if 0
3936150Scharnierstatic char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
4036150Scharnier#endif
4136150Scharnierstatic const char rcsid[] =
4236150Scharnier	"$Id$";
431556Srgrimes#endif /* not lint */
441556Srgrimes
451556Srgrimes/*
461556Srgrimes * Errors and exceptions.
471556Srgrimes */
481556Srgrimes
491556Srgrimes#include "shell.h"
501556Srgrimes#include "main.h"
511556Srgrimes#include "options.h"
521556Srgrimes#include "output.h"
531556Srgrimes#include "error.h"
5417987Speter#include "show.h"
551556Srgrimes#include <signal.h>
5617987Speter#include <unistd.h>
571556Srgrimes#include <errno.h>
581556Srgrimes
591556Srgrimes
601556Srgrimes/*
611556Srgrimes * Code to handle exceptions in C.
621556Srgrimes */
631556Srgrimes
641556Srgrimesstruct jmploc *handler;
651556Srgrimesint exception;
661556Srgrimesvolatile int suppressint;
671556Srgrimesvolatile int intpending;
681556Srgrimeschar *commandname;
691556Srgrimes
701556Srgrimes
7120425Sstevestatic void exverror __P((int, char *, va_list));
7220425Ssteve
731556Srgrimes/*
741556Srgrimes * Called to raise an exception.  Since C doesn't include exceptions, we
751556Srgrimes * just do a longjmp to the exception handler.  The type of exception is
761556Srgrimes * stored in the global variable "exception".
771556Srgrimes */
781556Srgrimes
791556Srgrimesvoid
8020425Ssteveexraise(e)
8117987Speter	int e;
8217987Speter{
831556Srgrimes	if (handler == NULL)
841556Srgrimes		abort();
851556Srgrimes	exception = e;
861556Srgrimes	longjmp(handler->loc, 1);
871556Srgrimes}
881556Srgrimes
891556Srgrimes
901556Srgrimes/*
911556Srgrimes * Called from trap.c when a SIGINT is received.  (If the user specifies
921556Srgrimes * that SIGINT is to be trapped or ignored using the trap builtin, then
931556Srgrimes * this routine is not called.)  Suppressint is nonzero when interrupts
941556Srgrimes * are held using the INTOFF macro.  The call to _exit is necessary because
951556Srgrimes * there is a short period after a fork before the signal handlers are
961556Srgrimes * set to the appropriate value for the child.  (The test for iflag is
971556Srgrimes * just defensive programming.)
981556Srgrimes */
991556Srgrimes
1001556Srgrimesvoid
1011556Srgrimesonint() {
10217987Speter	sigset_t sigset;
10317987Speter
1041556Srgrimes	if (suppressint) {
1051556Srgrimes		intpending++;
1061556Srgrimes		return;
1071556Srgrimes	}
1081556Srgrimes	intpending = 0;
10917987Speter	sigemptyset(&sigset);
11017987Speter	sigprocmask(SIG_SETMASK, &sigset, NULL);
11120425Ssteve	out2str("\n");
1121556Srgrimes	if (rootshell && iflag)
1131556Srgrimes		exraise(EXINT);
1141556Srgrimes	else
1151556Srgrimes		_exit(128 + SIGINT);
1161556Srgrimes}
1171556Srgrimes
1181556Srgrimes
1191556Srgrimes/*
12020425Ssteve * Exverror is called to raise the error exception.  If the first argument
1211556Srgrimes * is not NULL then error prints an error message using printf style
1221556Srgrimes * formatting.  It then raises the error exception.
1231556Srgrimes */
12420425Sstevestatic void
12520425Ssteveexverror(cond, msg, ap)
12620425Ssteve	int cond;
12720425Ssteve	char *msg;
12820425Ssteve	va_list ap;
12920425Ssteve{
13020425Ssteve	CLEAR_PENDING_INT;
13120425Ssteve	INTOFF;
1321556Srgrimes
13320425Ssteve#ifdef DEBUG
13420425Ssteve	if (msg)
13520425Ssteve		TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
13620425Ssteve	else
13720425Ssteve		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
13820425Ssteve#endif
13920425Ssteve	if (msg) {
14020425Ssteve		if (commandname)
14120425Ssteve			outfmt(&errout, "%s: ", commandname);
14220425Ssteve		doformat(&errout, msg, ap);
14320425Ssteve		out2c('\n');
14420425Ssteve	}
14520425Ssteve	flushall();
14620425Ssteve	exraise(cond);
14720425Ssteve}
14820425Ssteve
14920425Ssteve
15025222Ssteve#ifdef __STDC__
1511556Srgrimesvoid
15217987Spetererror(char *msg, ...)
1531556Srgrimes#else
1541556Srgrimesvoid
1551556Srgrimeserror(va_alist)
1561556Srgrimes	va_dcl
15717987Speter#endif
15817987Speter{
15925222Ssteve#ifndef __STDC__
1601556Srgrimes	char *msg;
1611556Srgrimes#endif
1621556Srgrimes	va_list ap;
16325222Ssteve#ifdef __STDC__
16420425Ssteve	va_start(ap, msg);
16520425Ssteve#else
16620425Ssteve	va_start(ap);
16720425Ssteve	msg = va_arg(ap, char *);
16820425Ssteve#endif
16920425Ssteve	exverror(EXERROR, msg, ap);
17020425Ssteve	va_end(ap);
17120425Ssteve}
17217987Speter
17320425Ssteve
17425222Ssteve#ifdef __STDC__
17520425Sstevevoid
17620425Ssteveexerror(int cond, char *msg, ...)
17720425Ssteve#else
17820425Sstevevoid
17920425Ssteveexerror(va_alist)
18020425Ssteve	va_dcl
18120425Ssteve#endif
18220425Ssteve{
18325222Ssteve#ifndef __STDC__
18420425Ssteve	int cond;
18520425Ssteve	char *msg;
18620425Ssteve#endif
18720425Ssteve	va_list ap;
18825222Ssteve#ifdef __STDC__
1891556Srgrimes	va_start(ap, msg);
1901556Srgrimes#else
1911556Srgrimes	va_start(ap);
19220425Ssteve	cond = va_arg(ap, int);
1931556Srgrimes	msg = va_arg(ap, char *);
1941556Srgrimes#endif
19520425Ssteve	exverror(cond, msg, ap);
1961556Srgrimes	va_end(ap);
1971556Srgrimes}
1981556Srgrimes
1991556Srgrimes
2001556Srgrimes
2011556Srgrimes/*
2021556Srgrimes * Table of error messages.
2031556Srgrimes */
2041556Srgrimes
2051556Srgrimesstruct errname {
2061556Srgrimes	short errcode;		/* error number */
2071556Srgrimes	short action;		/* operation which encountered the error */
2081556Srgrimes	char *msg;		/* text describing the error */
2091556Srgrimes};
2101556Srgrimes
2111556Srgrimes
2121556Srgrimes#define ALL (E_OPEN|E_CREAT|E_EXEC)
2131556Srgrimes
2141556SrgrimesSTATIC const struct errname errormsg[] = {
21517987Speter	{ EINTR,	ALL,	"interrupted" },
21617987Speter	{ EACCES,	ALL,	"permission denied" },
21717987Speter	{ EIO,		ALL,	"I/O error" },
21817987Speter	{ ENOENT,	E_OPEN,	"no such file" },
21917987Speter	{ ENOENT,	E_CREAT,"directory nonexistent" },
22017987Speter	{ ENOENT,	E_EXEC,	"not found" },
22117987Speter	{ ENOTDIR,	E_OPEN,	"no such file" },
22217987Speter	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
22317987Speter	{ ENOTDIR,	E_EXEC,	"not found" },
22417987Speter	{ EISDIR,	ALL,	"is a directory" },
22517987Speter#ifdef notdef
22617987Speter	{ EMFILE,	ALL,	"too many open files" },
22717987Speter#endif
22817987Speter	{ ENFILE,	ALL,	"file table overflow" },
22917987Speter	{ ENOSPC,	ALL,	"file system full" },
2301556Srgrimes#ifdef EDQUOT
23117987Speter	{ EDQUOT,	ALL,	"disk quota exceeded" },
2321556Srgrimes#endif
2331556Srgrimes#ifdef ENOSR
23417987Speter	{ ENOSR,	ALL,	"no streams resources" },
2351556Srgrimes#endif
23617987Speter	{ ENXIO,	ALL,	"no such device or address" },
23717987Speter	{ EROFS,	ALL,	"read-only file system" },
23817987Speter	{ ETXTBSY,	ALL,	"text busy" },
2391556Srgrimes#ifdef SYSV
24017987Speter	{ EAGAIN,	E_EXEC,	"not enough memory" },
2411556Srgrimes#endif
24217987Speter	{ ENOMEM,	ALL,	"not enough memory" },
2431556Srgrimes#ifdef ENOLINK
24417987Speter	{ ENOLINK,	ALL,	"remote access failed" },
2451556Srgrimes#endif
2461556Srgrimes#ifdef EMULTIHOP
24717987Speter	{ EMULTIHOP,	ALL,	"remote access failed" },
2481556Srgrimes#endif
2491556Srgrimes#ifdef ECOMM
25017987Speter	{ ECOMM,	ALL,	"remote access failed" },
2511556Srgrimes#endif
2521556Srgrimes#ifdef ESTALE
25317987Speter	{ ESTALE,	ALL,	"remote access failed" },
2541556Srgrimes#endif
2551556Srgrimes#ifdef ETIMEDOUT
25617987Speter	{ ETIMEDOUT,	ALL,	"remote access failed" },
2571556Srgrimes#endif
2581556Srgrimes#ifdef ELOOP
25917987Speter	{ ELOOP,	ALL,	"symbolic link loop" },
2601556Srgrimes#endif
26117987Speter	{ E2BIG,	E_EXEC,	"argument list too long" },
2621556Srgrimes#ifdef ELIBACC
26317987Speter	{ ELIBACC,	E_EXEC,	"shared library missing" },
2641556Srgrimes#endif
26517987Speter	{ 0,		0,	NULL },
2661556Srgrimes};
2671556Srgrimes
2681556Srgrimes
2691556Srgrimes/*
2701556Srgrimes * Return a string describing an error.  The returned string may be a
2711556Srgrimes * pointer to a static buffer that will be overwritten on the next call.
2721556Srgrimes * Action describes the operation that got the error.
2731556Srgrimes */
2741556Srgrimes
2751556Srgrimeschar *
27620425Ssteveerrmsg(e, action)
27717987Speter	int e;
27817987Speter	int action;
27917987Speter{
2801556Srgrimes	struct errname const *ep;
2811556Srgrimes	static char buf[12];
2821556Srgrimes
2831556Srgrimes	for (ep = errormsg ; ep->errcode ; ep++) {
2841556Srgrimes		if (ep->errcode == e && (ep->action & action) != 0)
2851556Srgrimes			return ep->msg;
2861556Srgrimes	}
2871556Srgrimes	fmtstr(buf, sizeof buf, "error %d", e);
2881556Srgrimes	return buf;
2891556Srgrimes}
290