Deleted Added
full compact
trap.c (50471) trap.c (90111)
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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
40#endif
41static const char rcsid[] =
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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
40#endif
41static const char rcsid[] =
42 "$FreeBSD: head/bin/sh/trap.c 50471 1999-08-27 23:15:48Z peter $";
42 "$FreeBSD: head/bin/sh/trap.c 90111 2002-02-02 06:50:57Z imp $";
43#endif /* not lint */
44
45#include <signal.h>
46#include <unistd.h>
47#include <stdlib.h>
48
49#include "shell.h"
50#include "main.h"
51#include "nodes.h" /* for other headers */
52#include "eval.h"
53#include "jobs.h"
54#include "show.h"
55#include "options.h"
56#include "syntax.h"
57#include "output.h"
58#include "memalloc.h"
59#include "error.h"
60#include "trap.h"
61#include "mystring.h"
62
63
64/*
65 * Sigmode records the current value of the signal handlers for the various
66 * modes. A value of zero means that the current handler is not known.
67 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
68 */
69
70#define S_DFL 1 /* default signal handling (SIG_DFL) */
71#define S_CATCH 2 /* signal is caught */
72#define S_IGN 3 /* signal is ignored (SIG_IGN) */
73#define S_HARD_IGN 4 /* signal is ignored permanently */
74#define S_RESET 5 /* temporary - to reset a hard ignored sig */
75
76
77MKINIT char sigmode[NSIG]; /* current value of signal */
78int pendingsigs; /* indicates some signal received */
79int in_dotrap; /* do we execute in a trap handler? */
80static char *volatile trap[NSIG]; /* trap handler commands */
81static volatile sig_atomic_t gotsig[NSIG];
82 /* indicates specified signal received */
83static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
84
43#endif /* not lint */
44
45#include <signal.h>
46#include <unistd.h>
47#include <stdlib.h>
48
49#include "shell.h"
50#include "main.h"
51#include "nodes.h" /* for other headers */
52#include "eval.h"
53#include "jobs.h"
54#include "show.h"
55#include "options.h"
56#include "syntax.h"
57#include "output.h"
58#include "memalloc.h"
59#include "error.h"
60#include "trap.h"
61#include "mystring.h"
62
63
64/*
65 * Sigmode records the current value of the signal handlers for the various
66 * modes. A value of zero means that the current handler is not known.
67 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
68 */
69
70#define S_DFL 1 /* default signal handling (SIG_DFL) */
71#define S_CATCH 2 /* signal is caught */
72#define S_IGN 3 /* signal is ignored (SIG_IGN) */
73#define S_HARD_IGN 4 /* signal is ignored permanently */
74#define S_RESET 5 /* temporary - to reset a hard ignored sig */
75
76
77MKINIT char sigmode[NSIG]; /* current value of signal */
78int pendingsigs; /* indicates some signal received */
79int in_dotrap; /* do we execute in a trap handler? */
80static char *volatile trap[NSIG]; /* trap handler commands */
81static volatile sig_atomic_t gotsig[NSIG];
82 /* indicates specified signal received */
83static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
84
85static int getsigaction __P((int, sig_t *));
85static int getsigaction(int, sig_t *);
86
87
88/*
89 * Map a string to a signal number.
90 */
91static int
86
87
88/*
89 * Map a string to a signal number.
90 */
91static int
92sigstring_to_signum(sig)
93 char *sig;
92sigstring_to_signum(char *sig)
94{
95
96 if (is_number(sig)) {
97 int signo;
98
99 signo = atoi(sig);
100 return ((signo >= 0 && signo < NSIG) ? signo : (-1));
101 } else if (strcasecmp(sig, "exit") == 0) {
102 return (0);
103 } else {
104 int n;
105
106 if (strncasecmp(sig, "sig", 3) == 0)
107 sig += 3;
108 for (n = 1; n < NSIG; n++)
109 if (strcasecmp(sys_signame[n], sig) == 0)
110 return (n);
111 }
112 return (-1);
113}
114
115
116/*
117 * Print a list of valid signal names.
118 */
119static void
93{
94
95 if (is_number(sig)) {
96 int signo;
97
98 signo = atoi(sig);
99 return ((signo >= 0 && signo < NSIG) ? signo : (-1));
100 } else if (strcasecmp(sig, "exit") == 0) {
101 return (0);
102 } else {
103 int n;
104
105 if (strncasecmp(sig, "sig", 3) == 0)
106 sig += 3;
107 for (n = 1; n < NSIG; n++)
108 if (strcasecmp(sys_signame[n], sig) == 0)
109 return (n);
110 }
111 return (-1);
112}
113
114
115/*
116 * Print a list of valid signal names.
117 */
118static void
120printsignals()
119printsignals(void)
121{
122 int n;
123
124 for (n = 1; n < NSIG; n++) {
125 out1fmt("%s", sys_signame[n]);
126 if (n == (NSIG / 2) || n == (NSIG - 1))
127 out1str("\n");
128 else
129 out1c(' ');
130 }
131}
132
133
134/*
135 * The trap builtin.
136 */
137int
120{
121 int n;
122
123 for (n = 1; n < NSIG; n++) {
124 out1fmt("%s", sys_signame[n]);
125 if (n == (NSIG / 2) || n == (NSIG - 1))
126 out1str("\n");
127 else
128 out1c(' ');
129 }
130}
131
132
133/*
134 * The trap builtin.
135 */
136int
138trapcmd(argc, argv)
139 int argc;
140 char **argv;
137trapcmd(int argc, char **argv)
141{
142 char *action;
143 int signo;
144
145 if (argc <= 1) {
146 for (signo = 0 ; signo < NSIG ; signo++) {
147 if (trap[signo] != NULL)
148 out1fmt("trap -- '%s' %s\n", trap[signo],
149 (signo) ? sys_signame[signo] : "exit");
150 }
151 return 0;
152 }
153 action = NULL;
154 if (*++argv && strcmp(*argv, "--") == 0)
155 argv++;
156 if (*argv && sigstring_to_signum(*argv) == -1) {
157 if ((*argv)[0] != '-') {
158 action = *argv;
159 argv++;
160 } else if ((*argv)[1] == '\0') {
161 argv++;
162 } else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
163 printsignals();
164 return 0;
165 } else {
166 error("bad option %s", *argv);
167 }
168 }
169 while (*argv) {
170 if ((signo = sigstring_to_signum(*argv)) == -1)
171 error("bad signal %s", *argv);
172 INTOFF;
173 if (action)
174 action = savestr(action);
175 if (trap[signo])
176 ckfree(trap[signo]);
177 trap[signo] = action;
178 if (signo != 0)
179 setsignal(signo);
180 INTON;
181 argv++;
182 }
183 return 0;
184}
185
186
187/*
188 * Clear traps on a fork.
189 */
190void
138{
139 char *action;
140 int signo;
141
142 if (argc <= 1) {
143 for (signo = 0 ; signo < NSIG ; signo++) {
144 if (trap[signo] != NULL)
145 out1fmt("trap -- '%s' %s\n", trap[signo],
146 (signo) ? sys_signame[signo] : "exit");
147 }
148 return 0;
149 }
150 action = NULL;
151 if (*++argv && strcmp(*argv, "--") == 0)
152 argv++;
153 if (*argv && sigstring_to_signum(*argv) == -1) {
154 if ((*argv)[0] != '-') {
155 action = *argv;
156 argv++;
157 } else if ((*argv)[1] == '\0') {
158 argv++;
159 } else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
160 printsignals();
161 return 0;
162 } else {
163 error("bad option %s", *argv);
164 }
165 }
166 while (*argv) {
167 if ((signo = sigstring_to_signum(*argv)) == -1)
168 error("bad signal %s", *argv);
169 INTOFF;
170 if (action)
171 action = savestr(action);
172 if (trap[signo])
173 ckfree(trap[signo]);
174 trap[signo] = action;
175 if (signo != 0)
176 setsignal(signo);
177 INTON;
178 argv++;
179 }
180 return 0;
181}
182
183
184/*
185 * Clear traps on a fork.
186 */
187void
191clear_traps()
188clear_traps(void)
192{
193 char *volatile *tp;
194
195 for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) {
196 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
197 INTOFF;
198 ckfree(*tp);
199 *tp = NULL;
200 if (tp != &trap[0])
201 setsignal(tp - trap);
202 INTON;
203 }
204 }
205}
206
207
208/*
209 * Set the signal handler for the specified signal. The routine figures
210 * out what it should be set to.
211 */
212void
189{
190 char *volatile *tp;
191
192 for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) {
193 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
194 INTOFF;
195 ckfree(*tp);
196 *tp = NULL;
197 if (tp != &trap[0])
198 setsignal(tp - trap);
199 INTON;
200 }
201 }
202}
203
204
205/*
206 * Set the signal handler for the specified signal. The routine figures
207 * out what it should be set to.
208 */
209void
213setsignal(signo)
214 int signo;
210setsignal(int signo)
215{
216 int action;
217 sig_t sig, sigact = SIG_DFL;
218 char *t;
219
220 if ((t = trap[signo]) == NULL)
221 action = S_DFL;
222 else if (*t != '\0')
223 action = S_CATCH;
224 else
225 action = S_IGN;
226 if (action == S_DFL) {
227 switch (signo) {
228 case SIGINT:
229 action = S_CATCH;
230 break;
231 case SIGQUIT:
232#ifdef DEBUG
233 {
234 extern int debug;
235
236 if (debug)
237 break;
238 }
239#endif
240 action = S_CATCH;
241 break;
242 case SIGTERM:
243 if (rootshell && iflag)
244 action = S_IGN;
245 break;
246#if JOBS
247 case SIGTSTP:
248 case SIGTTOU:
249 if (rootshell && mflag)
250 action = S_IGN;
251 break;
252#endif
253 }
254 }
255
256 t = &sigmode[signo];
257 if (*t == 0) {
258 /*
259 * current setting unknown
260 */
261 if (!getsigaction(signo, &sigact)) {
262 /*
263 * Pretend it worked; maybe we should give a warning
264 * here, but other shells don't. We don't alter
265 * sigmode, so that we retry every time.
266 */
267 return;
268 }
269 if (sigact == SIG_IGN) {
270 if (mflag && (signo == SIGTSTP ||
271 signo == SIGTTIN || signo == SIGTTOU)) {
272 *t = S_IGN; /* don't hard ignore these */
273 } else
274 *t = S_HARD_IGN;
275 } else {
276 *t = S_RESET; /* force to be set */
277 }
278 }
279 if (*t == S_HARD_IGN || *t == action)
280 return;
281 switch (action) {
282 case S_DFL: sigact = SIG_DFL; break;
283 case S_CATCH: sigact = onsig; break;
284 case S_IGN: sigact = SIG_IGN; break;
285 }
286 *t = action;
287 sig = signal(signo, sigact);
288#ifdef BSD
289 if (sig != SIG_ERR && action == S_CATCH)
290 siginterrupt(signo, 1);
291#endif
292}
293
294
295/*
296 * Return the current setting for sig w/o changing it.
297 */
298static int
211{
212 int action;
213 sig_t sig, sigact = SIG_DFL;
214 char *t;
215
216 if ((t = trap[signo]) == NULL)
217 action = S_DFL;
218 else if (*t != '\0')
219 action = S_CATCH;
220 else
221 action = S_IGN;
222 if (action == S_DFL) {
223 switch (signo) {
224 case SIGINT:
225 action = S_CATCH;
226 break;
227 case SIGQUIT:
228#ifdef DEBUG
229 {
230 extern int debug;
231
232 if (debug)
233 break;
234 }
235#endif
236 action = S_CATCH;
237 break;
238 case SIGTERM:
239 if (rootshell && iflag)
240 action = S_IGN;
241 break;
242#if JOBS
243 case SIGTSTP:
244 case SIGTTOU:
245 if (rootshell && mflag)
246 action = S_IGN;
247 break;
248#endif
249 }
250 }
251
252 t = &sigmode[signo];
253 if (*t == 0) {
254 /*
255 * current setting unknown
256 */
257 if (!getsigaction(signo, &sigact)) {
258 /*
259 * Pretend it worked; maybe we should give a warning
260 * here, but other shells don't. We don't alter
261 * sigmode, so that we retry every time.
262 */
263 return;
264 }
265 if (sigact == SIG_IGN) {
266 if (mflag && (signo == SIGTSTP ||
267 signo == SIGTTIN || signo == SIGTTOU)) {
268 *t = S_IGN; /* don't hard ignore these */
269 } else
270 *t = S_HARD_IGN;
271 } else {
272 *t = S_RESET; /* force to be set */
273 }
274 }
275 if (*t == S_HARD_IGN || *t == action)
276 return;
277 switch (action) {
278 case S_DFL: sigact = SIG_DFL; break;
279 case S_CATCH: sigact = onsig; break;
280 case S_IGN: sigact = SIG_IGN; break;
281 }
282 *t = action;
283 sig = signal(signo, sigact);
284#ifdef BSD
285 if (sig != SIG_ERR && action == S_CATCH)
286 siginterrupt(signo, 1);
287#endif
288}
289
290
291/*
292 * Return the current setting for sig w/o changing it.
293 */
294static int
299getsigaction(signo, sigact)
300 int signo;
301 sig_t *sigact;
295getsigaction(int signo, sig_t *sigact)
302{
303 struct sigaction sa;
304
305 if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
306 return 0;
307 *sigact = (sig_t) sa.sa_handler;
308 return 1;
309}
310
311
312/*
313 * Ignore a signal.
314 */
315void
296{
297 struct sigaction sa;
298
299 if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
300 return 0;
301 *sigact = (sig_t) sa.sa_handler;
302 return 1;
303}
304
305
306/*
307 * Ignore a signal.
308 */
309void
316ignoresig(signo)
317 int signo;
310ignoresig(int signo)
318{
319
320 if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
321 signal(signo, SIG_IGN);
322 }
323 sigmode[signo] = S_HARD_IGN;
324}
325
326
327#ifdef mkinit
328INCLUDE <signal.h>
329INCLUDE "trap.h"
330
331SHELLPROC {
332 char *sm;
333
334 clear_traps();
335 for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
336 if (*sm == S_IGN)
337 *sm = S_HARD_IGN;
338 }
339}
340#endif
341
342
343/*
344 * Signal handler.
345 */
346void
311{
312
313 if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
314 signal(signo, SIG_IGN);
315 }
316 sigmode[signo] = S_HARD_IGN;
317}
318
319
320#ifdef mkinit
321INCLUDE <signal.h>
322INCLUDE "trap.h"
323
324SHELLPROC {
325 char *sm;
326
327 clear_traps();
328 for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
329 if (*sm == S_IGN)
330 *sm = S_HARD_IGN;
331 }
332}
333#endif
334
335
336/*
337 * Signal handler.
338 */
339void
347onsig(signo)
348 int signo;
340onsig(int signo)
349{
350
351#ifndef BSD
352 signal(signo, onsig);
353#endif
354 if (signo == SIGINT && trap[SIGINT] == NULL) {
355 onint();
356 return;
357 }
358
359 if (signo != SIGCHLD || !ignore_sigchld)
360 gotsig[signo] = 1;
361 pendingsigs++;
362
363 /* If we are currently in a wait builtin, prepare to break it */
364 if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
365 breakwaitcmd = 1;
366 /*
367 * If a trap is set, not ignored and not the null command, we need
368 * to make sure traps are executed even when a child blocks signals.
369 */
370 if (Tflag &&
371 trap[signo] != NULL &&
372 ! trap[signo][0] == '\0' &&
373 ! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
374 breakwaitcmd = 1;
375}
376
377
378/*
379 * Called to execute a trap. Perhaps we should avoid entering new trap
380 * handlers while we are executing a trap handler.
381 */
382void
341{
342
343#ifndef BSD
344 signal(signo, onsig);
345#endif
346 if (signo == SIGINT && trap[SIGINT] == NULL) {
347 onint();
348 return;
349 }
350
351 if (signo != SIGCHLD || !ignore_sigchld)
352 gotsig[signo] = 1;
353 pendingsigs++;
354
355 /* If we are currently in a wait builtin, prepare to break it */
356 if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
357 breakwaitcmd = 1;
358 /*
359 * If a trap is set, not ignored and not the null command, we need
360 * to make sure traps are executed even when a child blocks signals.
361 */
362 if (Tflag &&
363 trap[signo] != NULL &&
364 ! trap[signo][0] == '\0' &&
365 ! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
366 breakwaitcmd = 1;
367}
368
369
370/*
371 * Called to execute a trap. Perhaps we should avoid entering new trap
372 * handlers while we are executing a trap handler.
373 */
374void
383dotrap()
375dotrap(void)
384{
385 int i;
386 int savestatus;
387
388 in_dotrap++;
389 for (;;) {
390 for (i = 1; i < NSIG; i++) {
391 if (gotsig[i]) {
392 gotsig[i] = 0;
393 if (trap[i]) {
394 /*
395 * Ignore SIGCHLD to avoid infinite recursion
396 * if the trap action does a fork.
397 */
398 if (i == SIGCHLD)
399 ignore_sigchld++;
400 savestatus = exitstatus;
401 evalstring(trap[i]);
402 exitstatus = savestatus;
403 if (i == SIGCHLD)
404 ignore_sigchld--;
405 }
406 break;
407 }
408 }
409 if (i >= NSIG)
410 break;
411 }
412 in_dotrap--;
413 pendingsigs = 0;
414}
415
416
417/*
418 * Controls whether the shell is interactive or not.
419 */
420void
376{
377 int i;
378 int savestatus;
379
380 in_dotrap++;
381 for (;;) {
382 for (i = 1; i < NSIG; i++) {
383 if (gotsig[i]) {
384 gotsig[i] = 0;
385 if (trap[i]) {
386 /*
387 * Ignore SIGCHLD to avoid infinite recursion
388 * if the trap action does a fork.
389 */
390 if (i == SIGCHLD)
391 ignore_sigchld++;
392 savestatus = exitstatus;
393 evalstring(trap[i]);
394 exitstatus = savestatus;
395 if (i == SIGCHLD)
396 ignore_sigchld--;
397 }
398 break;
399 }
400 }
401 if (i >= NSIG)
402 break;
403 }
404 in_dotrap--;
405 pendingsigs = 0;
406}
407
408
409/*
410 * Controls whether the shell is interactive or not.
411 */
412void
421setinteractive(on)
422 int on;
413setinteractive(int on)
423{
424 static int is_interactive = -1;
425
426 if (on == is_interactive)
427 return;
428 setsignal(SIGINT);
429 setsignal(SIGQUIT);
430 setsignal(SIGTERM);
431 is_interactive = on;
432}
433
434
435/*
436 * Called to exit the shell.
437 */
438void
414{
415 static int is_interactive = -1;
416
417 if (on == is_interactive)
418 return;
419 setsignal(SIGINT);
420 setsignal(SIGQUIT);
421 setsignal(SIGTERM);
422 is_interactive = on;
423}
424
425
426/*
427 * Called to exit the shell.
428 */
429void
439exitshell(status)
440 int status;
430exitshell(int status)
441{
442 struct jmploc loc1, loc2;
443 char *p;
444
445 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
446 if (setjmp(loc1.loc)) {
447 goto l1;
448 }
449 if (setjmp(loc2.loc)) {
450 goto l2;
451 }
452 handler = &loc1;
453 if ((p = trap[0]) != NULL && *p != '\0') {
454 trap[0] = NULL;
455 evalstring(p);
456 }
457l1: handler = &loc2; /* probably unnecessary */
458 flushall();
459#if JOBS
460 setjobctl(0);
461#endif
462l2: _exit(status);
463}
431{
432 struct jmploc loc1, loc2;
433 char *p;
434
435 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
436 if (setjmp(loc1.loc)) {
437 goto l1;
438 }
439 if (setjmp(loc2.loc)) {
440 goto l2;
441 }
442 handler = &loc1;
443 if ((p = trap[0]) != NULL && *p != '\0') {
444 trap[0] = NULL;
445 evalstring(p);
446 }
447l1: handler = &loc2; /* probably unnecessary */
448 flushall();
449#if JOBS
450 setjobctl(0);
451#endif
452l2: _exit(status);
453}