/*-1* Copyright (c) 1991, 19932* The Regents of the University of California. All rights reserved.3*4* This code is derived from software contributed to Berkeley by5* Kenneth Almquist.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15* 3. Neither the name of the University nor the names of its contributors16* may be used to endorse or promote products derived from this software17* without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND20* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE23* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL24* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS25* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT27* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY28* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF29* SUCH DAMAGE.30*/3132/*33* Errors and exceptions.34*/3536#include "shell.h"37#include "eval.h"38#include "main.h"39#include "options.h"40#include "output.h"41#include "error.h"42#include "nodes.h" /* show.h needs nodes.h */43#include "show.h"44#include "trap.h"45#include <signal.h>46#include <stdlib.h>47#include <unistd.h>48#include <errno.h>495051/*52* Code to handle exceptions in C.53*/5455struct jmploc *handler;56volatile sig_atomic_t exception;57volatile sig_atomic_t suppressint;58volatile sig_atomic_t intpending;596061static void verrorwithstatus(int, const char *, va_list) __printf0like(2, 0) __dead2;6263/*64* Called to raise an exception. Since C doesn't include exceptions, we65* just do a longjmp to the exception handler. The type of exception is66* stored in the global variable "exception".67*68* Interrupts are disabled; they should be re-enabled when the exception is69* caught.70*/7172void73exraise(int e)74{75INTOFF;76if (handler == NULL)77abort();78exception = e;79longjmp(handler->loc, 1);80}818283/*84* Called from trap.c when a SIGINT is received and not suppressed, or when85* an interrupt is pending and interrupts are re-enabled using INTON.86* (If the user specifies that SIGINT is to be trapped or ignored using the87* trap builtin, then this routine is not called.) Suppressint is nonzero88* when interrupts are held using the INTOFF macro. If SIGINTs are not89* suppressed and the shell is not a root shell, then we want to be90* terminated if we get here, as if we were terminated directly by a SIGINT.91* Arrange for this here.92*/9394void95onint(void)96{97sigset_t sigs;9899intpending = 0;100sigemptyset(&sigs);101sigprocmask(SIG_SETMASK, &sigs, NULL);102103/*104* This doesn't seem to be needed, since main() emits a newline.105*/106#if 0107if (tcgetpgrp(0) == getpid())108write(STDERR_FILENO, "\n", 1);109#endif110if (rootshell && iflag)111exraise(EXINT);112else {113signal(SIGINT, SIG_DFL);114kill(getpid(), SIGINT);115_exit(128 + SIGINT);116}117}118119120static void121vwarning(const char *msg, va_list ap)122{123if (commandname)124outfmt(out2, "%s: ", commandname);125else if (arg0)126outfmt(out2, "%s: ", arg0);127doformat(out2, msg, ap);128out2fmt_flush("\n");129}130131132void133warning(const char *msg, ...)134{135va_list ap;136va_start(ap, msg);137vwarning(msg, ap);138va_end(ap);139}140141142/*143* Exverror is called to raise the error exception. If the first argument144* is not NULL then error prints an error message using printf style145* formatting. It then raises the error exception.146*/147static void148verrorwithstatus(int status, const char *msg, va_list ap)149{150/*151* An interrupt trumps an error. Certain places catch error152* exceptions or transform them to a plain nonzero exit code153* in child processes, and if an error exception can be handled,154* an interrupt can be handled as well.155*156* exraise() will disable interrupts for the exception handler.157*/158FORCEINTON;159160#ifdef DEBUG161if (msg)162TRACE(("verrorwithstatus(%d, \"%s\") pid=%d\n",163status, msg, getpid()));164else165TRACE(("verrorwithstatus(%d, NULL) pid=%d\n",166status, getpid()));167#endif168if (msg)169vwarning(msg, ap);170flushall();171exitstatus = status;172exraise(EXERROR);173}174175176void177error(const char *msg, ...)178{179va_list ap;180va_start(ap, msg);181verrorwithstatus(2, msg, ap);182va_end(ap);183}184185186void187errorwithstatus(int status, const char *msg, ...)188{189va_list ap;190va_start(ap, msg);191verrorwithstatus(status, msg, ap);192va_end(ap);193}194195196