VirtualBox

source: kBuild/trunk/src/ash/trap.c@ 1158

Last change on this file since 1158 was 809, checked in by bird, 18 years ago

Solaris + cleanup.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette