svn commit: [25966] trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sun Apr 5 20:33:27 UTC 2009


Author: vda
Date: 2009-04-05 20:33:27 +0000 (Sun, 05 Apr 2009)
New Revision: 25966

Log:
hush: fix trap clearing in subshells on MMU; simplify NOMMU a bit:

function                                             old     new   delta
parse_stream_dquoted                                 335     324     -11
handle_dollar                                        849     800     -49
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-60)             Total: -60 bytes



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-04-05 19:13:39 UTC (rev 25965)
+++ trunk/busybox/shell/hush.c	2009-04-05 20:33:27 UTC (rev 25966)
@@ -1603,10 +1603,10 @@
 #endif
 static char *expand_string_to_string(const char *str);
 #if BB_MMU
-#define parse_stream_dquoted(ctx, dest, input, dquote_end) \
+#define parse_stream_dquoted(as_string, dest, input, dquote_end) \
 	parse_stream_dquoted(dest, input, dquote_end)
 #endif
-static int parse_stream_dquoted(struct parse_context *ctx,
+static int parse_stream_dquoted(o_string *as_string,
 		o_string *dest,
 		struct in_str *input,
 		int dquote_end);
@@ -2275,7 +2275,38 @@
 	_exit(EXIT_FAILURE);
 }
 
-#if !BB_MMU
+#if BB_MMU
+static void reset_traps_to_defaults(void)
+{
+	unsigned sig;
+	int dirty;
+
+	if (!G.traps)
+		return;
+	dirty = 0;
+	for (sig = 0; sig < NSIG; sig++) {
+		if (!G.traps[sig])
+			continue;
+		free(G.traps[sig]);
+		G.traps[sig] = NULL;
+		/* There is no signal for 0 (EXIT) */
+		if (sig == 0)
+			continue;
+		/* there was a trap handler, we are removing it
+		 * (if sig has non-DFL handling,
+		 * we don't need to do anything) */
+		if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
+			continue;
+		sigdelset(&G.blocked_set, sig);
+		dirty = 1;
+	}
+	if (dirty)
+		sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+}
+#define clean_up_after_re_execute() ((void)0)
+
+#else /* !BB_MMU */
+
 static void re_execute_shell(const char *s) NORETURN;
 static void re_execute_shell(const char *s)
 {
@@ -2310,13 +2341,32 @@
 			*pp++ = cur->varstr;
 		}
 	}
+//TODO: pass functions
+	/* We can pass activated traps here. Say, -Tnn:trap_string
+	 *
+	 * However, POSIX says that subshells reset signals with traps
+	 * to SIG_DFL.
+	 * I tested bash-3.2 and it not only does that with true subshells
+	 * of the form ( list ), but with any forked children shells.
+	 * I set trap "echo W" WINCH; and then tried:
+	 *
+	 * { echo 1; sleep 20; echo 2; } &
+	 * while true; do echo 1; sleep 20; echo 2; break; done &
+	 * true | { echo 1; sleep 20; echo 2; } | cat
+	 *
+	 * In all these cases sending SIGWINCH to the child shell
+	 * did not run the trap. If I add trap "echo V" WINCH;
+	 * _inside_ group (just before echo 1), it works.
+	 *
+	 * I conclude it means we don't need to pass active traps here.
+	 * exec syscall below resets them to SIG_DFL for us.
+	 */
 	*pp++ = (char *) "-c";
 	*pp++ = (char *) s;
 	pp2 = G.global_argv;
 	while (*pp2)
 		*pp++ = *pp2++;
 	/* *pp = NULL; - is already there */
-//TODO: pass traps and functions
 
 	debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
 	sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
@@ -2343,8 +2393,6 @@
 		G.argv_from_re_execing = NULL;
 	}
 }
-#else
-#define clean_up_after_re_execute() ((void)0)
 #endif
 
 static int run_list(struct pipe *pi);
@@ -2373,6 +2421,7 @@
 #if BB_MMU
 		int rcode;
 		debug_printf_exec("pseudo_exec: run_list\n");
+		reset_traps_to_defaults();
 		rcode = run_list(command->group);
 		/* OK to leak memory by not calling free_pipe_list,
 		 * since this process is about to exit */
@@ -3846,6 +3895,7 @@
 		/* Prevent it from trying to handle ctrl-z etc */
 		USE_HUSH_JOB(G.run_list_level = 1;)
 #if BB_MMU
+		reset_traps_to_defaults();
 		parse_and_run_string(s);
 		_exit(G.last_return_code);
 #else
@@ -4097,10 +4147,10 @@
 
 /* Return code: 0 for OK, 1 for syntax error */
 #if BB_MMU
-#define handle_dollar(ctx, dest, input) \
+#define handle_dollar(as_string, dest, input) \
 	handle_dollar(dest, input)
 #endif
-static int handle_dollar(struct parse_context *ctx,
+static int handle_dollar(o_string *as_string,
 		o_string *dest,
 		struct in_str *input)
 {
@@ -4112,7 +4162,7 @@
 	if (isalpha(ch)) {
 		ch = i_getch(input);
 #if !BB_MMU
-		if (ctx) o_addchr(&ctx->as_string, ch);
+		if (as_string) o_addchr(as_string, ch);
 #endif
  make_var:
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4125,7 +4175,7 @@
 				break;
 			ch = i_getch(input);
 #if !BB_MMU
-			if (ctx) o_addchr(&ctx->as_string, ch);
+			if (as_string) o_addchr(as_string, ch);
 #endif
 		}
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4133,7 +4183,7 @@
  make_one_char_var:
 		ch = i_getch(input);
 #if !BB_MMU
-		if (ctx) o_addchr(&ctx->as_string, ch);
+		if (as_string) o_addchr(as_string, ch);
 #endif
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 		debug_printf_parse(": '%c'\n", ch);
@@ -4153,7 +4203,7 @@
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 		ch = i_getch(input);
 #if !BB_MMU
-		if (ctx) o_addchr(&ctx->as_string, ch);
+		if (as_string) o_addchr(as_string, ch);
 #endif
 		/* XXX maybe someone will try to escape the '}' */
 		expansion = 0;
@@ -4162,7 +4212,7 @@
 		while (1) {
 			ch = i_getch(input);
 #if !BB_MMU
-			if (ctx) o_addchr(&ctx->as_string, ch);
+			if (as_string) o_addchr(as_string, ch);
 #endif
 			if (ch == '}')
 				break;
@@ -4235,13 +4285,13 @@
 # endif
 		ch = i_getch(input);
 # if !BB_MMU
-		if (ctx) o_addchr(&ctx->as_string, ch);
+		if (as_string) o_addchr(as_string, ch);
 # endif
 # if ENABLE_SH_MATH_SUPPORT
 		if (i_peek(input) == '(') {
 			ch = i_getch(input);
 #  if !BB_MMU
-			if (ctx) o_addchr(&ctx->as_string, ch);
+			if (as_string) o_addchr(as_string, ch);
 #  endif
 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
 			o_addchr(dest, /*quote_mask |*/ '+');
@@ -4250,10 +4300,10 @@
 #  endif
 			add_till_closing_paren(dest, input, true);
 #  if !BB_MMU
-			if (ctx) {
-				o_addstr(&ctx->as_string, dest->data + pos);
-				o_addchr(&ctx->as_string, ')');
-				o_addchr(&ctx->as_string, ')');
+			if (as_string) {
+				o_addstr(as_string, dest->data + pos);
+				o_addchr(as_string, ')');
+				o_addchr(as_string, ')');
 			}
 #  endif
 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4269,9 +4319,9 @@
 #  endif
 		add_till_closing_paren(dest, input, false);
 #  if !BB_MMU
-		if (ctx) {
-			o_addstr(&ctx->as_string, dest->data + pos);
-			o_addchr(&ctx->as_string, '`');
+		if (as_string) {
+			o_addstr(as_string, dest->data + pos);
+			o_addchr(as_string, '`');
 		}
 #  endif
 		//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
@@ -4283,7 +4333,7 @@
 	case '_':
 		ch = i_getch(input);
 #if !BB_MMU
-		if (ctx) o_addchr(&ctx->as_string, ch);
+		if (as_string) o_addchr(as_string, ch);
 #endif
 		ch = i_peek(input);
 		if (isalnum(ch)) { /* it's $_name or $_123 */
@@ -4302,10 +4352,10 @@
 }
 
 #if BB_MMU
-#define parse_stream_dquoted(ctx, dest, input, dquote_end) \
+#define parse_stream_dquoted(as_string, dest, input, dquote_end) \
 	parse_stream_dquoted(dest, input, dquote_end)
 #endif
-static int parse_stream_dquoted(struct parse_context *ctx,
+static int parse_stream_dquoted(o_string *as_string,
 		o_string *dest,
 		struct in_str *input,
 		int dquote_end)
@@ -4316,8 +4366,8 @@
  again:
 	ch = i_getch(input);
 #if !BB_MMU
-	if (ctx && ch != EOF)
-		o_addchr(&ctx->as_string, ch);
+	if (as_string && ch != EOF)
+		o_addchr(as_string, ch);
 #endif
 	if (ch == dquote_end) { /* may be only '"' or EOF */
 		dest->nonnull = 1;
@@ -4360,7 +4410,7 @@
 		goto again;
 	}
 	if (ch == '$') {
-		if (handle_dollar(ctx, dest, input) != 0) {
+		if (handle_dollar(as_string, dest, input) != 0) {
 			debug_printf_parse("parse_stream_dquoted return 1: "
 					"handle_dollar returned non-0\n");
 			return 1;
@@ -4432,7 +4482,7 @@
 		redir_type redir_style;
 
 		if (is_in_dquote) {
-			if (parse_stream_dquoted(&ctx, &dest, input, '"')) {
+			if (parse_stream_dquoted(&ctx.as_string, &dest, input, '"')) {
 				goto parse_error;
 			}
 			/* We reached closing '"' */
@@ -4579,8 +4629,7 @@
 #endif
 			break;
 		case '$':
-//NOMMU TODO!
-			if (handle_dollar(&ctx, &dest, input) != 0) {
+			if (handle_dollar(&ctx.as_string, &dest, input) != 0) {
 				debug_printf_parse("parse_stream parse error: "
 					"handle_dollar returned non-0\n");
 				goto parse_error;
@@ -5023,6 +5072,15 @@
 	G.PS2 = "> ";
 #endif
 
+	/* Shell is non-interactive at first. We need to call
+	 * block_signals(0) if we are going to execute "sh script",
+	 * "sh -c cmds" or login shell's /etc/profile and friends.
+	 * If we later decide that we are interactive, we run block_signals(0)
+	 * (or re-run block_signals(1) if we ran block_signals(0) before)
+	 * in order to intercept (more) signals.
+	 */
+
+	/* Parse options */
 	/* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
 	while (1) {
 		opt = getopt(argc, argv, "c:xins"
@@ -5136,7 +5194,9 @@
 		goto final_return;
 	}
 
-	/* Up to here, shell was non-interactive. Now it may become one. */
+	/* Up to here, shell was non-interactive. Now it may become one.
+	 * NB: don't forget to (re)run block_signals(0/1) as needed.
+	 */
 
 	/* A shell is interactive if the '-i' flag was given, or if all of
 	 * the following conditions are met:



More information about the busybox-cvs mailing list