summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko2009-04-03 03:19:15 +0000
committerDenis Vlasenko2009-04-03 03:19:15 +0000
commit3718168b87a5bf5009b90b1e1253bec2c7ce9edf (patch)
tree64037be3206c0ce3cb0c68c114828010cd3da367 /shell
parentf9f74293465e98f2af117a1821a8fbb97cdbc3ed (diff)
downloadbusybox-3718168b87a5bf5009b90b1e1253bec2c7ce9edf.zip
busybox-3718168b87a5bf5009b90b1e1253bec2c7ce9edf.tar.gz
hush: fix bug with local environment vars in pipes; simplify parse_stream()
function old new delta parse_stream 1238 1218 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-20) Total: -20 bytes
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c70
-rw-r--r--shell/hush_test/hush-vars/var_in_pipes.right6
-rwxr-xr-xshell/hush_test/hush-vars/var_in_pipes.tests7
3 files changed, 45 insertions, 38 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d401948..e2259ce 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1657,8 +1657,7 @@ static char **o_finalize_list(o_string *o, int n)
/* Expansion can recurse */
#if ENABLE_HUSH_TICK
-static int process_command_subs(o_string *dest,
- struct in_str *input, const char *subst_end);
+static int process_command_subs(o_string *dest, struct in_str *input);
#endif
static char *expand_string_to_string(const char *str);
static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end);
@@ -1814,7 +1813,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
//TODO: can we just stuff it into "output" directly?
debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
setup_string_in_str(&input, arg);
- process_command_subs(&subst_result, &input, NULL);
+ process_command_subs(&subst_result, &input);
debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
val = subst_result.data;
goto store_val;
@@ -1971,7 +1970,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
}
} /* default: */
} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
-
if (val) {
o_addQstr(output, val, strlen(val));
}
@@ -2265,7 +2263,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignme
if (argv_expanded) {
argv = argv_expanded;
} else {
- argv = expand_strvec_to_strvec(argv);
+ argv = expand_strvec_to_strvec(argv + assignment_cnt);
#if !BB_MMU
nommu_save->argv = argv;
#endif
@@ -3628,7 +3626,6 @@ static int done_word(o_string *word, struct parse_context *ctx)
ctx->ctx_dsemicolon = 0;
} else
#endif
-
if (!command->argv /* if it's the first word... */
#if ENABLE_HUSH_LOOPS
&& ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
@@ -3767,8 +3764,7 @@ static FILE *generate_stream_from_list(struct pipe *head)
/* Return code is exit status of the process that is run. */
static int process_command_subs(o_string *dest,
- struct in_str *input,
- const char *subst_end)
+ struct in_str *input)
{
int retcode, ch, eol_cnt;
o_string result = NULL_O_STRING;
@@ -3777,7 +3773,7 @@ static int process_command_subs(o_string *dest,
struct in_str pipe_str;
/* Recursion to generate command */
- retcode = parse_stream(&result, &inner, input, subst_end);
+ retcode = parse_stream(&result, &inner, input, NULL);
if (retcode != 0)
return retcode; /* syntax error or EOF */
o_free(&result);
@@ -4236,9 +4232,11 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
* A single-quote triggers a bypass of the main loop until its mate is
* found. When recursing, quote state is passed in via dest->o_escape. */
- debug_printf_parse("parse_stream entered, end_trigger='%s' dest->o_assignment:%d\n", end_trigger, dest->o_assignment);
- initialize_context(ctx);
+ debug_printf_parse("parse_stream entered, end_trigger='%s' "
+ "dest->o_assignment:%d\n", end_trigger, dest->o_assignment);
+ dest->o_assignment = MAYBE_ASSIGNMENT;
+ initialize_context(ctx);
is_in_dquote = dest->o_escape;
while (1) {
if (is_in_dquote) {
@@ -4269,51 +4267,47 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
}
continue;
}
- /* m is SPECIAL ($,`), IFS, or ORDINARY_IF_QUOTED (*,#)
- */
+ /* m is SPECIAL ($,`), IFS, or ORDINARY_IF_QUOTED (*,#) */
if (m == CHAR_IFS) {
+ if (ch == EOF)
+ goto ret_EOF;
if (done_word(dest, ctx)) {
debug_printf_parse("parse_stream return 1: done_word!=0\n");
return 1;
}
- if (ch == EOF)
- goto ret_EOF;
- /* If we aren't performing a substitution, treat
- * a newline as a command separator.
- * [why don't we handle it exactly like ';'? --vda] */
- if (end_trigger && ch == '\n') {
+ if (ch == '\n') {
#if ENABLE_HUSH_CASE
/* "case ... in <newline> word) ..." -
* newlines are ignored (but ';' wouldn't be) */
- if (dest->length == 0 // && argv[0] == NULL
+ if (ctx->command->argv == NULL
&& ctx->ctx_res_w == RES_MATCH
) {
continue;
}
#endif
+ /* Treat newline as a command separator.
+ * [why don't we handle it exactly like ';'? --vda] */
done_pipe(ctx, PIPE_SEQ);
dest->o_assignment = MAYBE_ASSIGNMENT;
}
}
- if (end_trigger) {
- if (strchr(end_trigger, ch)) {
- /* Special case: (...word) makes last word terminate,
- * as if ';' is seen */
- if (ch == ')') {
- done_word(dest, ctx);
+ if (end_trigger && strchr(end_trigger, ch)) {
+ /* Special case: (...word) makes last word terminate,
+ * as if ';' is seen */
+ if (ch == ')') {
+ done_word(dest, ctx);
//err chk?
- done_pipe(ctx, PIPE_SEQ);
- dest->o_assignment = MAYBE_ASSIGNMENT;
- }
- /* What do we check here? */
- if (!HAS_KEYWORDS
- IF_HAS_KEYWORDS(|| (ctx->ctx_res_w == RES_NONE && ctx->old_flag == 0))
- ) {
- debug_printf_parse("parse_stream return 0: end_trigger char found\n");
- /* this makes us return 0, not -1 */
- end_trigger = NULL;
- goto ret;
- }
+ done_pipe(ctx, PIPE_SEQ);
+ dest->o_assignment = MAYBE_ASSIGNMENT;
+ }
+ /* What do we check here? */
+ if (!HAS_KEYWORDS
+ IF_HAS_KEYWORDS(|| (ctx->ctx_res_w == RES_NONE && ctx->old_flag == 0))
+ ) {
+ debug_printf_parse("parse_stream return 0: end_trigger char found\n");
+ /* this makes us return 0, not -1 */
+ end_trigger = NULL;
+ goto ret;
}
}
if (m == CHAR_IFS)
diff --git a/shell/hush_test/hush-vars/var_in_pipes.right b/shell/hush_test/hush-vars/var_in_pipes.right
new file mode 100644
index 0000000..faf65be
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_in_pipes.right
@@ -0,0 +1,6 @@
+b=1
+b=2
+b=3
+b=4
+b=5
+b=6
diff --git a/shell/hush_test/hush-vars/var_in_pipes.tests b/shell/hush_test/hush-vars/var_in_pipes.tests
new file mode 100755
index 0000000..3f8cd27
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_in_pipes.tests
@@ -0,0 +1,7 @@
+b=1 env | grep ^b=
+true | b=2 env | grep ^b=
+a=1 true | b=3 env | grep ^b=
+
+(b=4 env) | grep ^b=
+(true | b=5 env) | grep ^b=
+(a=1 true | b=6 env) | grep ^b=