source: trunk/minix/commands/ash/trap.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 6.8 KB
Line 
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * 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
38static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
39#endif /* not lint */
40
41#include "shell.h"
42#include "main.h"
43#include "nodes.h" /* for other headers */
44#include "eval.h"
45#include "jobs.h"
46#include "options.h"
47#include "syntax.h"
48#include "signames.h"
49#include "output.h"
50#include "memalloc.h"
51#include "error.h"
52#include "trap.h"
53#include "mystring.h"
54#include <sys/types.h>
55#include <signal.h>
56
57
58/*
59 * Sigmode records the current value of the signal handlers for the various
60 * modes. A value of zero means that the current handler is not known.
61 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
62 */
63
64#define S_DFL 1 /* default signal handling (SIG_DFL) */
65#define S_CATCH 2 /* signal is caught */
66#define S_IGN 3 /* signal is ignored (SIG_IGN) */
67#define S_HARD_IGN 4 /* signal is ignored permenantly */
68
69
70extern char nullstr[1]; /* null string */
71
72char *trap[MAXSIG+1]; /* trap handler commands */
73MKINIT char sigmode[MAXSIG]; /* current value of signal */
74char gotsig[MAXSIG]; /* indicates specified signal received */
75int pendingsigs; /* indicates some signal received */
76
77/*
78 * The trap builtin.
79 */
80
81trapcmd(argc, argv) char **argv; {
82 char *action;
83 char **ap;
84 int signo;
85
86 if (argc <= 1) {
87 for (signo = 0 ; signo <= MAXSIG ; signo++) {
88 if (trap[signo] != NULL)
89 out1fmt("%d: %s\n", signo, trap[signo]);
90 }
91 return 0;
92 }
93 ap = argv + 1;
94 if (is_number(*ap))
95 action = NULL;
96 else
97 action = *ap++;
98 while (*ap) {
99 if ((signo = number(*ap)) < 0 || signo > MAXSIG)
100 error("%s: bad trap", *ap);
101 INTOFF;
102 if (action)
103 action = savestr(action);
104 if (trap[signo])
105 ckfree(trap[signo]);
106 trap[signo] = action;
107 if (signo != 0)
108 setsignal(signo);
109 INTON;
110 ap++;
111 }
112 return 0;
113}
114
115
116
117/*
118 * Clear traps on a fork.
119 */
120
121void
122clear_traps() {
123 char **tp;
124
125 for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
126 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
127 INTOFF;
128 ckfree(*tp);
129 *tp = NULL;
130 if (tp != &trap[0])
131 setsignal(tp - trap);
132 INTON;
133 }
134 }
135}
136
137
138
139/*
140 * Set the signal handler for the specified signal. The routine figures
141 * out what it should be set to.
142 */
143
144int
145setsignal(signo) {
146 int action;
147 sig_t sigact;
148 char *t;
149 extern void onsig();
150
151 if ((t = trap[signo]) == NULL)
152 action = S_DFL;
153 else if (*t != '\0')
154 action = S_CATCH;
155 else
156 action = S_IGN;
157 if (rootshell && action == S_DFL) {
158 switch (signo) {
159 case SIGINT:
160 if (iflag)
161 action = S_CATCH;
162 break;
163 case SIGQUIT:
164#if DEBUG
165 {
166 extern int debug;
167
168 if (debug)
169 break;
170 }
171#endif
172 /* FALLTHROUGH */
173 case SIGTERM:
174 if (iflag)
175 action = S_IGN;
176 break;
177#if JOBS
178 case SIGTSTP:
179 case SIGTTOU:
180 if (jflag)
181 action = S_IGN;
182 break;
183#endif
184 }
185 }
186 t = &sigmode[signo - 1];
187 if (*t == 0) { /* current setting unknown */
188 /*
189 * There is a race condition here if action is not S_IGN.
190 * A signal can be ignored that shouldn't be.
191 */
192 if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
193 error("Signal system call failed");
194 if (sigact == SIG_IGN) {
195 *t = S_HARD_IGN;
196 } else {
197 *t = S_IGN;
198 }
199 }
200 if (*t == S_HARD_IGN || *t == action)
201 return 0;
202 switch (action) {
203 case S_DFL: sigact = SIG_DFL; break;
204 case S_CATCH: sigact = onsig; break;
205 case S_IGN: sigact = SIG_IGN; break;
206 }
207 *t = action;
208 return (int)signal(signo, sigact);
209}
210
211
212/*
213 * Ignore a signal.
214 */
215
216void
217ignoresig(signo) {
218 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
219 signal(signo, SIG_IGN);
220 }
221 sigmode[signo - 1] = S_HARD_IGN;
222}
223
224
225#ifdef mkinit
226INCLUDE "signames.h"
227INCLUDE "trap.h"
228
229SHELLPROC {
230 char *sm;
231
232 clear_traps();
233 for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
234 if (*sm == S_IGN)
235 *sm = S_HARD_IGN;
236 }
237}
238#endif
239
240
241
242/*
243 * Signal handler.
244 */
245
246void
247onsig(signo) {
248 signal(signo, onsig);
249 if (signo == SIGINT && trap[SIGINT] == NULL) {
250 onint();
251 return;
252 }
253 gotsig[signo - 1] = 1;
254 pendingsigs++;
255}
256
257
258
259/*
260 * Called to execute a trap. Perhaps we should avoid entering new trap
261 * handlers while we are executing a trap handler.
262 */
263
264void
265dotrap() {
266 int i;
267 int savestatus;
268
269 for (;;) {
270 for (i = 1 ; ; i++) {
271 if (gotsig[i - 1])
272 break;
273 if (i >= MAXSIG)
274 goto done;
275 }
276 gotsig[i - 1] = 0;
277 savestatus=exitstatus;
278 evalstring(trap[i]);
279 exitstatus=savestatus;
280 }
281done:
282 pendingsigs = 0;
283}
284
285
286
287/*
288 * Controls whether the shell is interactive or not.
289 */
290
291int is_interactive;
292
293void
294setinteractive(on) {
295 if (on == is_interactive)
296 return;
297 setsignal(SIGINT);
298 setsignal(SIGQUIT);
299 setsignal(SIGTERM);
300 is_interactive = on;
301}
302
303
304
305/*
306 * Called to exit the shell.
307 */
308
309void
310exitshell(status) {
311 struct jmploc loc1, loc2;
312 char *p;
313
314 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
315 if (setjmp(loc1.loc)) goto l1;
316 if (setjmp(loc2.loc)) goto l2;
317 handler = &loc1;
318 if ((p = trap[0]) != NULL && *p != '\0') {
319 trap[0] = NULL;
320 evalstring(p);
321 }
322l1: handler = &loc2; /* probably unnecessary */
323 flushall();
324#if JOBS
325 setjobctl(0);
326#endif
327l2: _exit(status);
328}
Note: See TracBrowser for help on using the repository browser.