aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 13:52:51 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 13:52:51 +0000
commite4bd4f2cc8413bf3417ae902fcd14580a056a69c (patch)
treedaa1569fbda13dc0cce2caddf1748d24db915d69 /shell
parentf8c1f02d2f7733619437581c2264828d3d160089 (diff)
downloadbusybox-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.c73
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 */
1025enum {
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
2285static void reset_traps_to_defaults(void) 2296static 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)