Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 815 - (hide annotations) (download)
Fri Apr 24 18:32:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 8515 byte(s)
-updated to klibc-1.5.15
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    
298     savestatus = exitstatus;
299     pendingsigs = 0;
300     barrier();
301    
302     for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
303     if (!*q)
304     continue;
305     *q = 0;
306    
307     p = trap[i + 1];
308     if (!p)
309     continue;
310 niro 815 evalstring(p, SKIPEVAL);
311 niro 532 exitstatus = savestatus;
312 niro 815 if (evalskip)
313     return evalskip;
314 niro 532 }
315    
316 niro 815 return 0;
317 niro 532 }
318    
319    
320    
321     /*
322     * Controls whether the shell is interactive or not.
323     */
324    
325    
326     void
327     setinteractive(int on)
328     {
329     static int is_interactive;
330    
331     if (++on == is_interactive)
332     return;
333     is_interactive = on;
334     setsignal(SIGINT);
335     setsignal(SIGQUIT);
336     setsignal(SIGTERM);
337     }
338    
339    
340    
341     /*
342     * Called to exit the shell.
343     */
344    
345     void
346     exitshell(void)
347     {
348     struct jmploc loc;
349     char *p;
350     int status;
351    
352     #ifdef HETIO
353     hetio_reset_term();
354     #endif
355     status = exitstatus;
356     TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
357     if (setjmp(loc.loc)) {
358     if (exception == EXEXIT)
359     _exit(exitstatus);
360     goto out;
361     }
362     handler = &loc;
363     if ((p = trap[0])) {
364     trap[0] = NULL;
365     evalstring(p, 0);
366     }
367     flushall();
368     out:
369     _exit(status);
370     /* NOTREACHED */
371     }
372    
373     /*
374     * Decode a signal name
375     */
376     int decode_signal(const char *string, int minsig)
377     {
378     int i;
379    
380     if (is_number(string)) {
381     i = atoi(string);
382     if (i >= NSIG) {
383     return -1;
384     }
385     return i;
386     }
387    
388     for ( i = minsig ; i < NSIG ; i++ ) {
389     if ( sys_sigabbrev[i] &&
390     !strcasecmp(string, sys_sigabbrev[i]) )
391     return i;
392     }
393    
394     #ifdef SIGRTMIN
395     if ( !strncasecmp(string, "RTMIN", 5) ) {
396     char *ep;
397    
398     if ( string[5] && string[5] != '+' )
399     return -1;
400     i = SIGRTMIN + strtol(string+5, &ep, 10);
401     if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
402     return -1;
403     return i;
404     }
405    
406     if ( !strncasecmp(string, "RTMAX", 5) ) {
407     char *ep;
408    
409     if ( string[5] && string[5] != '-' )
410     return -1;
411     i = SIGRTMAX + strtol(string+5, &ep, 10);
412     if ( *ep || i < SIGRTMIN || i > SIGRTMAX )
413     return -1;
414     return i;
415     }
416     #endif
417    
418     return -1;
419     }
420    
421     /*
422     * Human-readable signal name
423     */
424     const char *
425     signal_name(int sig)
426     {
427     static char buf[64];
428    
429     if ( sig < 0 || sig >= NSIG ) {
430     return NULL;
431     } else if ( sys_sigabbrev[sig] ) {
432     return sys_sigabbrev[sig];
433     #ifdef SIGRTMIN
434     } else if ( sig >= SIGRTMIN && sig <= SIGRTMAX ) {
435     snprintf(buf, sizeof buf, "RTMIN+%d", sig-SIGRTMIN);
436     return buf;
437     #endif
438     } else {
439     snprintf(buf, sizeof buf, "%d", sig);
440     return buf;
441     }
442     }