From 3dfb035d8df33e59492e78a97bf42e961ba178e4 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Wed, 8 Apr 2009 09:29:14 +0000 Subject: hush: echo \2>file fix --- shell/hush.c | 29 +++++++++++++++++++++-------- shell/hush_test/hush-misc/heredoc2.right | 1 + shell/hush_test/hush-misc/heredoc2.tests | 1 + shell/hush_test/hush-misc/heredoc3.right | 1 + shell/hush_test/hush-misc/heredoc3.tests | 1 + shell/hush_test/hush-misc/redir2.right | 1 + shell/hush_test/hush-misc/redir2.tests | 2 ++ 7 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 shell/hush_test/hush-misc/redir2.right create mode 100755 shell/hush_test/hush-misc/redir2.tests diff --git a/shell/hush.c b/shell/hush.c index d5c90a262..5594aaea4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4081,7 +4081,7 @@ static int parse_redirect(struct parse_context *ctx, * the redirection expression. For example: * echo \2>a * writes the character 2 into file a" - * I am not sure we do it right (and not sure we care) + * We are getting it right by setting ->o_quoted on any \ * * A -1 return means no valid number was found, * the caller should use the appropriate default for this redirection. @@ -4141,6 +4141,9 @@ static char *fetch_till_str(o_string *as_string, } } +/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs + * and load them all. There should be exactly heredoc_cnt of them. + */ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input) { struct pipe *pi = ctx->list_head; @@ -4161,14 +4164,18 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ if (redir->rd_type == REDIRECT_HEREDOC) { char *p; - if (heredoc_cnt <= 0) + if (heredoc_cnt <= 0) { + syntax("heredoc BUG 1"); return 1; /* error */ + } redir->rd_type = REDIRECT_HEREDOC2; /* redir->dup is (ab)used to indicate <<- */ p = fetch_till_str(&ctx->as_string, input, redir->rd_filename, redir->rd_dup & HEREDOC_SKIPTABS); - if (!p) - return 1; /* unexpected EOF */ + if (!p) { + syntax("unexpected EOF in here document"); + return 1; + } free(redir->rd_filename); redir->rd_filename = p; heredoc_cnt--; @@ -4180,6 +4187,8 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ pi = pi->next; } /* Should be 0. If it isn't, it's a parse error */ + if (heredoc_cnt) + syntax("heredoc BUG 2"); return heredoc_cnt; } @@ -4673,12 +4682,12 @@ static int parse_stream_dquoted(o_string *as_string, if (ch != EOF) nommu_addchr(as_string, ch); if (ch == dquote_end) { /* may be only '"' or EOF */ - dest->o_quoted = 1; if (dest->o_assignment == NOT_ASSIGNMENT) dest->o_escape ^= 1; debug_printf_parse("parse_stream_dquoted return 0\n"); return 0; } + /* note: can't move it above ch == dquote_end check! */ if (ch == EOF) { syntax("unterminated \""); debug_printf_parse("parse_stream_dquoted return 1: unterminated \"\n"); @@ -4787,6 +4796,7 @@ static struct pipe *parse_stream(char **pstring, redir_type redir_style; if (is_in_dquote) { + /* dest.o_quoted = 1; - already is (see below) */ if (parse_stream_dquoted(&ctx.as_string, &dest, input, '"')) { goto parse_error; } @@ -4863,8 +4873,9 @@ static struct pipe *parse_stream(char **pstring, done_pipe(&ctx, PIPE_SEQ); debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); if (heredoc_cnt) { - if (fetch_heredocs(heredoc_cnt, &ctx, input)) + if (fetch_heredocs(heredoc_cnt, &ctx, input)) { goto parse_error; + } heredoc_cnt = 0; } dest.o_assignment = MAYBE_ASSIGNMENT; @@ -4938,7 +4949,6 @@ static struct pipe *parse_stream(char **pstring, i_getch(input); /* note: we do not add it to &ctx.as_string */ } -//TODO: go back one char? nommu_addchr(&ctx.as_string, '\n'); } else { o_addQchr(&dest, ch); @@ -4951,8 +4961,11 @@ static struct pipe *parse_stream(char **pstring, } o_addchr(&dest, '\\'); ch = i_getch(input); - o_addchr(&dest, ch); nommu_addchr(&ctx.as_string, ch); + o_addchr(&dest, ch); + /* Example: echo Hello \2>file + * we need to know that word 2 is quoted */ + dest.o_quoted = 1; break; case '$': if (handle_dollar(&ctx.as_string, &dest, input) != 0) { diff --git a/shell/hush_test/hush-misc/heredoc2.right b/shell/hush_test/hush-misc/heredoc2.right index 66545ae76..74110e3b5 100644 --- a/shell/hush_test/hush-misc/heredoc2.right +++ b/shell/hush_test/hush-misc/heredoc2.right @@ -6,3 +6,4 @@ moo EOF-f EOF-f f EOF-f +Ok diff --git a/shell/hush_test/hush-misc/heredoc2.tests b/shell/hush_test/hush-misc/heredoc2.tests index 19d9c9681..e619bded1 100755 --- a/shell/hush_test/hush-misc/heredoc2.tests +++ b/shell/hush_test/hush-misc/heredoc2.tests @@ -9,3 +9,4 @@ echo `echo Hello World` EOF-f f EOF-f EOF-f +echo Ok diff --git a/shell/hush_test/hush-misc/heredoc3.right b/shell/hush_test/hush-misc/heredoc3.right index 9b114fabf..6ed517f74 100644 --- a/shell/hush_test/hush-misc/heredoc3.right +++ b/shell/hush_test/hush-misc/heredoc3.right @@ -6,3 +6,4 @@ moo EOF-f EOF-f f EOF-f +Ok diff --git a/shell/hush_test/hush-misc/heredoc3.tests b/shell/hush_test/hush-misc/heredoc3.tests index 6391e49f9..938577a89 100755 --- a/shell/hush_test/hush-misc/heredoc3.tests +++ b/shell/hush_test/hush-misc/heredoc3.tests @@ -9,3 +9,4 @@ echo `echo Hello World` EOF-f f EOF-f EOF-f +echo Ok diff --git a/shell/hush_test/hush-misc/redir2.right b/shell/hush_test/hush-misc/redir2.right new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/shell/hush_test/hush-misc/redir2.right @@ -0,0 +1 @@ +Ok diff --git a/shell/hush_test/hush-misc/redir2.tests b/shell/hush_test/hush-misc/redir2.tests new file mode 100755 index 000000000..81983cae2 --- /dev/null +++ b/shell/hush_test/hush-misc/redir2.tests @@ -0,0 +1,2 @@ +echo NOT SHOWN \2>/dev/null +echo Ok -- cgit v1.2.3