00001 /*- 00002 * Copyright (c) 1991, 1993 00003 * The Regents of the University of California. All rights reserved. 00004 * 00005 * This code is derived from software contributed to Berkeley by 00006 * Kenneth Almquist. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 1. Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the distribution. 00016 * 4. Neither the name of the University nor the names of its contributors 00017 * may be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00024 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00025 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00026 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00027 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00028 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00029 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 */ 00032 00033 #ifndef lint 00034 #if 0 00035 static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; 00036 #endif 00037 #endif /* not lint */ 00038 /* 00039 #include <sys/cdefs.h> 00040 __FBSDID("$FreeBSD: src/bin/sh/error.c,v 1.25 2004/04/06 20:06:51 markm Exp $"); 00041 */ 00042 00043 /* 00044 * Errors and exceptions. 00045 */ 00046 00047 #include "shell.h" 00048 #include "main.h" 00049 #include "options.h" 00050 #include "output.h" 00051 #include "error.h" 00052 #include "nodes.h" /* show.h needs nodes.h */ 00053 #include "show.h" 00054 #include "trap.h" 00055 #include <signal.h> 00056 #include <stdlib.h> 00057 #include <unistd.h> 00058 #include <errno.h> 00059 #include <sys/types.h> 00060 00061 00062 /* 00063 * Code to handle exceptions in C. 00064 */ 00065 00066 struct jmploc *handler; 00067 volatile sig_atomic_t exception; 00068 volatile sig_atomic_t suppressint; 00069 volatile sig_atomic_t intpending; 00070 char *commandname; 00071 00072 00073 static void exverror(int, const char *, va_list) __printf0like(2, 0); 00074 00075 /* 00076 * Called to raise an exception. Since C doesn't include exceptions, we 00077 * just do a longjmp to the exception handler. The type of exception is 00078 * stored in the global variable "exception". 00079 */ 00080 00081 void 00082 exraise(int e) 00083 { 00084 if (handler == NULL) 00085 abort(); 00086 exception = e; 00087 longjmp(handler->loc, 1); 00088 } 00089 00090 00091 /* 00092 * Called from trap.c when a SIGINT is received. (If the user specifies 00093 * that SIGINT is to be trapped or ignored using the trap builtin, then 00094 * this routine is not called.) Suppressint is nonzero when interrupts 00095 * are held using the INTOFF macro. If SIGINTs are not suppressed and 00096 * the shell is not a root shell, then we want to be terminated if we 00097 * get here, as if we were terminated directly by a SIGINT. Arrange for 00098 * this here. 00099 */ 00100 00101 void 00102 onint(void) 00103 { 00104 sigset_t sigset; 00105 00106 /* 00107 * The !in_dotrap here is safe. The only way we can arrive here 00108 * with in_dotrap set is that a trap handler set SIGINT to SIG_DFL 00109 * and killed itself. 00110 */ 00111 00112 if (suppressint && !in_dotrap) { 00113 intpending++; 00114 return; 00115 } 00116 intpending = 0; 00117 sigemptyset(&sigset); 00118 sigprocmask(SIG_SETMASK, &sigset, NULL); 00119 00120 /* 00121 * This doesn't seem to be needed, since main() emits a newline. 00122 */ 00123 #if 0 00124 if (tcgetpgrp(0) == getpid()) 00125 write(STDERR_FILENO, "\n", 1); 00126 #endif 00127 if (rootshell && iflag) 00128 exraise(EXINT); 00129 else { 00130 signal(SIGINT, SIG_DFL); 00131 kill(getpid(), SIGINT); 00132 } 00133 } 00134 00135 00136 /* 00137 * Exverror is called to raise the error exception. If the first argument 00138 * is not NULL then error prints an error message using printf style 00139 * formatting. It then raises the error exception. 00140 */ 00141 static void 00142 exverror(int cond, const char *msg, va_list ap) 00143 { 00144 CLEAR_PENDING_INT; 00145 INTOFF; 00146 00147 #if DEBUG 00148 if (msg) 00149 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); 00150 else 00151 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); 00152 #endif 00153 if (msg) { 00154 if (commandname) 00155 outfmt(&errout, "%s: ", commandname); 00156 doformat(&errout, msg, ap); 00157 out2c('\n'); 00158 } 00159 flushall(); 00160 exraise(cond); 00161 } 00162 00163 00164 void 00165 error(const char *msg, ...) 00166 { 00167 va_list ap; 00168 va_start(ap, msg); 00169 exverror(EXERROR, msg, ap); 00170 va_end(ap); 00171 } 00172 00173 00174 void 00175 exerror(int cond, const char *msg, ...) 00176 { 00177 va_list ap; 00178 va_start(ap, msg); 00179 exverror(cond, msg, ap); 00180 va_end(ap); 00181 } 00182 00183 /* 00184 * $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $ 00185 */
1.5.8