xref: /freebsd/bin/sh/error.c (revision e043f37205ffbde5627ff299ad25cd532f2956f0)
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