diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-18 16:29:32 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-18 16:29:32 +0000 |
commit | ab876cd107fe6ca274f58bae3264396745d8e5f9 (patch) | |
tree | c94ecba9c7d10af007294333e9b4c80efe079cfb /shell/hush.c | |
parent | 985de15bf3f39b5e32e34cadaf6947708197f018 (diff) |
hush: add testsuite for "no globbing in redirection" rule.
simplify redirection habdling
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 69 |
1 files changed, 24 insertions, 45 deletions
diff --git a/shell/hush.c b/shell/hush.c index cb289769e..f81203e2b 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -287,7 +287,7 @@ struct redir_struct { redir_type type; /* type of redirection */ int fd; /* file descriptor being redirected */ int dup; /* -1, or file descriptor being duplicated */ - char **glob_word; /* *word.gl_pathv is the filename */ + char *rd_filename; /* filename */ }; struct child_prog { @@ -1304,14 +1304,14 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]) struct redir_struct *redir; for (redir = prog->redirects; redir; redir = redir->next) { - if (redir->dup == -1 && redir->glob_word == NULL) { + if (redir->dup == -1 && redir->rd_filename == NULL) { /* something went wrong in the parse. Pretend it didn't happen */ continue; } if (redir->dup == -1) { char *p; mode = redir_table[redir->type].mode; - p = expand_string_to_string(redir->glob_word[0]); + p = expand_string_to_string(redir->rd_filename); openfd = open_or_warn(p, mode); free(p); if (openfd < 0) { @@ -2227,10 +2227,10 @@ static int free_pipe(struct pipe *pi, int indent) debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip); if (r->dup == -1) { /* guard against the case >$FOO, where foo is unset or blank */ - if (r->glob_word) { - debug_printf_clean(" %s\n", r->glob_word[0]); - free_strings(r->glob_word); - r->glob_word = NULL; + if (r->rd_filename) { + debug_printf_clean(" %s\n", r->rd_filename); + free(r->rd_filename); + r->rd_filename = NULL; } } else { debug_printf_clean("&%d\n", r->dup); @@ -2680,7 +2680,7 @@ static int setup_redirect(struct p_context *ctx, int fd, redir_type style, } redir = xzalloc(sizeof(struct redir_struct)); /* redir->next = NULL; */ - /* redir->glob_word = NULL; */ + /* redir->rd_filename = NULL; */ if (last_redir) { last_redir->next = redir; } else { @@ -2857,17 +2857,17 @@ static int reserved_word(const o_string *word, struct p_context *ctx) static int done_word(o_string *word, struct p_context *ctx) { struct child_prog *child = ctx->child; - char ***glob_target; debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); - if (word->length == 0) { - if (!word->nonnull) { - debug_printf_parse("done_word return 0: true null, ignored\n"); - return 0; - } + if (word->length == 0 && word->nonnull == 0) { + debug_printf_parse("done_word return 0: true null, ignored\n"); + return 0; } if (ctx->pending_redirect) { - glob_target = &ctx->pending_redirect->glob_word; + /* We do not glob in e.g. >*.tmp case. bash seems to glob here + * only if run as "bash", not "sh" */ + ctx->pending_redirect->rd_filename = xstrdup(word->data); + debug_printf("word stored in rd_filename: '%s'\n", word->data); } else { if (child->group) { /* TODO: example how to trigger? */ syntax(NULL); @@ -2882,46 +2882,25 @@ static int done_word(o_string *word, struct p_context *ctx) return (ctx->res_w == RES_SNTX); } } - if (word->nonnull) { + if (word->nonnull + /* && word->data[0] != */ + ) { /* Insert "empty variable" reference, this makes e.g. "", '', * $empty"" etc to not disappear */ o_addchr(word, SPECIAL_VAR_SYMBOL); o_addchr(word, SPECIAL_VAR_SYMBOL); } - glob_target = &child->argv; - } - -//FIXME: we had globbing here, but now it's moved! Do we glob in e.g. ">*.tmp" now!? - - /*if (word->length || word->nonnull) - true */ { - *glob_target = add_malloced_string_to_strings(*glob_target, xstrdup(word->data)); - debug_print_strings("glob_target appended", *glob_target); + child->argv = add_malloced_string_to_strings(child->argv, xstrdup(word->data)); + debug_print_strings("word appended to argv", child->argv); } o_reset(word); - if (ctx->pending_redirect) { - /* NB: don't free_strings(ctx->pending_redirect->glob_word) here */ - if (ctx->pending_redirect->glob_word - && ctx->pending_redirect->glob_word[0] - && ctx->pending_redirect->glob_word[1] - ) { - /* more than one word resulted from globbing redir */ - ctx->pending_redirect = NULL; - bb_error_msg("ambiguous redirect"); - debug_printf_parse("done_word return 1: ambiguous redirect\n"); - return 1; - } - ctx->pending_redirect = NULL; - } + ctx->pending_redirect = NULL; + #if ENABLE_HUSH_LOOPS - /* comment? is it forcing "for" to have just one word (variable name)? */ - if (ctx->res_w == RES_FOR) { -//TESTING -//looks like (word->length == 0 && !word->nonnull) is true here, always -//(due to o_reset). done_word would return at once. Why then? -// done_word(word, ctx); + /* Force FOR to have just one word (variable name) */ + if (ctx->res_w == RES_FOR) done_pipe(ctx, PIPE_SEQ); - } #endif debug_printf_parse("done_word return 0\n"); return 0; |