From b5be13ccd9ce2120468a381a5475955013c0f049 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Sep 2015 06:22:10 +0200 Subject: [PATCH] hush: fix a nommu bug where a part of function body is lost if run in a pipe Signed-off-by: Denys Vlasenko --- shell/hush.c | 35 ++++++++++++++++++-------- shell/hush_test/hush-misc/nommu3.right | 2 ++ shell/hush_test/hush-misc/nommu3.tests | 15 +++++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 shell/hush_test/hush-misc/nommu3.right create mode 100755 shell/hush_test/hush-misc/nommu3.tests 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 '(': diff --git a/shell/hush_test/hush-misc/nommu3.right b/shell/hush_test/hush-misc/nommu3.right new file mode 100644 index 000000000..da1534bef --- /dev/null +++ b/shell/hush_test/hush-misc/nommu3.right @@ -0,0 +1,2 @@ +Ok +0 diff --git a/shell/hush_test/hush-misc/nommu3.tests b/shell/hush_test/hush-misc/nommu3.tests new file mode 100755 index 000000000..0aca67a67 --- /dev/null +++ b/shell/hush_test/hush-misc/nommu3.tests @@ -0,0 +1,15 @@ +#!/bin/sh + +func() +{ + while read p; do echo "$p"; done +} + +pipe_to_func() +{ + # We had a NOMMU bug which caused "echo Ok |" part ot be lost + echo Ok | func +} + +pipe_to_func | cat +echo $?