Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/trap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 8526 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1997-2005
5 * Herbert Xu <herbert@gondor.apana.org.au>. 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 #include <signal.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdio.h>
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 "show.h"
47 #include "options.h"
48 #include "syntax.h"
49 #include "output.h"
50 #include "memalloc.h"
51 #include "error.h"
52 #include "trap.h"
53 #include "mystring.h"
54
55 #ifdef HETIO
56 #include "hetio.h"
57 #endif
58
59 /*
60 * Sigmode records the current value of the signal handlers for the various
61 * modes. A value of zero means that the current handler is not known.
62 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
63 */
64
65 #define S_DFL 1 /* default signal handling (SIG_DFL) */
66 #define S_CATCH 2 /* signal is caught */
67 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
68 #define S_HARD_IGN 4 /* signal is ignored permenantly */
69 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
70
71
72 /* trap handler commands */
73 char *trap[NSIG];
74 /* current value of signal */
75 static char sigmode[NSIG - 1];
76 /* indicates specified signal received */
77 char gotsig[NSIG - 1];
78 /* last pending signal */
79 volatile sig_atomic_t pendingsigs;
80 /* do we generate EXSIG events */
81 int exsig;
82
83 #ifdef mkinit
84 INCLUDE <signal.h>
85 INIT {
86 signal(SIGCHLD, SIG_DFL);
87 }
88 #endif
89
90 /*
91 * The trap builtin.
92 */
93
94 int
95 trapcmd(int argc, char **argv)
96 {
97 char *action;
98 char **ap;
99 int signo;
100
101 nextopt(nullstr);
102 ap = argptr;
103 if (!*ap) {
104 for (signo = 0 ; signo < NSIG ; signo++) {
105 if (trap[signo] != NULL) {
106 out1fmt(
107 "trap -- %s %s\n",
108 single_quote(trap[signo]),
109 signal_name(signo)
110 );
111 }
112 }
113 return 0;
114 }
115 if (!ap[1])
116 action = NULL;
117 else
118 action = *ap++;
119 while (*ap) {
120 if ((signo = decode_signal(*ap, 0)) < 0)
121 sh_error("%s: bad trap", *ap);
122 INTOFF;
123 if (action) {
124 if (action[0] == '-' && action[1] == '\0')
125 action = NULL;
126 else
127 action = savestr(action);
128 }
129 if (trap[signo])
130 ckfree(trap[signo]);
131 trap[signo] = action;
132 if (signo != 0)
133 setsignal(signo);
134 INTON;
135 ap++;
136 }
137 return 0;
138 }
139
140
141
142 /*
143 * Clear traps on a fork.
144 */
145
146 void
147 clear_traps(void)
148 {
149 char **tp;
150
151 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
152 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
153 INTOFF;
154 ckfree(*tp);
155 *tp = NULL;
156 if (tp != &trap[0])
157 setsignal(tp - trap);
158 INTON;
159 }
160 }
161 }
162
163
164
165 /*
166 * Set the signal handler for the specified signal. The routine figures
167 * out what it should be set to.
168 */
169
170 void
171 setsignal(int signo)
172 {
173 int action;
174 char *t, tsig;
175 struct sigaction act;
176
177 if ((t = trap[signo]) == NULL)
178 action = S_DFL;
179 else if (*t != '\0')
180 action = S_CATCH;
181 else
182 action = S_IGN;
183 if (rootshell && action == S_DFL) {
184 switch (signo) {
185 case SIGINT:
186 if (iflag || minusc || sflag == 0)
187 action = S_CATCH;
188 break;
189 case SIGQUIT:
190 #ifdef DEBUG
191 if (debug)
192 break;
193 #endif
194 /* FALLTHROUGH */
195 case SIGTERM:
196 if (iflag)
197 action = S_IGN;
198 break;
199 #if JOBS
200 case SIGTSTP:
201 case SIGTTOU:
202 if (mflag)
203 action = S_IGN;
204 break;
205 #endif
206 }
207 }
208
209 t = &sigmode[signo - 1];
210 tsig = *t;
211 if (tsig == 0) {
212 /*
213 * current setting unknown
214 */
215 if (sigaction(signo, 0, &act) == -1) {
216 /*
217 * Pretend it worked; maybe we should give a warning
218 * here, but other shells don't. We don't alter
219 * sigmode, so that we retry every time.
220 */
221 return;
222 }
223 if (act.sa_handler == SIG_IGN) {
224 if (mflag && (signo == SIGTSTP ||
225 signo == SIGTTIN || signo == SIGTTOU)) {
226 tsig = S_IGN; /* don't hard ignore these */
227 } else
228 tsig = S_HARD_IGN;
229 } else {
230 tsig = S_RESET; /* force to be set */
231 }
232 }
233 if (tsig == S_HARD_IGN || tsig == action)
234 return;
235 switch (action) {
236 case S_CATCH:
237 act.sa_handler = onsig;
238 break;
239 case S_IGN:
240 act.sa_handler = SIG_IGN;
241 break;
242 default:
243 act.sa_handler = SIG_DFL;
244 }
245 *t = action;
246 act.sa_flags = 0;
247 sigfillset(&act.sa_mask);
248 sigaction(signo, &act, 0);
249 }
250
251 /*
252 * Ignore a signal.
253 */
254
255 void
256 ignoresig(int signo)
257 {
258 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
259 signal(signo, SIG_IGN);
260 }
261 sigmode[signo - 1] = S_HARD_IGN;
262 }
263
264
265
266 /*
267 * Signal handler.
268 */
269
270 void
271 onsig(int signo)
272 {
273 gotsig[signo - 1] = 1;
274 pendingsigs = signo;
275
276 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
277 if (!suppressint)
278 onint();
279 intpending = 1;
280 }
281 }
282
283
284
285 /*
286 * Called to execute a trap. Perhaps we should avoid entering new trap
287 * handlers while we are executing a trap handler.
288 */
289
290 int
291 dotrap(void)
292 {
293 char *p;
294 char *q;
295 int i;
296 int savestatus;
297 int skip = 0;
298
299 savestatus = exitstatus;
300 pendingsigs = 0;
301 barrier();
302
303 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
304 if (!*q)
305 continue;
306 *q = 0;
307
308 p = trap[i + 1];
309 if (!p)
310 continue;
311 skip = evalstring(p, SKIPEVAL);
312 exitstatus = savestatus;
313 if (skip)
314 break;
315 }
316
317 return skip;
318 }
319
320
321
322 /*
323 * Controls whether the shell is interactive or not.
324 */
325
326
327 void
328 setinteractive(int on)
329 {
330 static int is_interactive;
331
332 if (++on == is_interactive)
333 return;
334 is_interactive = on;
335 setsignal(SIGINT);
336 setsignal(SIGQUIT);
337 setsignal(SIGTERM);
338 }
339
340
341
342 /*
343 * Called to exit the shell.
344 */
345
346 void
347 exitshell(void)
348 {
349 struct jmploc loc;
350 char *p;
351 int status;
352
353 #ifdef HETIO
354 hetio_reset_term();
355 #endif
356 status = exitstatus;
357 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
358 if (setjmp(loc.loc)) {
359 if (exception == EXEXIT)
360 _exit(exitstatus);
361 goto out;
362 }
363 handler = &loc;
364 if ((p = trap[0])) {
365 trap[0] = NULL;
366 evalstring(p, 0);
367 }
368 flushall();
369 out:
370 _exit(status);
371 /* NOTREACHED */
372 }
373
374 /*
375 * Decode a signal name
376 */
377 int decode_signal(const char *string, int minsig)
378 {
379 int i;
380
381 if (is_number(string)) {
382 i = atoi(string);
383 if (i >= NSIG) {
384 return -1;
385 }
386 return i;
387 }
388
389 for ( i = minsig ; i < NSIG ; i++ ) {
390 if ( sys_sigabbrev[i] &&
391 !strcasecmp(string, sys_sigabbrev[i]) )
392 return i;
393 }
394
395 #ifdef SIGRTMIN
396 if ( !strncasecmp(string, "RTMIN", 5) ) {
397 char *ep;
398
399 if ( string[5] && string[5] != '+' )
400 return -1;
401 i = SIGRTMIN + strtol(string+5, &ep, 10);
402 if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
403 return -1;
404 return i;
405 }
406
407 if ( !strncasecmp(string, "RTMAX", 5) ) {
408 char *ep;
409
410 if ( string[5] && string[5] != '-' )
411 return -1;
412 i = SIGRTMAX + strtol(string+5, &ep, 10);
413 if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
414 return -1;
415 return i;
416 }
417 #endif
418
419 return -1;
420 }
421
422 /*
423 * Human-readable signal name
424 */
425 const char *
426 signal_name(int sig)
427 {
428 static char buf[64];
429
430 if ( sig < 0 || sig >= NSIG ) {
431 return NULL;
432 } else if ( sys_sigabbrev[sig] ) {
433 return sys_sigabbrev[sig];
434 #ifdef SIGRTMIN
435 } else if ( sig >= SIGRTMIN && sig <= SIGRTMAX ) {
436 snprintf(buf, sizeof buf, "RTMIN+%d", sig-SIGRTMIN);
437 return buf;
438 #endif
439 } else {
440 snprintf(buf, sizeof buf, "%d", sig);
441 return buf;
442 }
443 }