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