aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c43
-rw-r--r--shell/hush_test/hush-misc/empty_args.right6
-rwxr-xr-xshell/hush_test/hush-misc/empty_args.tests9
-rw-r--r--shell/hush_test/hush-psubst/emptytick.right7
-rwxr-xr-xshell/hush_test/hush-psubst/emptytick.tests8
5 files changed, 58 insertions, 15 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 1d2826d9a..46bb7e9a2 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2185,7 +2185,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2185 2185
2186 ored_ch = 0; 2186 ored_ch = 0;
2187 2187
2188 debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg); 2188 debug_printf_expand("expand_vars_to_list: arg:'%s' or_mask:%x\n", arg, or_mask);
2189 debug_print_list("expand_vars_to_list", output, n); 2189 debug_print_list("expand_vars_to_list", output, n);
2190 n = o_save_ptr(output, n); 2190 n = o_save_ptr(output, n);
2191 debug_print_list("expand_vars_to_list[0]", output, n); 2191 debug_print_list("expand_vars_to_list[0]", output, n);
@@ -3425,7 +3425,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
3425 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 3425 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
3426 execvp(argv[0], argv); 3426 execvp(argv[0], argv);
3427 bb_perror_msg("can't execute '%s'", argv[0]); 3427 bb_perror_msg("can't execute '%s'", argv[0]);
3428 _exit(EXIT_FAILURE); 3428 _exit(127); /* bash compat */
3429} 3429}
3430 3430
3431/* Called after [v]fork() in run_pipe 3431/* Called after [v]fork() in run_pipe
@@ -3895,7 +3895,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
3895 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt); 3895 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
3896 } 3896 }
3897 3897
3898 /* if someone gives us an empty string: ``, $(), ... */ 3898 /* if someone gives us an empty string: `cmd with empty output` */
3899 if (!argv_expanded[0]) { 3899 if (!argv_expanded[0]) {
3900 debug_leave(); 3900 debug_leave();
3901 return 0; 3901 return 0;
@@ -5802,7 +5802,7 @@ static int parse_stream_dquoted(o_string *as_string,
5802 if (ch != '\n') { 5802 if (ch != '\n') {
5803 next = i_peek(input); 5803 next = i_peek(input);
5804 } 5804 }
5805 debug_printf_parse(": ch=%c (%d) escape=%d\n", 5805 debug_printf_parse("\" ch=%c (%d) escape=%d\n",
5806 ch, ch, dest->o_escape); 5806 ch, ch, dest->o_escape);
5807 if (ch == '\\') { 5807 if (ch == '\\') {
5808 if (next == EOF) { 5808 if (next == EOF) {
@@ -5882,6 +5882,11 @@ static struct pipe *parse_stream(char **pstring,
5882 end_trigger ? end_trigger : 'X'); 5882 end_trigger ? end_trigger : 'X');
5883 debug_enter(); 5883 debug_enter();
5884 5884
5885 /* If very first arg is "" or '', dest.data may end up NULL.
5886 * Preventing this: */
5887 o_addchr(&dest, '\0');
5888 dest.length = 0;
5889
5885 G.ifs = get_local_var_value("IFS"); 5890 G.ifs = get_local_var_value("IFS");
5886 if (G.ifs == NULL) 5891 if (G.ifs == NULL)
5887 G.ifs = " \t\n"; 5892 G.ifs = " \t\n";
@@ -6979,16 +6984,32 @@ static int FAST_FUNC builtin_cd(char **argv)
6979 6984
6980static int FAST_FUNC builtin_exec(char **argv) 6985static int FAST_FUNC builtin_exec(char **argv)
6981{ 6986{
6982 if (*++argv == NULL) 6987 static const char pseudo_null_str[] = { SPECIAL_VAR_SYMBOL, SPECIAL_VAR_SYMBOL, '\0' };
6983 return EXIT_SUCCESS; /* bash does this */ 6988 char **pp = argv;
6984 {
6985#if !BB_MMU 6989#if !BB_MMU
6986 nommu_save_t dummy; 6990 nommu_save_t dummy;
6987#endif 6991#endif
6988 /* TODO: if exec fails, bash does NOT exit! We do... */ 6992
6989 pseudo_exec_argv(&dummy, argv, 0, NULL); 6993 if (*++argv == NULL)
6990 /* never returns */ 6994 return EXIT_SUCCESS; /* bash does this */
6995
6996 /* Make sure empty arguments aren't ignored */
6997 /* Example: exec ls '' */
6998 pp = argv;
6999 while (*pp) {
7000 if ((*pp)[0] == '\0')
7001 *pp = (char*)pseudo_null_str;
7002 pp++;
6991 } 7003 }
7004
7005 /* Careful: we can end up here after [v]fork. Do not restore
7006 * tty pgrp then, only top-level shell process does that */
7007 if (G_saved_tty_pgrp && getpid() == G.root_pid)
7008 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
7009
7010 /* TODO: if exec fails, bash does NOT exit! We do... */
7011 pseudo_exec_argv(&dummy, argv, 0, NULL);
7012 /* never returns */
6992} 7013}
6993 7014
6994static int FAST_FUNC builtin_exit(char **argv) 7015static int FAST_FUNC builtin_exit(char **argv)
diff --git a/shell/hush_test/hush-misc/empty_args.right b/shell/hush_test/hush-misc/empty_args.right
new file mode 100644
index 000000000..38ed8b8be
--- /dev/null
+++ b/shell/hush_test/hush-misc/empty_args.right
@@ -0,0 +1,6 @@
1Null 0th arg:
2hush: can't execute '': No such file or directory
3127
4Null 1st arg:
50
6Null arg in exec:
diff --git a/shell/hush_test/hush-misc/empty_args.tests b/shell/hush_test/hush-misc/empty_args.tests
new file mode 100755
index 000000000..efce5494a
--- /dev/null
+++ b/shell/hush_test/hush-misc/empty_args.tests
@@ -0,0 +1,9 @@
1echo Null 0th arg:
2""
3echo $?
4echo Null 1st arg:
5# printf without args would print usage info
6printf ""
7echo $?
8echo Null arg in exec:
9exec printf ""
diff --git a/shell/hush_test/hush-psubst/emptytick.right b/shell/hush_test/hush-psubst/emptytick.right
index d4b70c58a..1f60ecfda 100644
--- a/shell/hush_test/hush-psubst/emptytick.right
+++ b/shell/hush_test/hush-psubst/emptytick.right
@@ -1,14 +1,17 @@
10 10
20 20
3hush: can't execute '': No such file or directory
30 40
5hush: can't execute '': No such file or directory
40 60
50 70
60 80
70 90
80 100
11hush: can't execute '': No such file or directory
90 120
13hush: can't execute '': No such file or directory
100 140
110 150
120 160
130 17hush: can't execute '': No such file or directory
140
diff --git a/shell/hush_test/hush-psubst/emptytick.tests b/shell/hush_test/hush-psubst/emptytick.tests
index af3a1836c..a269f025a 100755
--- a/shell/hush_test/hush-psubst/emptytick.tests
+++ b/shell/hush_test/hush-psubst/emptytick.tests
@@ -1,16 +1,20 @@
1true; ``; echo $? 1true; ``; echo $?
2false; ``; echo $? 2false; ``; echo $?
3# UNFIXED BUG. bash sets $? to 127:
3true; `""`; echo $? 4true; `""`; echo $?
5# bash sets $? to 127:
4false; `""`; echo $? 6false; `""`; echo $?
5true; ` `; echo $? 7true; ` `; echo $?
6false; ` `; echo $? 8false; ` `; echo $?
7 9
8true; $(); echo $? 10true; $(); echo $?
9false; $(); echo $? 11false; $(); echo $?
12# bash sets $? to 127:
10true; $(""); echo $? 13true; $(""); echo $?
14# bash sets $? to 127:
11false; $(""); echo $? 15false; $(""); echo $?
12true; $( ); echo $? 16true; $( ); echo $?
13false; $( ); echo $? 17false; $( ); echo $?
14 18
15true; exec ''; echo $? 19exec ''; echo $?
16false; exec ''; echo $? 20echo Not reached