source: mainline/uspace/app/ash/trap.c@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was c28a023, checked in by Josef Cejka <malyzelenyhnus@…>, 17 years ago

Initial commit of ash shell.
It cannot be compiled yet.

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[c28a023]1/* $NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#include <sys/cdefs.h>
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
43#else
44__RCSID("$NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $");
45#endif
46#endif /* not lint */
47
48#include <signal.h>
49#include <unistd.h>
50#include <stdlib.h>
51
52#include "shell.h"
53#include "main.h"
54#include "nodes.h" /* for other headers */
55#include "eval.h"
56#include "jobs.h"
57#include "show.h"
58#include "options.h"
59#include "syntax.h"
60#include "output.h"
61#include "memalloc.h"
62#include "error.h"
63#include "trap.h"
64#include "mystring.h"
65#include "mail.h"
66
67#ifdef HETIO
68#include "hetio.h"
69#endif
70
71/*
72 * Sigmode records the current value of the signal handlers for the various
73 * modes. A value of zero means that the current handler is not known.
74 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
75 */
76
77#define S_DFL 1 /* default signal handling (SIG_DFL) */
78#define S_CATCH 2 /* signal is caught */
79#define S_IGN 3 /* signal is ignored (SIG_IGN) */
80#define S_HARD_IGN 4 /* signal is ignored permenantly */
81#define S_RESET 5 /* temporary - to reset a hard ignored sig */
82
83
84extern char nullstr[1]; /* null string */
85
86char *trap[NSIG+1]; /* trap handler commands */
87MKINIT char sigmode[NSIG]; /* current value of signal */
88char gotsig[NSIG]; /* indicates specified signal received */
89int pendingsigs; /* indicates some signal received */
90
91extern char *signal_names[];
92
93/*
94 * The trap builtin.
95 */
96
97int
98trapcmd(argc, argv)
99 int argc;
100 char **argv;
101{
102 char *action;
103 char **ap;
104 int signo;
105
106 if (argc <= 1) {
107 for (signo = 0 ; signo <= NSIG ; signo++) {
108 if (trap[signo] != NULL)
109 out1fmt("%d: %s\n", signo, trap[signo]);
110 }
111 return 0;
112 }
113 ap = argv + 1;
114 if (argc == 2)
115 action = NULL;
116 else
117 action = *ap++;
118 while (*ap) {
119 if ((signo = decode_signal(*ap)) < 0)
120 error("%s: bad trap", *ap);
121 INTOFF;
122 if (action) {
123 if (action[0] == '-' && action[1] == '\0')
124 action = NULL;
125 else
126 action = savestr(action);
127 }
128 if (trap[signo])
129 ckfree(trap[signo]);
130 trap[signo] = action;
131 if (signo != 0)
132 setsignal(signo);
133 INTON;
134 ap++;
135 }
136 return 0;
137}
138
139
140
141/*
142 * Clear traps on a fork.
143 */
144
145void
146clear_traps() {
147 char **tp;
148
149 for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
150 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
151 INTOFF;
152 ckfree(*tp);
153 *tp = NULL;
154 if (tp != &trap[0])
155 setsignal(tp - trap);
156 INTON;
157 }
158 }
159}
160
161
162
163/*
164 * Set the signal handler for the specified signal. The routine figures
165 * out what it should be set to.
166 */
167
168void
169setsignal(signo)
170 int signo;
171{
172 int action;
173 char *t;
174 struct sigaction act;
175
176 if ((t = trap[signo]) == NULL)
177 action = S_DFL;
178 else if (*t != '\0')
179 action = S_CATCH;
180 else
181 action = S_IGN;
182 if (rootshell && action == S_DFL) {
183 switch (signo) {
184 case SIGINT:
185 if (iflag || minusc || sflag == 0)
186 action = S_CATCH;
187 break;
188 case SIGQUIT:
189#ifdef DEBUG
190 {
191 extern int debug;
192
193 if (debug)
194 break;
195 }
196#endif
197 /* FALLTHROUGH */
198 case SIGTERM:
199 if (iflag)
200 action = S_IGN;
201 break;
202#if JOBS
203 case SIGTSTP:
204 case SIGTTOU:
205 if (mflag)
206 action = S_IGN;
207 break;
208#endif
209 }
210 }
211
212 t = &sigmode[signo - 1];
213 if (*t == 0) {
214 /*
215 * current setting unknown
216 */
217 if (sigaction(signo, 0, &act) == -1) {
218 /*
219 * Pretend it worked; maybe we should give a warning
220 * here, but other shells don't. We don't alter
221 * sigmode, so that we retry every time.
222 */
223 return;
224 }
225 if (act.sa_handler == SIG_IGN) {
226 if (mflag && (signo == SIGTSTP ||
227 signo == SIGTTIN || signo == SIGTTOU)) {
228 *t = S_IGN; /* don't hard ignore these */
229 } else
230 *t = S_HARD_IGN;
231 } else {
232 *t = S_RESET; /* force to be set */
233 }
234 }
235 if (*t == S_HARD_IGN || *t == action)
236 return;
237 switch (action) {
238 case S_CATCH:
239 act.sa_handler = onsig;
240 break;
241 case S_IGN:
242 act.sa_handler = SIG_IGN;
243 break;
244 default:
245 act.sa_handler = SIG_DFL;
246 }
247 *t = action;
248 act.sa_flags = 0;
249 sigemptyset(&act.sa_mask);
250 sigaction(signo, &act, 0);
251}
252
253/*
254 * Ignore a signal.
255 */
256
257void
258ignoresig(signo)
259 int signo;
260{
261 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
262 signal(signo, SIG_IGN);
263 }
264 sigmode[signo - 1] = S_HARD_IGN;
265}
266
267
268#ifdef mkinit
269INCLUDE <signal.h>
270INCLUDE "trap.h"
271
272SHELLPROC {
273 char *sm;
274
275 clear_traps();
276 for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
277 if (*sm == S_IGN)
278 *sm = S_HARD_IGN;
279 }
280}
281#endif
282
283
284
285/*
286 * Signal handler.
287 */
288
289void
290onsig(signo)
291 int signo;
292{
293 signal(signo, onsig);
294 if (signo == SIGINT && trap[SIGINT] == NULL) {
295 onint();
296 return;
297 }
298 gotsig[signo - 1] = 1;
299 pendingsigs++;
300}
301
302
303
304/*
305 * Called to execute a trap. Perhaps we should avoid entering new trap
306 * handlers while we are executing a trap handler.
307 */
308
309void
310dotrap() {
311 int i;
312 int savestatus;
313
314 for (;;) {
315 for (i = 1 ; ; i++) {
316 if (gotsig[i - 1])
317 break;
318 if (i >= NSIG)
319 goto done;
320 }
321 gotsig[i - 1] = 0;
322 savestatus=exitstatus;
323 evalstring(trap[i], 0);
324 exitstatus=savestatus;
325 }
326done:
327 pendingsigs = 0;
328}
329
330
331
332/*
333 * Controls whether the shell is interactive or not.
334 */
335
336
337void
338setinteractive(on)
339 int on;
340{
341 static int is_interactive;
342
343 if (on == is_interactive)
344 return;
345 setsignal(SIGINT);
346 setsignal(SIGQUIT);
347 setsignal(SIGTERM);
348 chkmail(1);
349 is_interactive = on;
350}
351
352
353
354/*
355 * Called to exit the shell.
356 */
357
358void
359exitshell(status)
360 int status;
361{
362 struct jmploc loc1, loc2;
363 char *p;
364
365 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
366#ifdef HETIO
367 hetio_reset_term();
368#endif
369 if (setjmp(loc1.loc)) {
370 goto l1;
371 }
372 if (setjmp(loc2.loc)) {
373 goto l2;
374 }
375 handler = &loc1;
376 if ((p = trap[0]) != NULL && *p != '\0') {
377 trap[0] = NULL;
378 evalstring(p, 0);
379 }
380l1: handler = &loc2; /* probably unnecessary */
381 flushall();
382#if JOBS
383 setjobctl(0);
384#endif
385l2: _exit(status);
386 /* NOTREACHED */
387}
388
389int decode_signal(const char *string)
390{
391 int signo;
392
393 if (is_number(string)) return atoi(string);
394
395 for (signo=0; signo < NSIG; signo++)
396 if (strcasecmp(string, signal_names[signo]) == 0 ||
397 strcasecmp(string, &(signal_names[signo])[3]) == 0)
398 return signo;
399
400 return -1;
401}
Note: See TracBrowser for help on using the repository browser.