Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (hide annotations) (download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 8722 byte(s)
-updated to klibc-1.5.19
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 niro 1122 char sigmode[NSIG - 1];
76 niro 532 /* indicates specified signal received */
77 niro 1122 static char gotsig[NSIG - 1];
78 niro 532 /* last pending signal */
79     volatile sig_atomic_t pendingsigs;
80    
81     #ifdef mkinit
82 niro 1122 INCLUDE "trap.h"
83 niro 532 INIT {
84 niro 1122 sigmode[SIGCHLD - 1] = S_DFL;
85     setsignal(SIGCHLD);
86 niro 532 }
87     #endif
88    
89     /*
90     * The trap builtin.
91     */
92    
93     int
94     trapcmd(int argc, char **argv)
95     {
96     char *action;
97     char **ap;
98     int signo;
99    
100     nextopt(nullstr);
101     ap = argptr;
102     if (!*ap) {
103     for (signo = 0 ; signo < NSIG ; signo++) {
104     if (trap[signo] != NULL) {
105     out1fmt(
106     "trap -- %s %s\n",
107     single_quote(trap[signo]),
108     signal_name(signo)
109     );
110     }
111     }
112     return 0;
113     }
114     if (!ap[1])
115     action = NULL;
116     else
117     action = *ap++;
118     while (*ap) {
119 niro 1122 if ((signo = decode_signal(*ap, 0)) < 0) {
120     outfmt(out2, "trap: %s: bad trap\n", *ap);
121     return 1;
122     }
123 niro 532 INTOFF;
124     if (action) {
125     if (action[0] == '-' && action[1] == '\0')
126     action = NULL;
127     else
128     action = savestr(action);
129     }
130     if (trap[signo])
131     ckfree(trap[signo]);
132     trap[signo] = action;
133     if (signo != 0)
134     setsignal(signo);
135     INTON;
136     ap++;
137     }
138     return 0;
139     }
140    
141    
142    
143     /*
144     * Clear traps on a fork.
145     */
146    
147     void
148     clear_traps(void)
149     {
150     char **tp;
151    
152     for (tp = trap ; tp < &trap[NSIG] ; tp++) {
153     if (*tp && **tp) { /* trap not NULL or SIG_IGN */
154     INTOFF;
155     ckfree(*tp);
156     *tp = NULL;
157     if (tp != &trap[0])
158     setsignal(tp - trap);
159     INTON;
160     }
161     }
162     }
163    
164    
165    
166     /*
167     * Set the signal handler for the specified signal. The routine figures
168     * out what it should be set to.
169     */
170    
171     void
172     setsignal(int signo)
173     {
174     int action;
175     char *t, tsig;
176     struct sigaction act;
177    
178     if ((t = trap[signo]) == NULL)
179     action = S_DFL;
180     else if (*t != '\0')
181     action = S_CATCH;
182     else
183     action = S_IGN;
184     if (rootshell && action == S_DFL) {
185     switch (signo) {
186     case SIGINT:
187     if (iflag || minusc || sflag == 0)
188     action = S_CATCH;
189     break;
190     case SIGQUIT:
191     #ifdef DEBUG
192     if (debug)
193     break;
194     #endif
195     /* FALLTHROUGH */
196     case SIGTERM:
197     if (iflag)
198     action = S_IGN;
199     break;
200     #if JOBS
201     case SIGTSTP:
202     case SIGTTOU:
203     if (mflag)
204     action = S_IGN;
205     break;
206     #endif
207     }
208     }
209    
210 niro 1122 if (signo == SIGCHLD)
211     action = S_CATCH;
212    
213 niro 532 t = &sigmode[signo - 1];
214     tsig = *t;
215     if (tsig == 0) {
216     /*
217     * current setting unknown
218     */
219     if (sigaction(signo, 0, &act) == -1) {
220     /*
221     * Pretend it worked; maybe we should give a warning
222     * here, but other shells don't. We don't alter
223     * sigmode, so that we retry every time.
224     */
225     return;
226     }
227     if (act.sa_handler == SIG_IGN) {
228     if (mflag && (signo == SIGTSTP ||
229     signo == SIGTTIN || signo == SIGTTOU)) {
230     tsig = S_IGN; /* don't hard ignore these */
231     } else
232     tsig = S_HARD_IGN;
233     } else {
234     tsig = S_RESET; /* force to be set */
235     }
236     }
237     if (tsig == S_HARD_IGN || tsig == action)
238     return;
239     switch (action) {
240     case S_CATCH:
241     act.sa_handler = onsig;
242     break;
243     case S_IGN:
244     act.sa_handler = SIG_IGN;
245     break;
246     default:
247     act.sa_handler = SIG_DFL;
248     }
249     *t = action;
250     act.sa_flags = 0;
251     sigfillset(&act.sa_mask);
252     sigaction(signo, &act, 0);
253     }
254    
255     /*
256     * Ignore a signal.
257     */
258    
259     void
260     ignoresig(int signo)
261     {
262     if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
263     signal(signo, SIG_IGN);
264     }
265     sigmode[signo - 1] = S_HARD_IGN;
266     }
267    
268    
269    
270     /*
271     * Signal handler.
272     */
273    
274     void
275     onsig(int signo)
276     {
277     gotsig[signo - 1] = 1;
278     pendingsigs = signo;
279    
280 niro 1122 if (signo == SIGINT && !trap[SIGINT]) {
281 niro 532 if (!suppressint)
282     onint();
283     intpending = 1;
284     }
285     }
286    
287    
288    
289     /*
290     * Called to execute a trap. Perhaps we should avoid entering new trap
291     * handlers while we are executing a trap handler.
292     */
293    
294     int
295     dotrap(void)
296     {
297     char *p;
298     char *q;
299     int i;
300     int savestatus;
301    
302     savestatus = exitstatus;
303     pendingsigs = 0;
304     barrier();
305    
306     for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
307     if (!*q)
308     continue;
309     *q = 0;
310    
311     p = trap[i + 1];
312     if (!p)
313     continue;
314 niro 1122 evalstring(p, 0);
315 niro 532 exitstatus = savestatus;
316 niro 815 if (evalskip)
317     return evalskip;
318 niro 532 }
319    
320 niro 815 return 0;
321 niro 532 }
322    
323    
324    
325     /*
326     * Controls whether the shell is interactive or not.
327     */
328    
329    
330     void
331     setinteractive(int on)
332     {
333     static int is_interactive;
334    
335     if (++on == is_interactive)
336     return;
337     is_interactive = on;
338     setsignal(SIGINT);
339     setsignal(SIGQUIT);
340     setsignal(SIGTERM);
341     }
342    
343    
344    
345     /*
346     * Called to exit the shell.
347     */
348    
349     void
350     exitshell(void)
351     {
352     struct jmploc loc;
353     char *p;
354     int status;
355    
356     #ifdef HETIO
357     hetio_reset_term();
358     #endif
359     status = exitstatus;
360     TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
361     if (setjmp(loc.loc)) {
362     if (exception == EXEXIT)
363 niro 1122 status = exitstatus;
364 niro 532 goto out;
365     }
366     handler = &loc;
367     if ((p = trap[0])) {
368     trap[0] = NULL;
369 niro 1122 evalskip = 0;
370 niro 532 evalstring(p, 0);
371     }
372 niro 1122 out:
373     /*
374     * Disable job control so that whoever had the foreground before we
375     * started can get it back.
376     */
377     if (likely(!setjmp(loc.loc)))
378     setjobctl(0);
379 niro 532 flushall();
380     _exit(status);
381     /* NOTREACHED */
382     }
383    
384     /*
385     * Decode a signal name
386     */
387     int decode_signal(const char *string, int minsig)
388     {
389     int i;
390    
391     if (is_number(string)) {
392     i = atoi(string);
393     if (i >= NSIG) {
394     return -1;
395     }
396     return i;
397     }
398    
399     for ( i = minsig ; i < NSIG ; i++ ) {
400     if ( sys_sigabbrev[i] &&
401     !strcasecmp(string, sys_sigabbrev[i]) )
402     return i;
403     }
404    
405     #ifdef SIGRTMIN
406     if ( !strncasecmp(string, "RTMIN", 5) ) {
407     char *ep;
408    
409     if ( string[5] && string[5] != '+' )
410     return -1;
411     i = SIGRTMIN + strtol(string+5, &ep, 10);
412     if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
413     return -1;
414     return i;
415     }
416    
417     if ( !strncasecmp(string, "RTMAX", 5) ) {
418     char *ep;
419    
420     if ( string[5] && string[5] != '-' )
421     return -1;
422     i = SIGRTMAX + strtol(string+5, &ep, 10);
423     if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
424     return -1;
425     return i;
426     }
427     #endif
428    
429     return -1;
430     }
431    
432     /*
433     * Human-readable signal name
434     */
435     const char *
436     signal_name(int sig)
437     {
438     static char buf[64];
439    
440     if ( sig < 0 || sig >= NSIG ) {
441     return NULL;
442     } else if ( sys_sigabbrev[sig] ) {
443     return sys_sigabbrev[sig];
444     #ifdef SIGRTMIN
445     } else if ( sig >= SIGRTMIN && sig <= SIGRTMAX ) {
446     snprintf(buf, sizeof buf, "RTMIN+%d", sig-SIGRTMIN);
447     return buf;
448     #endif
449     } else {
450     snprintf(buf, sizeof buf, "%d", sig);
451     return buf;
452     }
453     }