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 * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD$"); 401556Srgrimes 411556Srgrimes/* 421556Srgrimes * Errors and exceptions. 431556Srgrimes */ 441556Srgrimes 451556Srgrimes#include "shell.h" 46279569Sjilles#include "eval.h" 471556Srgrimes#include "main.h" 481556Srgrimes#include "options.h" 491556Srgrimes#include "output.h" 501556Srgrimes#include "error.h" 5153891Scracauer#include "nodes.h" /* show.h needs nodes.h */ 5217987Speter#include "show.h" 5338521Scracauer#include "trap.h" 541556Srgrimes#include <signal.h> 5578732Sdd#include <stdlib.h> 5617987Speter#include <unistd.h> 571556Srgrimes#include <errno.h> 581556Srgrimes 591556Srgrimes 601556Srgrimes/* 611556Srgrimes * Code to handle exceptions in C. 621556Srgrimes */ 631556Srgrimes 641556Srgrimesstruct jmploc *handler; 6538521Scracauervolatile sig_atomic_t exception; 6638530Scracauervolatile sig_atomic_t suppressint; 6738521Scracauervolatile sig_atomic_t intpending; 681556Srgrimes 691556Srgrimes 70213811Sobrienstatic void exverror(int, const char *, va_list) __printf0like(2, 0) __dead2; 7120425Ssteve 721556Srgrimes/* 731556Srgrimes * Called to raise an exception. Since C doesn't include exceptions, we 741556Srgrimes * just do a longjmp to the exception handler. The type of exception is 751556Srgrimes * stored in the global variable "exception". 76199660Sjilles * 77199660Sjilles * Interrupts are disabled; they should be reenabled when the exception is 78199660Sjilles * caught. 791556Srgrimes */ 801556Srgrimes 811556Srgrimesvoid 8290111Simpexraise(int e) 8317987Speter{ 84199660Sjilles INTOFF; 851556Srgrimes if (handler == NULL) 861556Srgrimes abort(); 871556Srgrimes exception = e; 881556Srgrimes longjmp(handler->loc, 1); 891556Srgrimes} 901556Srgrimes 911556Srgrimes 921556Srgrimes/* 93276038Sjilles * Called from trap.c when a SIGINT is received and not suppressed, or when 94276038Sjilles * an interrupt is pending and interrupts are re-enabled using INTON. 95276038Sjilles * (If the user specifies that SIGINT is to be trapped or ignored using the 96276038Sjilles * trap builtin, then this routine is not called.) Suppressint is nonzero 97276038Sjilles * when interrupts are held using the INTOFF macro. If SIGINTs are not 98276038Sjilles * suppressed and the shell is not a root shell, then we want to be 99276038Sjilles * terminated if we get here, as if we were terminated directly by a SIGINT. 100276038Sjilles * Arrange for this here. 1011556Srgrimes */ 1021556Srgrimes 1031556Srgrimesvoid 10490111Simponint(void) 10590111Simp{ 106211281Sjilles sigset_t sigs; 10717987Speter 1081556Srgrimes intpending = 0; 109211281Sjilles sigemptyset(&sigs); 110211281Sjilles sigprocmask(SIG_SETMASK, &sigs, NULL); 11138521Scracauer 11238536Scracauer /* 11338536Scracauer * This doesn't seem to be needed, since main() emits a newline. 11438536Scracauer */ 11538521Scracauer#if 0 116155301Sschweikh if (tcgetpgrp(0) == getpid()) 11738521Scracauer write(STDERR_FILENO, "\n", 1); 11838521Scracauer#endif 1191556Srgrimes if (rootshell && iflag) 1201556Srgrimes exraise(EXINT); 12138521Scracauer else { 12238521Scracauer signal(SIGINT, SIG_DFL); 12338521Scracauer kill(getpid(), SIGINT); 124276038Sjilles _exit(128 + SIGINT); 12538521Scracauer } 1261556Srgrimes} 1271556Srgrimes 1281556Srgrimes 129216622Sjillesstatic void 130216622Sjillesvwarning(const char *msg, va_list ap) 131216622Sjilles{ 132216622Sjilles if (commandname) 133216622Sjilles outfmt(out2, "%s: ", commandname); 134274899Sjilles else if (arg0) 135274899Sjilles outfmt(out2, "%s: ", arg0); 136216622Sjilles doformat(out2, msg, ap); 137216622Sjilles out2fmt_flush("\n"); 138216622Sjilles} 139216622Sjilles 140216622Sjilles 141216622Sjillesvoid 142216622Sjilleswarning(const char *msg, ...) 143216622Sjilles{ 144216622Sjilles va_list ap; 145216622Sjilles va_start(ap, msg); 146216622Sjilles vwarning(msg, ap); 147216622Sjilles va_end(ap); 148216622Sjilles} 149216622Sjilles 150216622Sjilles 1511556Srgrimes/* 15220425Ssteve * Exverror is called to raise the error exception. If the first argument 1531556Srgrimes * is not NULL then error prints an error message using printf style 1541556Srgrimes * formatting. It then raises the error exception. 1551556Srgrimes */ 156213811Sobrienstatic void 15790111Simpexverror(int cond, const char *msg, va_list ap) 15820425Ssteve{ 159199660Sjilles /* 160199660Sjilles * An interrupt trumps an error. Certain places catch error 161199660Sjilles * exceptions or transform them to a plain nonzero exit code 162199660Sjilles * in child processes, and if an error exception can be handled, 163199660Sjilles * an interrupt can be handled as well. 164199660Sjilles * 165199660Sjilles * exraise() will disable interrupts for the exception handler. 166199660Sjilles */ 167199660Sjilles FORCEINTON; 1681556Srgrimes 16920425Ssteve#ifdef DEBUG 17020425Ssteve if (msg) 17120425Ssteve TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); 17220425Ssteve else 17320425Ssteve TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); 17420425Ssteve#endif 175216622Sjilles if (msg) 176216622Sjilles vwarning(msg, ap); 17720425Ssteve flushall(); 17820425Ssteve exraise(cond); 17920425Ssteve} 18020425Ssteve 18120425Ssteve 1821556Srgrimesvoid 18375577Skriserror(const char *msg, ...) 18417987Speter{ 1851556Srgrimes va_list ap; 18620425Ssteve va_start(ap, msg); 18720425Ssteve exverror(EXERROR, msg, ap); 18820425Ssteve va_end(ap); 18920425Ssteve} 19017987Speter 19120425Ssteve 19220425Sstevevoid 19375577Skrisexerror(int cond, const char *msg, ...) 19420425Ssteve{ 19520425Ssteve va_list ap; 1961556Srgrimes va_start(ap, msg); 19720425Ssteve exverror(cond, msg, ap); 1981556Srgrimes va_end(ap); 1991556Srgrimes} 200