diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-14 12:03:24 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-14 12:03:24 +0200 |
| commit | cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8 (patch) | |
| tree | 07a542ea9ee47b56f69122ed66dea7ed8e6c1925 /shell | |
| parent | 4343ca9aa879cabc52ff82c0a46d3ba20d7fec5c (diff) | |
| download | busybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.tar.gz busybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.tar.bz2 busybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.zip | |
hush: explain "empty quoted str marker" trick
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c index d65da3b98..002140b1a 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -5656,15 +5656,20 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5656 | nommu_addchr(&ctx.as_string, ch); | 5656 | nommu_addchr(&ctx.as_string, ch); |
| 5657 | if (ch == '\'') { | 5657 | if (ch == '\'') { |
| 5658 | ctx.word.has_quoted_part = 1; | 5658 | ctx.word.has_quoted_part = 1; |
| 5659 | next = i_getch(input); | 5659 | ch = i_getch(input); |
| 5660 | if (next == '\'' && !ctx.pending_redirect/*why?*/) { | 5660 | if (ch == '\'' && !ctx.pending_redirect/*why?*/) { |
| 5661 | insert_empty_quoted_str_marker: | 5661 | insert_empty_quoted_str_marker: |
| 5662 | nommu_addchr(&ctx.as_string, next); | 5662 | nommu_addchr(&ctx.as_string, ch); |
| 5663 | //Just inserting nothing doesn't work: consider | ||
| 5664 | // CMD $EMPTYVAR | ||
| 5665 | // CMD '' | ||
| 5666 | //At execution time both will expand argv[1] to empty string | ||
| 5667 | //and thus the argument will "vanish". | ||
| 5668 | //But for second CMD, it should not vanish! | ||
| 5663 | o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); | 5669 | o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); |
| 5664 | o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); | 5670 | o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); |
| 5665 | continue; /* get next char */ | 5671 | continue; /* get next char */ |
| 5666 | } | 5672 | } |
| 5667 | ch = next; | ||
| 5668 | while (1) { | 5673 | while (1) { |
| 5669 | if (ch == EOF) { | 5674 | if (ch == EOF) { |
| 5670 | syntax_error_unterm_ch('\''); | 5675 | syntax_error_unterm_ch('\''); |
| @@ -5789,6 +5794,7 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5789 | if ((ctx.is_assignment == MAYBE_ASSIGNMENT | 5794 | if ((ctx.is_assignment == MAYBE_ASSIGNMENT |
| 5790 | || ctx.is_assignment == WORD_IS_KEYWORD) | 5795 | || ctx.is_assignment == WORD_IS_KEYWORD) |
| 5791 | && ch == '=' | 5796 | && ch == '=' |
| 5797 | // && !ctx.word.has_quoted_part // unnecessary, "empty quoted str marker" trick handles this too | ||
| 5792 | && endofname(ctx.word.data)[0] == '=' | 5798 | && endofname(ctx.word.data)[0] == '=' |
| 5793 | ) { | 5799 | ) { |
| 5794 | ctx.is_assignment = DEFINITELY_ASSIGNMENT; | 5800 | ctx.is_assignment = DEFINITELY_ASSIGNMENT; |
| @@ -5983,7 +5989,7 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5983 | case '"': | 5989 | case '"': |
| 5984 | ctx.word.has_quoted_part = 1; | 5990 | ctx.word.has_quoted_part = 1; |
| 5985 | if (next == '"' && !ctx.pending_redirect) { | 5991 | if (next == '"' && !ctx.pending_redirect) { |
| 5986 | i_getch(input); /* eat second " */ | 5992 | ch = i_getch(input); /* eat second " */ |
| 5987 | goto insert_empty_quoted_str_marker; | 5993 | goto insert_empty_quoted_str_marker; |
| 5988 | } | 5994 | } |
| 5989 | if (ctx.is_assignment == NOT_ASSIGNMENT) | 5995 | if (ctx.is_assignment == NOT_ASSIGNMENT) |
