diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2015-09-04 06:22:10 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-09-04 06:22:10 +0200 |
commit | b5be13ccd9ce2120468a381a5475955013c0f049 (patch) | |
tree | cf2b99e5a1fc91944dade4c72694f7704502d438 /shell/hush.c | |
parent | 2156e228537065f04e5f862e186421df0db36612 (diff) |
hush: fix a nommu bug where a part of function body is lost if run in a pipe
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/shell/hush.c b/shell/hush.c index 3ca04494c..752080a64 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3161,11 +3161,29 @@ static int reserved_word(o_string *word, struct parse_context *ctx) old->command->group = ctx->list_head; old->command->cmd_type = CMD_NORMAL; # if !BB_MMU - o_addstr(&old->as_string, ctx->as_string.data); - o_free_unsafe(&ctx->as_string); - old->command->group_as_string = xstrdup(old->as_string.data); - debug_printf_parse("pop, remembering as:'%s'\n", - old->command->group_as_string); + /* At this point, the compound command's string is in + * ctx->as_string... except for the leading keyword! + * Consider this example: "echo a | if true; then echo a; fi" + * ctx->as_string will contain "true; then echo a; fi", + * with "if " remaining in old->as_string! + */ + { + char *str; + int len = old->as_string.length; + /* Concatenate halves */ + o_addstr(&old->as_string, ctx->as_string.data); + o_free_unsafe(&ctx->as_string); + /* Find where leading keyword starts in first half */ + str = old->as_string.data + len; + if (str > old->as_string.data) + str--; /* skip whitespace after keyword */ + while (str > old->as_string.data && isalpha(str[-1])) + str--; + /* Ugh, we're done with this horrid hack */ + old->command->group_as_string = xstrdup(str); + debug_printf_parse("pop, remembering as:'%s'\n", + old->command->group_as_string); + } # endif *ctx = *old; /* physical copy */ free(old); @@ -4248,7 +4266,7 @@ static struct pipe *parse_stream(char **pstring, pi = NULL; } #if !BB_MMU - debug_printf_parse("as_string '%s'\n", ctx.as_string.data); + debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data); if (pstring) *pstring = ctx.as_string.data; else @@ -4399,7 +4417,7 @@ static struct pipe *parse_stream(char **pstring, ) { o_free(&dest); #if !BB_MMU - debug_printf_parse("as_string '%s'\n", ctx.as_string.data); + debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data); if (pstring) *pstring = ctx.as_string.data; else @@ -4639,9 +4657,6 @@ static struct pipe *parse_stream(char **pstring, * with redirect_opt_num(), but bash doesn't do it. * "echo foo 2| cat" yields "foo 2". */ done_command(&ctx); -#if !BB_MMU - o_reset_to_empty_unquoted(&ctx.as_string); -#endif } goto new_cmd; case '(': |