svn commit: [25955] trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sun Apr 5 01:43:00 UTC 2009


Author: vda
Date: 2009-04-05 01:42:59 +0000 (Sun, 05 Apr 2009)
New Revision: 25955

Log:
hush: fix all testsuite failures on NOMMU except memory leak.
 known TODOs: we do not pass traps and positional args yet.



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-04-04 23:15:14 UTC (rev 25954)
+++ trunk/busybox/shell/hush.c	2009-04-05 01:42:59 UTC (rev 25955)
@@ -1055,13 +1055,18 @@
 
 /* str holds "NAME=VAL" and is expected to be malloced.
  * We take ownership of it.
- * flg_export is used by:
+ * flg_export:
  *  0: do not export
  *  1: export
  * -1: if NAME is set, leave export status alone
  *     if NAME is not set, do not export
+ * flg_read_only is set only when we handle -R var=val
  */
-static int set_local_var(char *str, int flg_export)
+#if BB_MMU
+#define set_local_var(str, flg_export, flg_read_only) \
+	set_local_var(str, flg_export)
+#endif
+static int set_local_var(char *str, int flg_export, int flg_read_only)
 {
 	struct variable *cur;
 	char *value;
@@ -1088,7 +1093,10 @@
 		/* We found an existing var with this name */
 		*value = '\0';
 		if (cur->flg_read_only) {
-			bb_error_msg("%s: readonly variable", str);
+#if !BB_MMU
+			if (!flg_read_only)
+#endif
+				bb_error_msg("%s: readonly variable", str);
 			free(str);
 			return -1;
 		}
@@ -1119,6 +1127,7 @@
 
  set_str_and_exp:
 	cur->varstr = str;
+	cur->flg_read_only = flg_read_only;
  exp:
 	if (flg_export == 1)
 		cur->flg_export = 1;
@@ -1182,7 +1191,7 @@
 {
 	/* arith code doesnt malloc space, so do it for it */
 	char *var = xasprintf("%s=%s", name, val);
-	set_local_var(var, flags);
+	set_local_var(var, flags, 0);
 }
 #endif
 
@@ -1948,7 +1957,7 @@
 						} else {
 							char *new_var = xmalloc(strlen(var) + strlen(val) + 2);
 							sprintf(new_var, "%s=%s", var, val);
-							set_local_var(new_var, -1);
+							set_local_var(new_var, -1, 0);
 						}
 					}
 				}
@@ -2332,9 +2341,40 @@
 static void re_execute_shell(const char *s) NORETURN;
 static void re_execute_shell(const char *s)
 {
-//TODO: pass non-exported variables, traps, and functions
-	debug_printf_exec("re_execute_shell pid:%d cmd:'%s'", getpid(), s);
-	execl(bb_busybox_exec_path, "hush", "-c", s, NULL);
+	struct variable *cur;
+	char **argv, **pp;
+	unsigned cnt;
+
+	/* hush -$<pid> -?<exitcode> ... -c <cmd> NULL */
+	cnt = 6;
+	for (cur = G.top_var; cur; cur = cur->next) {
+		if (!cur->flg_export || cur->flg_read_only)
+			cnt += 2;
+	}
+//TODO: need to free these strings in parent!
+	argv = pp = xmalloc(sizeof(argv[0]) * cnt);
+	*pp++ = (char *) applet_name;
+	*pp++ = xasprintf("-$%u", G.root_pid);
+	*pp++ = xasprintf("-?%u", G.last_return_code);
+	for (cur = G.top_var; cur; cur = cur->next) {
+		if (cur->varstr == hush_version_str)
+			continue;
+		if (cur->flg_read_only) {
+			*pp++ = (char *) "-R";
+			*pp++ = cur->varstr;
+		} else if (!cur->flg_export) {
+			*pp++ = (char *) "-V";
+			*pp++ = cur->varstr;
+		}
+	}
+	*pp++ = (char *) "-c";
+	*pp++ = (char *) s;
+//TODO: pass $N
+	*pp = NULL;
+//TODO: pass traps and functions
+
+	debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
+	execv(bb_busybox_exec_path, argv);
 //TODO: fallback for init=/bin/hush?
 	_exit(127);
 }
@@ -2720,7 +2760,7 @@
 				p = expand_string_to_string(*argv);
 				debug_printf_exec("set shell var:'%s'->'%s'\n",
 						*argv, p);
-				set_local_var(p, 0);
+				set_local_var(p, 0, 0);
 				argv++;
 			}
 			/* Do we need to flag set_local_var() errors?
@@ -4094,7 +4134,7 @@
 	if (isalpha(ch)) {
 		ch = i_getch(input);
 #if !BB_MMU
-		o_addchr(&ctx->as_string, ch);
+		if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
  make_var:
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4107,7 +4147,7 @@
 				break;
 			ch = i_getch(input);
 #if !BB_MMU
-			o_addchr(&ctx->as_string, ch);
+			if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 		}
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4115,7 +4155,7 @@
  make_one_char_var:
 		ch = i_getch(input);
 #if !BB_MMU
-		o_addchr(&ctx->as_string, ch);
+		if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 		debug_printf_parse(": '%c'\n", ch);
@@ -4135,7 +4175,7 @@
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 		ch = i_getch(input);
 #if !BB_MMU
-		o_addchr(&ctx->as_string, ch);
+		if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 		/* XXX maybe someone will try to escape the '}' */
 		expansion = 0;
@@ -4144,7 +4184,7 @@
 		while (1) {
 			ch = i_getch(input);
 #if !BB_MMU
-			o_addchr(&ctx->as_string, ch);
+			if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 			if (ch == '}')
 				break;
@@ -4211,19 +4251,32 @@
 		break;
 	}
 	case '(': {
+#if !BB_MMU
+		int pos;
+#endif
 		ch = i_getch(input);
 #if !BB_MMU
-		o_addchr(&ctx->as_string, ch);
+		if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 #if ENABLE_SH_MATH_SUPPORT
 		if (i_peek(input) == '(') {
 			ch = i_getch(input);
 #if !BB_MMU
-			o_addchr(&ctx->as_string, ch);
+			if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
 			o_addchr(dest, /*quote_mask |*/ '+');
+#if !BB_MMU
+			pos = dest->length;
+#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, ')');
+			}
+#endif
 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
 			break;
 		}
@@ -4232,7 +4285,16 @@
 		//int pos = dest->length;
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 		o_addchr(dest, quote_mask | '`');
+#if !BB_MMU
+		pos = dest->length;
+#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, '`');
+		}
+#endif
 		//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
 #endif
@@ -4241,7 +4303,7 @@
 	case '_':
 		ch = i_getch(input);
 #if !BB_MMU
-		o_addchr(&ctx->as_string, ch);
+		if (ctx) o_addchr(&ctx->as_string, ch);
 #endif
 		ch = i_peek(input);
 		if (isalnum(ch)) { /* it's $_name or $_123 */
@@ -4293,8 +4355,8 @@
 	if (ch != '\n') {
 		next = i_peek(input);
 	}
-	debug_printf_parse(": ch=%c (%d) m=%d escape=%d\n",
-					ch, ch, m, dest->o_escape);
+	debug_printf_parse(": ch=%c (%d) escape=%d\n",
+					ch, ch, dest->o_escape);
 	if (ch == '\\') {
 		if (next == EOF) {
 			syntax("\\<eof>");
@@ -4944,7 +5006,14 @@
 	input = stdin;
 
 	/* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
-	while ((opt = getopt(argc, argv, "c:xins")) > 0) {
+	while (1) {
+		opt = getopt(argc, argv, "c:xins"
+#if !BB_MMU
+				"$:?:R:V:"
+#endif
+		);
+		if (opt <= 0)
+			break;
 		switch (opt) {
 		case 'c':
 			G.global_argv = argv + optind;
@@ -4965,6 +5034,18 @@
 			/* "-s" means "read from stdin", but this is how we always
 			 * operate, so simply do nothing here. */
 			break;
+#if !BB_MMU
+		case '$':
+			G.root_pid = xatoi_u(optarg);
+			break;
+		case '?':
+			G.last_return_code = xatoi_u(optarg);
+			break;
+		case 'R':
+		case 'V':
+			set_local_var(xstrdup(optarg), 0, opt == 'R');
+			break;
+#endif
 		case 'n':
 		case 'x':
 			if (!set_mode('-', opt))
@@ -5293,7 +5374,7 @@
 		return EXIT_SUCCESS;
 	}
 
-	set_local_var(xstrdup(name), 1);
+	set_local_var(xstrdup(name), 1, 0);
 	return EXIT_SUCCESS;
 }
 
@@ -5406,7 +5487,7 @@
 	const char *name = argv[1] ? argv[1] : "REPLY";
 
 	string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL);
-	return set_local_var(string, 0);
+	return set_local_var(string, 0, 0);
 }
 
 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set



More information about the busybox-cvs mailing list