Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide 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 niro 532 /*-
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     }