Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/bin/sh/error.c
39475 views
1
/*-
2
* Copyright (c) 1991, 1993
3
* The Regents of the University of California. All rights reserved.
4
*
5
* This code is derived from software contributed to Berkeley by
6
* Kenneth Almquist.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* 3. Neither the name of the University nor the names of its contributors
17
* may be used to endorse or promote products derived from this software
18
* without specific prior written permission.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*/
32
33
/*
34
* Errors and exceptions.
35
*/
36
37
#include "shell.h"
38
#include "eval.h"
39
#include "main.h"
40
#include "options.h"
41
#include "output.h"
42
#include "error.h"
43
#include "nodes.h" /* show.h needs nodes.h */
44
#include "show.h"
45
#include "trap.h"
46
#include <signal.h>
47
#include <stdlib.h>
48
#include <unistd.h>
49
#include <errno.h>
50
51
52
/*
53
* Code to handle exceptions in C.
54
*/
55
56
struct jmploc *handler;
57
volatile sig_atomic_t exception;
58
volatile sig_atomic_t suppressint;
59
volatile sig_atomic_t intpending;
60
61
62
static void verrorwithstatus(int, const char *, va_list) __printf0like(2, 0) __dead2;
63
64
/*
65
* Called to raise an exception. Since C doesn't include exceptions, we
66
* just do a longjmp to the exception handler. The type of exception is
67
* stored in the global variable "exception".
68
*
69
* Interrupts are disabled; they should be re-enabled when the exception is
70
* caught.
71
*/
72
73
void
74
exraise(int e)
75
{
76
INTOFF;
77
if (handler == NULL)
78
abort();
79
exception = e;
80
longjmp(handler->loc, 1);
81
}
82
83
84
/*
85
* Called from trap.c when a SIGINT is received and not suppressed, or when
86
* an interrupt is pending and interrupts are re-enabled using INTON.
87
* (If the user specifies that SIGINT is to be trapped or ignored using the
88
* trap builtin, then this routine is not called.) Suppressint is nonzero
89
* when interrupts are held using the INTOFF macro. If SIGINTs are not
90
* suppressed and the shell is not a root shell, then we want to be
91
* terminated if we get here, as if we were terminated directly by a SIGINT.
92
* Arrange for this here.
93
*/
94
95
void
96
onint(void)
97
{
98
sigset_t sigs;
99
100
intpending = 0;
101
sigemptyset(&sigs);
102
sigprocmask(SIG_SETMASK, &sigs, NULL);
103
104
/*
105
* This doesn't seem to be needed, since main() emits a newline.
106
*/
107
#if 0
108
if (tcgetpgrp(0) == getpid())
109
write(STDERR_FILENO, "\n", 1);
110
#endif
111
if (rootshell && iflag)
112
exraise(EXINT);
113
else {
114
signal(SIGINT, SIG_DFL);
115
kill(getpid(), SIGINT);
116
_exit(128 + SIGINT);
117
}
118
}
119
120
121
static void
122
vwarning(const char *msg, va_list ap)
123
{
124
if (commandname)
125
outfmt(out2, "%s: ", commandname);
126
else if (arg0)
127
outfmt(out2, "%s: ", arg0);
128
doformat(out2, msg, ap);
129
out2fmt_flush("\n");
130
}
131
132
133
void
134
warning(const char *msg, ...)
135
{
136
va_list ap;
137
va_start(ap, msg);
138
vwarning(msg, ap);
139
va_end(ap);
140
}
141
142
143
/*
144
* Exverror is called to raise the error exception. If the first argument
145
* is not NULL then error prints an error message using printf style
146
* formatting. It then raises the error exception.
147
*/
148
static void
149
verrorwithstatus(int status, const char *msg, va_list ap)
150
{
151
/*
152
* An interrupt trumps an error. Certain places catch error
153
* exceptions or transform them to a plain nonzero exit code
154
* in child processes, and if an error exception can be handled,
155
* an interrupt can be handled as well.
156
*
157
* exraise() will disable interrupts for the exception handler.
158
*/
159
FORCEINTON;
160
161
#ifdef DEBUG
162
if (msg)
163
TRACE(("verrorwithstatus(%d, \"%s\") pid=%d\n",
164
status, msg, getpid()));
165
else
166
TRACE(("verrorwithstatus(%d, NULL) pid=%d\n",
167
status, getpid()));
168
#endif
169
if (msg)
170
vwarning(msg, ap);
171
flushall();
172
exitstatus = status;
173
exraise(EXERROR);
174
}
175
176
177
void
178
error(const char *msg, ...)
179
{
180
va_list ap;
181
va_start(ap, msg);
182
verrorwithstatus(2, msg, ap);
183
va_end(ap);
184
}
185
186
187
void
188
errorwithstatus(int status, const char *msg, ...)
189
{
190
va_list ap;
191
va_start(ap, msg);
192
verrorwithstatus(status, msg, ap);
193
va_end(ap);
194
}
195
196