14b88c807SRodney W. Grimes /*-
24b88c807SRodney W. Grimes * Copyright (c) 1991, 1993
34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved.
44b88c807SRodney W. Grimes *
54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by
64b88c807SRodney W. Grimes * Kenneth Almquist.
74b88c807SRodney W. Grimes *
84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions
104b88c807SRodney W. Grimes * are met:
114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution.
16fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
174b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software
184b88c807SRodney W. Grimes * without specific prior written permission.
194b88c807SRodney W. Grimes *
204b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
214b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
244b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304b88c807SRodney W. Grimes * SUCH DAMAGE.
314b88c807SRodney W. Grimes */
324b88c807SRodney W. Grimes
334b88c807SRodney W. Grimes /*
344b88c807SRodney W. Grimes * Errors and exceptions.
354b88c807SRodney W. Grimes */
364b88c807SRodney W. Grimes
374b88c807SRodney W. Grimes #include "shell.h"
3858bdb076SJilles Tjoelker #include "eval.h"
394b88c807SRodney W. Grimes #include "main.h"
404b88c807SRodney W. Grimes #include "options.h"
414b88c807SRodney W. Grimes #include "output.h"
424b88c807SRodney W. Grimes #include "error.h"
436c48b6cfSMartin Cracauer #include "nodes.h" /* show.h needs nodes.h */
44aa9caaf6SPeter Wemm #include "show.h"
457a8e920bSMartin Cracauer #include "trap.h"
464b88c807SRodney W. Grimes #include <signal.h>
47cafefe8cSDima Dorfman #include <stdlib.h>
48aa9caaf6SPeter Wemm #include <unistd.h>
494b88c807SRodney W. Grimes #include <errno.h>
504b88c807SRodney W. Grimes
514b88c807SRodney W. Grimes
524b88c807SRodney W. Grimes /*
534b88c807SRodney W. Grimes * Code to handle exceptions in C.
544b88c807SRodney W. Grimes */
554b88c807SRodney W. Grimes
564b88c807SRodney W. Grimes struct jmploc *handler;
577a8e920bSMartin Cracauer volatile sig_atomic_t exception;
58a1c7435aSMartin Cracauer volatile sig_atomic_t suppressint;
597a8e920bSMartin Cracauer volatile sig_atomic_t intpending;
604b88c807SRodney W. Grimes
614b88c807SRodney W. Grimes
62bb324af6SJilles Tjoelker static void verrorwithstatus(int, const char *, va_list) __printf0like(2, 0) __dead2;
63ab0a2172SSteve Price
644b88c807SRodney W. Grimes /*
654b88c807SRodney W. Grimes * Called to raise an exception. Since C doesn't include exceptions, we
664b88c807SRodney W. Grimes * just do a longjmp to the exception handler. The type of exception is
674b88c807SRodney W. Grimes * stored in the global variable "exception".
689922c6d2SJilles Tjoelker *
69*48556dffSElyes HAOUAS * Interrupts are disabled; they should be re-enabled when the exception is
709922c6d2SJilles Tjoelker * caught.
714b88c807SRodney W. Grimes */
724b88c807SRodney W. Grimes
734b88c807SRodney W. Grimes void
exraise(int e)745134c3f7SWarner Losh exraise(int e)
75aa9caaf6SPeter Wemm {
769922c6d2SJilles Tjoelker INTOFF;
774b88c807SRodney W. Grimes if (handler == NULL)
784b88c807SRodney W. Grimes abort();
794b88c807SRodney W. Grimes exception = e;
804b88c807SRodney W. Grimes longjmp(handler->loc, 1);
814b88c807SRodney W. Grimes }
824b88c807SRodney W. Grimes
834b88c807SRodney W. Grimes
844b88c807SRodney W. Grimes /*
8585052e7bSJilles Tjoelker * Called from trap.c when a SIGINT is received and not suppressed, or when
8685052e7bSJilles Tjoelker * an interrupt is pending and interrupts are re-enabled using INTON.
8785052e7bSJilles Tjoelker * (If the user specifies that SIGINT is to be trapped or ignored using the
8885052e7bSJilles Tjoelker * trap builtin, then this routine is not called.) Suppressint is nonzero
8985052e7bSJilles Tjoelker * when interrupts are held using the INTOFF macro. If SIGINTs are not
9085052e7bSJilles Tjoelker * suppressed and the shell is not a root shell, then we want to be
9185052e7bSJilles Tjoelker * terminated if we get here, as if we were terminated directly by a SIGINT.
9285052e7bSJilles Tjoelker * Arrange for this here.
934b88c807SRodney W. Grimes */
944b88c807SRodney W. Grimes
954b88c807SRodney W. Grimes void
onint(void)965134c3f7SWarner Losh onint(void)
975134c3f7SWarner Losh {
9892378cceSJilles Tjoelker sigset_t sigs;
99aa9caaf6SPeter Wemm
1004b88c807SRodney W. Grimes intpending = 0;
10192378cceSJilles Tjoelker sigemptyset(&sigs);
10292378cceSJilles Tjoelker sigprocmask(SIG_SETMASK, &sigs, NULL);
1037a8e920bSMartin Cracauer
1041f40b47bSMartin Cracauer /*
1051f40b47bSMartin Cracauer * This doesn't seem to be needed, since main() emits a newline.
1067a8e920bSMartin Cracauer */
1077a8e920bSMartin Cracauer #if 0
1087a8e920bSMartin Cracauer if (tcgetpgrp(0) == getpid())
1097a8e920bSMartin Cracauer write(STDERR_FILENO, "\n", 1);
1107a8e920bSMartin Cracauer #endif
1114b88c807SRodney W. Grimes if (rootshell && iflag)
1124b88c807SRodney W. Grimes exraise(EXINT);
1137a8e920bSMartin Cracauer else {
1147a8e920bSMartin Cracauer signal(SIGINT, SIG_DFL);
1157a8e920bSMartin Cracauer kill(getpid(), SIGINT);
11685052e7bSJilles Tjoelker _exit(128 + SIGINT);
1177a8e920bSMartin Cracauer }
1184b88c807SRodney W. Grimes }
1194b88c807SRodney W. Grimes
1204b88c807SRodney W. Grimes
1215fe9123fSJilles Tjoelker static void
vwarning(const char * msg,va_list ap)1225fe9123fSJilles Tjoelker vwarning(const char *msg, va_list ap)
1235fe9123fSJilles Tjoelker {
1245fe9123fSJilles Tjoelker if (commandname)
1255fe9123fSJilles Tjoelker outfmt(out2, "%s: ", commandname);
126fafeab43SJilles Tjoelker else if (arg0)
127fafeab43SJilles Tjoelker outfmt(out2, "%s: ", arg0);
1285fe9123fSJilles Tjoelker doformat(out2, msg, ap);
1295fe9123fSJilles Tjoelker out2fmt_flush("\n");
1305fe9123fSJilles Tjoelker }
1315fe9123fSJilles Tjoelker
1325fe9123fSJilles Tjoelker
1335fe9123fSJilles Tjoelker void
warning(const char * msg,...)1345fe9123fSJilles Tjoelker warning(const char *msg, ...)
1355fe9123fSJilles Tjoelker {
1365fe9123fSJilles Tjoelker va_list ap;
1375fe9123fSJilles Tjoelker va_start(ap, msg);
1385fe9123fSJilles Tjoelker vwarning(msg, ap);
1395fe9123fSJilles Tjoelker va_end(ap);
1405fe9123fSJilles Tjoelker }
1415fe9123fSJilles Tjoelker
1425fe9123fSJilles Tjoelker
1434b88c807SRodney W. Grimes /*
144ab0a2172SSteve Price * Exverror is called to raise the error exception. If the first argument
1454b88c807SRodney W. Grimes * is not NULL then error prints an error message using printf style
1464b88c807SRodney W. Grimes * formatting. It then raises the error exception.
1474b88c807SRodney W. Grimes */
14888328642SDavid E. O'Brien static void
verrorwithstatus(int status,const char * msg,va_list ap)149bb324af6SJilles Tjoelker verrorwithstatus(int status, const char *msg, va_list ap)
150ab0a2172SSteve Price {
1519922c6d2SJilles Tjoelker /*
1529922c6d2SJilles Tjoelker * An interrupt trumps an error. Certain places catch error
1539922c6d2SJilles Tjoelker * exceptions or transform them to a plain nonzero exit code
1549922c6d2SJilles Tjoelker * in child processes, and if an error exception can be handled,
1559922c6d2SJilles Tjoelker * an interrupt can be handled as well.
1569922c6d2SJilles Tjoelker *
1579922c6d2SJilles Tjoelker * exraise() will disable interrupts for the exception handler.
1589922c6d2SJilles Tjoelker */
1599922c6d2SJilles Tjoelker FORCEINTON;
160ab0a2172SSteve Price
161ab0a2172SSteve Price #ifdef DEBUG
162ab0a2172SSteve Price if (msg)
163bb324af6SJilles Tjoelker TRACE(("verrorwithstatus(%d, \"%s\") pid=%d\n",
164bb324af6SJilles Tjoelker status, msg, getpid()));
165ab0a2172SSteve Price else
166bb324af6SJilles Tjoelker TRACE(("verrorwithstatus(%d, NULL) pid=%d\n",
167bb324af6SJilles Tjoelker status, getpid()));
168ab0a2172SSteve Price #endif
1695fe9123fSJilles Tjoelker if (msg)
1705fe9123fSJilles Tjoelker vwarning(msg, ap);
171ab0a2172SSteve Price flushall();
172bb324af6SJilles Tjoelker exitstatus = status;
173bb324af6SJilles Tjoelker exraise(EXERROR);
174ab0a2172SSteve Price }
175ab0a2172SSteve Price
1764b88c807SRodney W. Grimes
1774b88c807SRodney W. Grimes void
error(const char * msg,...)178a2e73040SKris Kennaway error(const char *msg, ...)
1794b88c807SRodney W. Grimes {
1804b88c807SRodney W. Grimes va_list ap;
1814b88c807SRodney W. Grimes va_start(ap, msg);
182bb324af6SJilles Tjoelker verrorwithstatus(2, msg, ap);
1834b88c807SRodney W. Grimes va_end(ap);
184ab0a2172SSteve Price }
185ab0a2172SSteve Price
186ab0a2172SSteve Price
187ab0a2172SSteve Price void
errorwithstatus(int status,const char * msg,...)188bb324af6SJilles Tjoelker errorwithstatus(int status, const char *msg, ...)
189ab0a2172SSteve Price {
190ab0a2172SSteve Price va_list ap;
191ab0a2172SSteve Price va_start(ap, msg);
192bb324af6SJilles Tjoelker verrorwithstatus(status, msg, ap);
193ab0a2172SSteve Price va_end(ap);
1944b88c807SRodney W. Grimes }
195