Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 815 - (show 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 /*-
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 evalstring(p, SKIPEVAL);
311 exitstatus = savestatus;
312 if (evalskip)
313 return evalskip;
314 }
315
316 return 0;
317 }
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 }