aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-18 16:29:32 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-18 16:29:32 +0000
commitab876cd107fe6ca274f58bae3264396745d8e5f9 (patch)
treec94ecba9c7d10af007294333e9b4c80efe079cfb
parent985de15bf3f39b5e32e34cadaf6947708197f018 (diff)
downloadbusybox-w32-ab876cd107fe6ca274f58bae3264396745d8e5f9.tar.gz
busybox-w32-ab876cd107fe6ca274f58bae3264396745d8e5f9.tar.bz2
busybox-w32-ab876cd107fe6ca274f58bae3264396745d8e5f9.zip
hush: add testsuite for "no globbing in redirection" rule.
simplify redirection habdling
-rw-r--r--shell/hush.c69
-rw-r--r--shell/hush_test/hush-glob/glob_redir.right2
-rwxr-xr-xshell/hush_test/hush-glob/glob_redir.tests9
-rw-r--r--shell/hush_test/hush-parsing/escape3.right23
-rwxr-xr-xshell/hush_test/hush-parsing/escape3.tests8
-rw-r--r--shell/hush_test/hush-parsing/redir_space.right3
-rwxr-xr-xshell/hush_test/hush-parsing/redir_space.tests6
7 files changed, 75 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 {
287 redir_type type; /* type of redirection */ 287 redir_type type; /* type of redirection */
288 int fd; /* file descriptor being redirected */ 288 int fd; /* file descriptor being redirected */
289 int dup; /* -1, or file descriptor being duplicated */ 289 int dup; /* -1, or file descriptor being duplicated */
290 char **glob_word; /* *word.gl_pathv is the filename */ 290 char *rd_filename; /* filename */
291}; 291};
292 292
293struct child_prog { 293struct child_prog {
@@ -1304,14 +1304,14 @@ static int setup_redirects(struct child_prog *prog, int squirrel[])
1304 struct redir_struct *redir; 1304 struct redir_struct *redir;
1305 1305
1306 for (redir = prog->redirects; redir; redir = redir->next) { 1306 for (redir = prog->redirects; redir; redir = redir->next) {
1307 if (redir->dup == -1 && redir->glob_word == NULL) { 1307 if (redir->dup == -1 && redir->rd_filename == NULL) {
1308 /* something went wrong in the parse. Pretend it didn't happen */ 1308 /* something went wrong in the parse. Pretend it didn't happen */
1309 continue; 1309 continue;
1310 } 1310 }
1311 if (redir->dup == -1) { 1311 if (redir->dup == -1) {
1312 char *p; 1312 char *p;
1313 mode = redir_table[redir->type].mode; 1313 mode = redir_table[redir->type].mode;
1314 p = expand_string_to_string(redir->glob_word[0]); 1314 p = expand_string_to_string(redir->rd_filename);
1315 openfd = open_or_warn(p, mode); 1315 openfd = open_or_warn(p, mode);
1316 free(p); 1316 free(p);
1317 if (openfd < 0) { 1317 if (openfd < 0) {
@@ -2227,10 +2227,10 @@ static int free_pipe(struct pipe *pi, int indent)
2227 debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip); 2227 debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip);
2228 if (r->dup == -1) { 2228 if (r->dup == -1) {
2229 /* guard against the case >$FOO, where foo is unset or blank */ 2229 /* guard against the case >$FOO, where foo is unset or blank */
2230 if (r->glob_word) { 2230 if (r->rd_filename) {
2231 debug_printf_clean(" %s\n", r->glob_word[0]); 2231 debug_printf_clean(" %s\n", r->rd_filename);
2232 free_strings(r->glob_word); 2232 free(r->rd_filename);
2233 r->glob_word = NULL; 2233 r->rd_filename = NULL;
2234 } 2234 }
2235 } else { 2235 } else {
2236 debug_printf_clean("&%d\n", r->dup); 2236 debug_printf_clean("&%d\n", r->dup);
@@ -2680,7 +2680,7 @@ static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
2680 } 2680 }
2681 redir = xzalloc(sizeof(struct redir_struct)); 2681 redir = xzalloc(sizeof(struct redir_struct));
2682 /* redir->next = NULL; */ 2682 /* redir->next = NULL; */
2683 /* redir->glob_word = NULL; */ 2683 /* redir->rd_filename = NULL; */
2684 if (last_redir) { 2684 if (last_redir) {
2685 last_redir->next = redir; 2685 last_redir->next = redir;
2686 } else { 2686 } else {
@@ -2857,17 +2857,17 @@ static int reserved_word(const o_string *word, struct p_context *ctx)
2857static int done_word(o_string *word, struct p_context *ctx) 2857static int done_word(o_string *word, struct p_context *ctx)
2858{ 2858{
2859 struct child_prog *child = ctx->child; 2859 struct child_prog *child = ctx->child;
2860 char ***glob_target;
2861 2860
2862 debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); 2861 debug_printf_parse("done_word entered: '%s' %p\n", word->data, child);
2863 if (word->length == 0) { 2862 if (word->length == 0 && word->nonnull == 0) {
2864 if (!word->nonnull) { 2863 debug_printf_parse("done_word return 0: true null, ignored\n");
2865 debug_printf_parse("done_word return 0: true null, ignored\n"); 2864 return 0;
2866 return 0;
2867 }
2868 } 2865 }
2869 if (ctx->pending_redirect) { 2866 if (ctx->pending_redirect) {
2870 glob_target = &ctx->pending_redirect->glob_word; 2867 /* We do not glob in e.g. >*.tmp case. bash seems to glob here
2868 * only if run as "bash", not "sh" */
2869 ctx->pending_redirect->rd_filename = xstrdup(word->data);
2870 debug_printf("word stored in rd_filename: '%s'\n", word->data);
2871 } else { 2871 } else {
2872 if (child->group) { /* TODO: example how to trigger? */ 2872 if (child->group) { /* TODO: example how to trigger? */
2873 syntax(NULL); 2873 syntax(NULL);
@@ -2882,46 +2882,25 @@ static int done_word(o_string *word, struct p_context *ctx)
2882 return (ctx->res_w == RES_SNTX); 2882 return (ctx->res_w == RES_SNTX);
2883 } 2883 }
2884 } 2884 }
2885 if (word->nonnull) { 2885 if (word->nonnull
2886 /* && word->data[0] != */
2887 ) {
2886 /* Insert "empty variable" reference, this makes e.g. "", '', 2888 /* Insert "empty variable" reference, this makes e.g. "", '',
2887 * $empty"" etc to not disappear */ 2889 * $empty"" etc to not disappear */
2888 o_addchr(word, SPECIAL_VAR_SYMBOL); 2890 o_addchr(word, SPECIAL_VAR_SYMBOL);
2889 o_addchr(word, SPECIAL_VAR_SYMBOL); 2891 o_addchr(word, SPECIAL_VAR_SYMBOL);
2890 } 2892 }
2891 glob_target = &child->argv; 2893 child->argv = add_malloced_string_to_strings(child->argv, xstrdup(word->data));
2892 } 2894 debug_print_strings("word appended to argv", child->argv);
2893
2894//FIXME: we had globbing here, but now it's moved! Do we glob in e.g. ">*.tmp" now!?
2895
2896 /*if (word->length || word->nonnull) - true */ {
2897 *glob_target = add_malloced_string_to_strings(*glob_target, xstrdup(word->data));
2898 debug_print_strings("glob_target appended", *glob_target);
2899 } 2895 }
2900 2896
2901 o_reset(word); 2897 o_reset(word);
2902 if (ctx->pending_redirect) { 2898 ctx->pending_redirect = NULL;
2903 /* NB: don't free_strings(ctx->pending_redirect->glob_word) here */ 2899
2904 if (ctx->pending_redirect->glob_word
2905 && ctx->pending_redirect->glob_word[0]
2906 && ctx->pending_redirect->glob_word[1]
2907 ) {
2908 /* more than one word resulted from globbing redir */
2909 ctx->pending_redirect = NULL;
2910 bb_error_msg("ambiguous redirect");
2911 debug_printf_parse("done_word return 1: ambiguous redirect\n");
2912 return 1;
2913 }
2914 ctx->pending_redirect = NULL;
2915 }
2916#if ENABLE_HUSH_LOOPS 2900#if ENABLE_HUSH_LOOPS
2917 /* comment? is it forcing "for" to have just one word (variable name)? */ 2901 /* Force FOR to have just one word (variable name) */
2918 if (ctx->res_w == RES_FOR) { 2902 if (ctx->res_w == RES_FOR)
2919//TESTING
2920//looks like (word->length == 0 && !word->nonnull) is true here, always
2921//(due to o_reset). done_word would return at once. Why then?
2922// done_word(word, ctx);
2923 done_pipe(ctx, PIPE_SEQ); 2903 done_pipe(ctx, PIPE_SEQ);
2924 }
2925#endif 2904#endif
2926 debug_printf_parse("done_word return 0\n"); 2905 debug_printf_parse("done_word return 0\n");
2927 return 0; 2906 return 0;
diff --git a/shell/hush_test/hush-glob/glob_redir.right b/shell/hush_test/hush-glob/glob_redir.right
new file mode 100644
index 000000000..fbd0309b0
--- /dev/null
+++ b/shell/hush_test/hush-glob/glob_redir.right
@@ -0,0 +1,2 @@
1z.tmp:
2?.tmp: TEST
diff --git a/shell/hush_test/hush-glob/glob_redir.tests b/shell/hush_test/hush-glob/glob_redir.tests
new file mode 100755
index 000000000..621d12017
--- /dev/null
+++ b/shell/hush_test/hush-glob/glob_redir.tests
@@ -0,0 +1,9 @@
1# Redirections are not globbed.
2# bash:
3# if run as "sh", they are not globbed, but
4# if run as "bash", they are!
5>z.tmp
6echo TEST >?.tmp
7echo 'z.tmp:' `cat 'z.tmp'`
8echo '?.tmp:' `cat '?.tmp'`
9rm 'z.tmp' '?.tmp'
diff --git a/shell/hush_test/hush-parsing/escape3.right b/shell/hush_test/hush-parsing/escape3.right
new file mode 100644
index 000000000..da02a976a
--- /dev/null
+++ b/shell/hush_test/hush-parsing/escape3.right
@@ -0,0 +1,23 @@
1v: a \ b \\ c \\\ d \\\\ e
2v: a \ b \\ c \\\ d \\\\ e
3Unquoted:
4.a.
5.\.
6.b.
7.\\.
8.c.
9.\\\.
10.d.
11.\\\\.
12.e.
13Quoted:
14.a.
15.\.
16.b.
17.\\.
18.c.
19.\\\.
20.d.
21.\\\\.
22.e.
23done
diff --git a/shell/hush_test/hush-parsing/escape3.tests b/shell/hush_test/hush-parsing/escape3.tests
new file mode 100755
index 000000000..111ed40a2
--- /dev/null
+++ b/shell/hush_test/hush-parsing/escape3.tests
@@ -0,0 +1,8 @@
1v='a \ b \\ c \\\ d \\\\ e'
2echo v: $v
3echo v: "$v"
4echo Unquoted:
5for a in $v; do echo .$a.; done
6echo Quoted:
7for a in $v; do echo ".$a."; done
8echo done
diff --git a/shell/hush_test/hush-parsing/redir_space.right b/shell/hush_test/hush-parsing/redir_space.right
new file mode 100644
index 000000000..084295204
--- /dev/null
+++ b/shell/hush_test/hush-parsing/redir_space.right
@@ -0,0 +1,3 @@
1z1.tmp: 1
2z2.tmp: 1
3"z1.tmp z2.tmp": TEST 0
diff --git a/shell/hush_test/hush-parsing/redir_space.tests b/shell/hush_test/hush-parsing/redir_space.tests
new file mode 100755
index 000000000..c0b543098
--- /dev/null
+++ b/shell/hush_test/hush-parsing/redir_space.tests
@@ -0,0 +1,6 @@
1v='z1.tmp z2.tmp'
2echo TEST >$v
3echo 'z1.tmp:' `cat 'z1.tmp' 2>/dev/null; echo $?`
4echo 'z2.tmp:' `cat 'z2.tmp' 2>/dev/null; echo $?`
5echo '"z1.tmp z2.tmp":' `cat 'z1.tmp z2.tmp' 2>/dev/null; echo $?`
6rm z*.tmp