diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-17 13:52:51 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-17 13:52:51 +0000 |
commit | e4bd4f2cc8413bf3417ae902fcd14580a056a69c (patch) | |
tree | daa1569fbda13dc0cce2caddf1748d24db915d69 /shell | |
parent | f8c1f02d2f7733619437581c2264828d3d160089 (diff) | |
download | busybox-w32-e4bd4f2cc8413bf3417ae902fcd14580a056a69c.tar.gz busybox-w32-e4bd4f2cc8413bf3417ae902fcd14580a056a69c.tar.bz2 busybox-w32-e4bd4f2cc8413bf3417ae902fcd14580a056a69c.zip |
hush: unblock TERM, INT, HUP in child shells too.
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/shell/hush.c b/shell/hush.c index 8dda988ee..13a06a492 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1022,6 +1022,15 @@ static void free_strings(char **strings) | |||
1022 | * are to count SIGCHLDs [disabled - bug somewhere, + bloat] | 1022 | * are to count SIGCHLDs [disabled - bug somewhere, + bloat] |
1023 | * and to restore tty pgrp on signal-induced exit. | 1023 | * and to restore tty pgrp on signal-induced exit. |
1024 | */ | 1024 | */ |
1025 | enum { | ||
1026 | SPECIAL_INTERACTIVE_SIGS = 0 | ||
1027 | #if ENABLE_HUSH_JOB | ||
1028 | | (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP) | ||
1029 | #endif | ||
1030 | | (1 << SIGTERM) | ||
1031 | //TODO | (1 << SIGHUP) | ||
1032 | | (1 << SIGINT) | ||
1033 | }; | ||
1025 | 1034 | ||
1026 | //static void SIGCHLD_handler(int sig UNUSED_PARAM) | 1035 | //static void SIGCHLD_handler(int sig UNUSED_PARAM) |
1027 | //{ | 1036 | //{ |
@@ -1059,6 +1068,8 @@ static int check_and_run_traps(int sig) | |||
1059 | // G.count_SIGCHLD++; | 1068 | // G.count_SIGCHLD++; |
1060 | // break; | 1069 | // break; |
1061 | case SIGINT: | 1070 | case SIGINT: |
1071 | //TODO: add putchar('\n') also when we detect that child was killed (sleep 5 + ^C) | ||
1072 | /* Builtin was ^C'ed, make it look prettier: */ | ||
1062 | bb_putchar('\n'); | 1073 | bb_putchar('\n'); |
1063 | G.flag_SIGINT = 1; | 1074 | G.flag_SIGINT = 1; |
1064 | break; | 1075 | break; |
@@ -2284,37 +2295,46 @@ void re_execute_shell(char ***to_free, const char *s, char *argv0, char **argv); | |||
2284 | 2295 | ||
2285 | static void reset_traps_to_defaults(void) | 2296 | static void reset_traps_to_defaults(void) |
2286 | { | 2297 | { |
2287 | enum { | 2298 | /* This function is always called in a child shell |
2288 | JOBSIGS = (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP) | 2299 | * after fork (not vfork, NOMMU doesn't use this function). |
2289 | }; | ||
2290 | unsigned sig; | ||
2291 | |||
2292 | if (!G.traps && !(G.non_DFL_mask & JOBSIGS)) | ||
2293 | return; | ||
2294 | |||
2295 | /* This function is always called in a child shell. | ||
2296 | * Child shells are not interactive. | 2300 | * Child shells are not interactive. |
2297 | * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. | 2301 | * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. |
2298 | * Testcase: (while :; do :; done) + ^Z should background. | 2302 | * Testcase: (while :; do :; done) + ^Z should background. |
2303 | * Same goes for SIGTERM, SIGHUP, SIGINT. | ||
2299 | */ | 2304 | */ |
2300 | G.non_DFL_mask &= ~JOBSIGS; | 2305 | unsigned sig; |
2301 | sigdelset(&G.blocked_set, SIGTTIN); | 2306 | unsigned mask; |
2302 | sigdelset(&G.blocked_set, SIGTTOU); | ||
2303 | sigdelset(&G.blocked_set, SIGTSTP); | ||
2304 | 2307 | ||
2305 | if (G.traps) for (sig = 0; sig < NSIG; sig++) { | 2308 | if (!G.traps && !(G.non_DFL_mask & SPECIAL_INTERACTIVE_SIGS)) |
2306 | if (!G.traps[sig]) { | 2309 | return; |
2310 | |||
2311 | /* Stupid. It can be done with *single* &= op, but we can't use | ||
2312 | * the fact that G.blocked_set is implemented as a bitmask... */ | ||
2313 | mask = (SPECIAL_INTERACTIVE_SIGS >> 1); | ||
2314 | sig = 1; | ||
2315 | while (1) { | ||
2316 | if (mask & 1) | ||
2317 | sigdelset(&G.blocked_set, sig); | ||
2318 | mask >>= 1; | ||
2319 | if (!mask) | ||
2320 | break; | ||
2321 | sig++; | ||
2322 | } | ||
2323 | |||
2324 | G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS; | ||
2325 | mask = G.non_DFL_mask; | ||
2326 | if (G.traps) for (sig = 0; sig < NSIG; sig++, mask >>= 1) { | ||
2327 | if (!G.traps[sig]) | ||
2307 | continue; | 2328 | continue; |
2308 | } | ||
2309 | free(G.traps[sig]); | 2329 | free(G.traps[sig]); |
2310 | G.traps[sig] = NULL; | 2330 | G.traps[sig] = NULL; |
2311 | /* There is no signal for 0 (EXIT) */ | 2331 | /* There is no signal for 0 (EXIT) */ |
2312 | if (sig == 0) | 2332 | if (sig == 0) |
2313 | continue; | 2333 | continue; |
2314 | /* there was a trap handler, we are removing it | 2334 | /* There was a trap handler, we are removing it. |
2315 | * (if sig has non-DFL handling, | 2335 | * But if sig still has non-DFL handling, |
2316 | * we don't need to do anything) */ | 2336 | * we should not unblock it. */ |
2317 | if (sig < 32 && (G.non_DFL_mask & (1 << sig))) | 2337 | if (mask & 1) |
2318 | continue; | 2338 | continue; |
2319 | sigdelset(&G.blocked_set, sig); | 2339 | sigdelset(&G.blocked_set, sig); |
2320 | } | 2340 | } |
@@ -5740,17 +5760,8 @@ static void block_signals(int second_time) | |||
5740 | unsigned mask; | 5760 | unsigned mask; |
5741 | 5761 | ||
5742 | mask = (1 << SIGQUIT); | 5762 | mask = (1 << SIGQUIT); |
5743 | if (G_interactive_fd) { | 5763 | if (G_interactive_fd) |
5744 | mask = 0 | 5764 | mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS; |
5745 | | (1 << SIGQUIT) | ||
5746 | | (1 << SIGTERM) | ||
5747 | //TODO | (1 << SIGHUP) | ||
5748 | #if ENABLE_HUSH_JOB | ||
5749 | | (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP) | ||
5750 | #endif | ||
5751 | | (1 << SIGINT) | ||
5752 | ; | ||
5753 | } | ||
5754 | G.non_DFL_mask = mask; | 5765 | G.non_DFL_mask = mask; |
5755 | 5766 | ||
5756 | if (!second_time) | 5767 | if (!second_time) |