diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 15:48:57 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 15:48:57 +0000 |
commit | 9db164d6e39050d09f38288c6045cd2a2cbf6d63 (patch) | |
tree | ea5dc2d28d15da0de25c197ed7d059c3656af1a0 /shell | |
parent | 1118c95535ea51961437089fc3dece5ab4ea7e1b (diff) | |
parent | d84b175cb6948eb17f847313bf912174e2f934e1 (diff) | |
download | busybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.tar.gz busybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.tar.bz2 busybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.zip |
Merge commit 'd84b175cb6948eb17f847313bf912174e2f934e1' into merge
Conflicts:
include/platform.h
Diffstat (limited to 'shell')
-rw-r--r-- | shell/cttyhack.c | 81 | ||||
-rw-r--r-- | shell/hush.c | 117 | ||||
-rw-r--r-- | shell/hush_test/hush-parsing/starquoted2.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-parsing/starquoted2.tests | 6 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_expand_on_ifs.right | 9 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_expand_on_ifs.tests | 11 |
6 files changed, 159 insertions, 68 deletions
diff --git a/shell/cttyhack.c b/shell/cttyhack.c index d1ac2cd23..4261289b4 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c | |||
@@ -14,18 +14,22 @@ | |||
14 | //config: bool "cttyhack" | 14 | //config: bool "cttyhack" |
15 | //config: default y | 15 | //config: default y |
16 | //config: help | 16 | //config: help |
17 | //config: One common problem reported on the mailing list is "can't access tty; | 17 | //config: One common problem reported on the mailing list is the "can't |
18 | //config: job control turned off" error message which typically appears when | 18 | //config: access tty; job control turned off" error message, which typically |
19 | //config: one tries to use shell with stdin/stdout opened to /dev/console. | 19 | //config: appears when one tries to use a shell with stdin/stdout on |
20 | //config: /dev/console. | ||
20 | //config: This device is special - it cannot be a controlling tty. | 21 | //config: This device is special - it cannot be a controlling tty. |
21 | //config: | 22 | //config: |
22 | //config: Proper solution is to use correct device instead of /dev/console. | 23 | //config: The proper solution is to use the correct device instead of |
24 | //config: /dev/console. | ||
23 | //config: | 25 | //config: |
24 | //config: cttyhack provides "quick and dirty" solution to this problem. | 26 | //config: cttyhack provides a "quick and dirty" solution to this problem. |
25 | //config: It analyzes stdin with various ioctls, trying to determine whether | 27 | //config: It analyzes stdin with various ioctls, trying to determine whether |
26 | //config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). | 28 | //config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). |
27 | //config: If it detects one, it closes stdin/out/err and reopens that device. | 29 | //config: On Linux it also checks sysfs for a pointer to the active console. |
28 | //config: Then it executes given program. Opening the device will make | 30 | //config: If cttyhack is able to find the real console device, it closes |
31 | //config: stdin/out/err and reopens that device. | ||
32 | //config: Then it executes the given program. Opening the device will make | ||
29 | //config: that device a controlling tty. This may require cttyhack | 33 | //config: that device a controlling tty. This may require cttyhack |
30 | //config: to be a session leader. | 34 | //config: to be a session leader. |
31 | //config: | 35 | //config: |
@@ -115,33 +119,48 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) | |||
115 | close(fd); | 119 | close(fd); |
116 | } else { | 120 | } else { |
117 | /* We don't have ctty (or don't have "/dev/tty" node...) */ | 121 | /* We don't have ctty (or don't have "/dev/tty" node...) */ |
118 | if (0) {} | 122 | do { |
119 | #ifdef TIOCGSERIAL | ||
120 | else if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { | ||
121 | /* this is a serial console */ | ||
122 | sprintf(console + 8, "S%d", u.sr.line); | ||
123 | } | ||
124 | #endif | ||
125 | #ifdef __linux__ | 123 | #ifdef __linux__ |
126 | else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { | 124 | int s = open_read_close("/sys/class/tty/console/active", |
127 | /* this is linux virtual tty */ | 125 | console + 5, sizeof(console) - 5 - 1); |
128 | sprintf(console + 8, "S%d" + 1, u.vt.v_active); | 126 | if (s > 0) { |
129 | } | 127 | /* found active console via sysfs (Linux 2.6.38+) */ |
128 | console[5 + s] = '\0'; | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { | ||
133 | /* this is linux virtual tty */ | ||
134 | sprintf(console + 8, "S%d" + 1, u.vt.v_active); | ||
135 | break; | ||
136 | } | ||
130 | #endif | 137 | #endif |
131 | if (console[8]) { | 138 | #ifdef TIOCGSERIAL |
132 | fd = xopen(console, O_RDWR); | 139 | if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { |
133 | //bb_error_msg("switching to '%s'", console); | 140 | /* this is a serial console, asuming it is named /dev/ttySn */ |
134 | dup2(fd, 0); | 141 | sprintf(console + 8, "S%d", u.sr.line); |
135 | dup2(fd, 1); | 142 | break; |
136 | dup2(fd, 2); | 143 | } |
137 | while (fd > 2) | 144 | #endif |
138 | close(fd--); | 145 | /* nope, could not find it */ |
139 | /* Some other session may have it as ctty, | 146 | goto ret; |
140 | * steal it from them: | 147 | } while (0); |
141 | */ | 148 | |
142 | ioctl(0, TIOCSCTTY, 1); | 149 | fd = open_or_warn(console, O_RDWR); |
143 | } | 150 | if (fd < 0) |
151 | goto ret; | ||
152 | //bb_error_msg("switching to '%s'", console); | ||
153 | dup2(fd, 0); | ||
154 | dup2(fd, 1); | ||
155 | dup2(fd, 2); | ||
156 | while (fd > 2) | ||
157 | close(fd--); | ||
158 | /* Some other session may have it as ctty, | ||
159 | * steal it from them: | ||
160 | */ | ||
161 | ioctl(0, TIOCSCTTY, 1); | ||
144 | } | 162 | } |
145 | 163 | ||
164 | ret: | ||
146 | BB_EXECVP_or_die(argv); | 165 | BB_EXECVP_or_die(argv); |
147 | } | 166 | } |
diff --git a/shell/hush.c b/shell/hush.c index 1082738a2..e4138adf7 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -2281,7 +2281,7 @@ static void o_addqblock(o_string *o, const char *str, int len) | |||
2281 | ordinary_cnt = len; | 2281 | ordinary_cnt = len; |
2282 | o_addblock(o, str, ordinary_cnt); | 2282 | o_addblock(o, str, ordinary_cnt); |
2283 | if (ordinary_cnt == len) | 2283 | if (ordinary_cnt == len) |
2284 | return; | 2284 | return; /* NUL is already added by o_addblock */ |
2285 | str += ordinary_cnt; | 2285 | str += ordinary_cnt; |
2286 | len -= ordinary_cnt + 1; /* we are processing + 1 char below */ | 2286 | len -= ordinary_cnt + 1; /* we are processing + 1 char below */ |
2287 | 2287 | ||
@@ -2295,8 +2295,8 @@ static void o_addqblock(o_string *o, const char *str, int len) | |||
2295 | o_grow_by(o, sz); | 2295 | o_grow_by(o, sz); |
2296 | o->data[o->length] = ch; | 2296 | o->data[o->length] = ch; |
2297 | o->length++; | 2297 | o->length++; |
2298 | o->data[o->length] = '\0'; | ||
2299 | } | 2298 | } |
2299 | o->data[o->length] = '\0'; | ||
2300 | } | 2300 | } |
2301 | 2301 | ||
2302 | static void o_addQblock(o_string *o, const char *str, int len) | 2302 | static void o_addQblock(o_string *o, const char *str, int len) |
@@ -2385,6 +2385,7 @@ static int o_save_ptr_helper(o_string *o, int n) | |||
2385 | n, string_len, string_start); | 2385 | n, string_len, string_start); |
2386 | o->has_empty_slot = 0; | 2386 | o->has_empty_slot = 0; |
2387 | } | 2387 | } |
2388 | o->has_quoted_part = 0; | ||
2388 | list[n] = (char*)(uintptr_t)string_len; | 2389 | list[n] = (char*)(uintptr_t)string_len; |
2389 | return n + 1; | 2390 | return n + 1; |
2390 | } | 2391 | } |
@@ -3264,14 +3265,6 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
3264 | ) { | 3265 | ) { |
3265 | p += 3; | 3266 | p += 3; |
3266 | } | 3267 | } |
3267 | if (p == word->data || p[0] != '\0') { | ||
3268 | /* saw no "$@", or not only "$@" but some | ||
3269 | * real text is there too */ | ||
3270 | /* insert "empty variable" reference, this makes | ||
3271 | * e.g. "", $empty"" etc to not disappear */ | ||
3272 | o_addchr(word, SPECIAL_VAR_SYMBOL); | ||
3273 | o_addchr(word, SPECIAL_VAR_SYMBOL); | ||
3274 | } | ||
3275 | } | 3268 | } |
3276 | command->argv = add_string_to_strings(command->argv, xstrdup(word->data)); | 3269 | command->argv = add_string_to_strings(command->argv, xstrdup(word->data)); |
3277 | debug_print_strings("word appended to argv", command->argv); | 3270 | debug_print_strings("word appended to argv", command->argv); |
@@ -4515,20 +4508,30 @@ static struct pipe *parse_stream(char **pstring, | |||
4515 | break; | 4508 | break; |
4516 | case '\'': | 4509 | case '\'': |
4517 | dest.has_quoted_part = 1; | 4510 | dest.has_quoted_part = 1; |
4518 | while (1) { | 4511 | if (next == '\'' && !ctx.pending_redirect) { |
4519 | ch = i_getch(input); | 4512 | insert_empty_quoted_str_marker: |
4520 | if (ch == EOF) { | 4513 | nommu_addchr(&ctx.as_string, next); |
4521 | syntax_error_unterm_ch('\''); | 4514 | i_getch(input); /* eat second ' */ |
4522 | goto parse_error; | 4515 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); |
4516 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
4517 | } else { | ||
4518 | while (1) { | ||
4519 | ch = i_getch(input); | ||
4520 | if (ch == EOF) { | ||
4521 | syntax_error_unterm_ch('\''); | ||
4522 | goto parse_error; | ||
4523 | } | ||
4524 | nommu_addchr(&ctx.as_string, ch); | ||
4525 | if (ch == '\'') | ||
4526 | break; | ||
4527 | o_addqchr(&dest, ch); | ||
4523 | } | 4528 | } |
4524 | nommu_addchr(&ctx.as_string, ch); | ||
4525 | if (ch == '\'') | ||
4526 | break; | ||
4527 | o_addqchr(&dest, ch); | ||
4528 | } | 4529 | } |
4529 | break; | 4530 | break; |
4530 | case '"': | 4531 | case '"': |
4531 | dest.has_quoted_part = 1; | 4532 | dest.has_quoted_part = 1; |
4533 | if (next == '"' && !ctx.pending_redirect) | ||
4534 | goto insert_empty_quoted_str_marker; | ||
4532 | if (dest.o_assignment == NOT_ASSIGNMENT) | 4535 | if (dest.o_assignment == NOT_ASSIGNMENT) |
4533 | dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; | 4536 | dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; |
4534 | if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1)) | 4537 | if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1)) |
@@ -4750,12 +4753,22 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len | |||
4750 | 4753 | ||
4751 | /* Store given string, finalizing the word and starting new one whenever | 4754 | /* Store given string, finalizing the word and starting new one whenever |
4752 | * we encounter IFS char(s). This is used for expanding variable values. | 4755 | * we encounter IFS char(s). This is used for expanding variable values. |
4753 | * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ | 4756 | * End-of-string does NOT finalize word: think about 'echo -$VAR-'. |
4754 | static int expand_on_ifs(o_string *output, int n, const char *str) | 4757 | * Return in *ended_with_ifs: |
4758 | * 1 - ended with IFS char, else 0 (this includes case of empty str). | ||
4759 | */ | ||
4760 | static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str) | ||
4755 | { | 4761 | { |
4762 | int last_is_ifs = 0; | ||
4763 | |||
4756 | while (1) { | 4764 | while (1) { |
4757 | int word_len = strcspn(str, G.ifs); | 4765 | int word_len; |
4766 | |||
4767 | if (!*str) /* EOL - do not finalize word */ | ||
4768 | break; | ||
4769 | word_len = strcspn(str, G.ifs); | ||
4758 | if (word_len) { | 4770 | if (word_len) { |
4771 | /* We have WORD_LEN leading non-IFS chars */ | ||
4759 | if (!(output->o_expflags & EXP_FLAG_GLOB)) { | 4772 | if (!(output->o_expflags & EXP_FLAG_GLOB)) { |
4760 | o_addblock(output, str, word_len); | 4773 | o_addblock(output, str, word_len); |
4761 | } else { | 4774 | } else { |
@@ -4768,15 +4781,36 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
4768 | /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */ | 4781 | /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */ |
4769 | /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */ | 4782 | /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */ |
4770 | } | 4783 | } |
4784 | last_is_ifs = 0; | ||
4771 | str += word_len; | 4785 | str += word_len; |
4786 | if (!*str) /* EOL - do not finalize word */ | ||
4787 | break; | ||
4772 | } | 4788 | } |
4789 | |||
4790 | /* We know str here points to at least one IFS char */ | ||
4791 | last_is_ifs = 1; | ||
4792 | str += strspn(str, G.ifs); /* skip IFS chars */ | ||
4773 | if (!*str) /* EOL - do not finalize word */ | 4793 | if (!*str) /* EOL - do not finalize word */ |
4774 | break; | 4794 | break; |
4775 | o_addchr(output, '\0'); | 4795 | |
4776 | debug_print_list("expand_on_ifs", output, n); | 4796 | /* Start new word... but not always! */ |
4777 | n = o_save_ptr(output, n); | 4797 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ |
4778 | str += strspn(str, G.ifs); /* skip ifs chars */ | 4798 | if (output->has_quoted_part |
4799 | /* Case "v=' a'; echo $v": | ||
4800 | * here nothing precedes the space in $v expansion, | ||
4801 | * therefore we should not finish the word | ||
4802 | * (IOW: if there *is* word to finalize, only then do it): | ||
4803 | */ | ||
4804 | || (n > 0 && output->data[output->length - 1]) | ||
4805 | ) { | ||
4806 | o_addchr(output, '\0'); | ||
4807 | debug_print_list("expand_on_ifs", output, n); | ||
4808 | n = o_save_ptr(output, n); | ||
4809 | } | ||
4779 | } | 4810 | } |
4811 | |||
4812 | if (ended_with_ifs) | ||
4813 | *ended_with_ifs = last_is_ifs; | ||
4780 | debug_print_list("expand_on_ifs[1]", output, n); | 4814 | debug_print_list("expand_on_ifs[1]", output, n); |
4781 | return n; | 4815 | return n; |
4782 | } | 4816 | } |
@@ -5191,6 +5225,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5191 | * expansion of right-hand side of assignment == 1-element expand. | 5225 | * expansion of right-hand side of assignment == 1-element expand. |
5192 | */ | 5226 | */ |
5193 | char cant_be_null = 0; /* only bit 0x80 matters */ | 5227 | char cant_be_null = 0; /* only bit 0x80 matters */ |
5228 | int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ | ||
5194 | char *p; | 5229 | char *p; |
5195 | 5230 | ||
5196 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, | 5231 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, |
@@ -5209,6 +5244,13 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5209 | #if ENABLE_SH_MATH_SUPPORT | 5244 | #if ENABLE_SH_MATH_SUPPORT |
5210 | char arith_buf[sizeof(arith_t)*3 + 2]; | 5245 | char arith_buf[sizeof(arith_t)*3 + 2]; |
5211 | #endif | 5246 | #endif |
5247 | |||
5248 | if (ended_in_ifs) { | ||
5249 | o_addchr(output, '\0'); | ||
5250 | n = o_save_ptr(output, n); | ||
5251 | ended_in_ifs = 0; | ||
5252 | } | ||
5253 | |||
5212 | o_addblock(output, arg, p - arg); | 5254 | o_addblock(output, arg, p - arg); |
5213 | debug_print_list("expand_vars_to_list[1]", output, n); | 5255 | debug_print_list("expand_vars_to_list[1]", output, n); |
5214 | arg = ++p; | 5256 | arg = ++p; |
@@ -5237,7 +5279,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5237 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 5279 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
5238 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 5280 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
5239 | while (G.global_argv[i]) { | 5281 | while (G.global_argv[i]) { |
5240 | n = expand_on_ifs(output, n, G.global_argv[i]); | 5282 | n = expand_on_ifs(NULL, output, n, G.global_argv[i]); |
5241 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); | 5283 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
5242 | if (G.global_argv[i++][0] && G.global_argv[i]) { | 5284 | if (G.global_argv[i++][0] && G.global_argv[i]) { |
5243 | /* this argv[] is not empty and not last: | 5285 | /* this argv[] is not empty and not last: |
@@ -5270,11 +5312,13 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5270 | if (G.ifs[0]) | 5312 | if (G.ifs[0]) |
5271 | o_addchr(output, G.ifs[0]); | 5313 | o_addchr(output, G.ifs[0]); |
5272 | } | 5314 | } |
5315 | output->has_quoted_part = 1; | ||
5273 | } | 5316 | } |
5274 | break; | 5317 | break; |
5275 | } | 5318 | } |
5276 | case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ | 5319 | case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ |
5277 | /* "Empty variable", used to make "" etc to not disappear */ | 5320 | /* "Empty variable", used to make "" etc to not disappear */ |
5321 | output->has_quoted_part = 1; | ||
5278 | arg++; | 5322 | arg++; |
5279 | cant_be_null = 0x80; | 5323 | cant_be_null = 0x80; |
5280 | break; | 5324 | break; |
@@ -5312,10 +5356,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5312 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, | 5356 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, |
5313 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 5357 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
5314 | if (val && val[0]) { | 5358 | if (val && val[0]) { |
5315 | n = expand_on_ifs(output, n, val); | 5359 | n = expand_on_ifs(&ended_in_ifs, output, n, val); |
5316 | val = NULL; | 5360 | val = NULL; |
5317 | } | 5361 | } |
5318 | } else { /* quoted $VAR, val will be appended below */ | 5362 | } else { /* quoted $VAR, val will be appended below */ |
5363 | output->has_quoted_part = 1; | ||
5319 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, | 5364 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, |
5320 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 5365 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
5321 | } | 5366 | } |
@@ -5340,6 +5385,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5340 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ | 5385 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ |
5341 | 5386 | ||
5342 | if (arg[0]) { | 5387 | if (arg[0]) { |
5388 | if (ended_in_ifs) { | ||
5389 | o_addchr(output, '\0'); | ||
5390 | n = o_save_ptr(output, n); | ||
5391 | } | ||
5343 | debug_print_list("expand_vars_to_list[a]", output, n); | 5392 | debug_print_list("expand_vars_to_list[a]", output, n); |
5344 | /* this part is literal, and it was already pre-quoted | 5393 | /* this part is literal, and it was already pre-quoted |
5345 | * if needed (much earlier), do not use o_addQstr here! */ | 5394 | * if needed (much earlier), do not use o_addQstr here! */ |
@@ -5470,12 +5519,6 @@ static char **expand_assignments(char **argv, int count) | |||
5470 | } | 5519 | } |
5471 | 5520 | ||
5472 | 5521 | ||
5473 | #if BB_MMU | ||
5474 | /* never called */ | ||
5475 | void re_execute_shell(char ***to_free, const char *s, | ||
5476 | char *g_argv0, char **g_argv, | ||
5477 | char **builtin_argv) NORETURN; | ||
5478 | |||
5479 | static void switch_off_special_sigs(unsigned mask) | 5522 | static void switch_off_special_sigs(unsigned mask) |
5480 | { | 5523 | { |
5481 | unsigned sig = 0; | 5524 | unsigned sig = 0; |
@@ -5495,6 +5538,12 @@ static void switch_off_special_sigs(unsigned mask) | |||
5495 | } | 5538 | } |
5496 | } | 5539 | } |
5497 | 5540 | ||
5541 | #if BB_MMU | ||
5542 | /* never called */ | ||
5543 | void re_execute_shell(char ***to_free, const char *s, | ||
5544 | char *g_argv0, char **g_argv, | ||
5545 | char **builtin_argv) NORETURN; | ||
5546 | |||
5498 | static void reset_traps_to_defaults(void) | 5547 | static void reset_traps_to_defaults(void) |
5499 | { | 5548 | { |
5500 | /* This function is always called in a child shell | 5549 | /* This function is always called in a child shell |
diff --git a/shell/hush_test/hush-parsing/starquoted2.right b/shell/hush_test/hush-parsing/starquoted2.right index e1562ed6d..1bff408ca 100644 --- a/shell/hush_test/hush-parsing/starquoted2.right +++ b/shell/hush_test/hush-parsing/starquoted2.right | |||
@@ -1,4 +1,7 @@ | |||
1 | Should be printed | 1 | Should be printed |
2 | Would not be printed by bash | ||
3 | Would not be printed by bash | ||
4 | Would not be printed by bash | ||
2 | Should be printed | 5 | Should be printed |
3 | Empty: | 6 | Empty: |
4 | Empty: | 7 | Empty: |
diff --git a/shell/hush_test/hush-parsing/starquoted2.tests b/shell/hush_test/hush-parsing/starquoted2.tests index f305c4cd9..7c5ff45b8 100755 --- a/shell/hush_test/hush-parsing/starquoted2.tests +++ b/shell/hush_test/hush-parsing/starquoted2.tests | |||
@@ -8,9 +8,9 @@ for a in "$@"; do echo Should not be printed; done | |||
8 | # Yes, believe it or not, bash is mesmerized by "$@" and stops | 8 | # Yes, believe it or not, bash is mesmerized by "$@" and stops |
9 | # treating "" as "this word cannot be expanded to nothing, | 9 | # treating "" as "this word cannot be expanded to nothing, |
10 | # but must be at least null string". Now it can be expanded to nothing. | 10 | # but must be at least null string". Now it can be expanded to nothing. |
11 | for a in "$@"""; do echo Should not be printed; done | 11 | for a in "$@"""; do echo Would not be printed by bash; done |
12 | for a in """$@"; do echo Should not be printed; done | 12 | for a in """$@"; do echo Would not be printed by bash; done |
13 | for a in """$@"''"$@"''; do echo Should not be printed; done | 13 | for a in """$@"''"$@"''; do echo Would not be printed by bash; done |
14 | for a in ""; do echo Should be printed; done | 14 | for a in ""; do echo Should be printed; done |
15 | 15 | ||
16 | # Bug 207: "$@" expands to nothing, and we erroneously glob "%s\n" twice: | 16 | # Bug 207: "$@" expands to nothing, and we erroneously glob "%s\n" twice: |
diff --git a/shell/hush_test/hush-vars/var_expand_on_ifs.right b/shell/hush_test/hush-vars/var_expand_on_ifs.right new file mode 100644 index 000000000..2ed2069f7 --- /dev/null +++ b/shell/hush_test/hush-vars/var_expand_on_ifs.right | |||
@@ -0,0 +1,9 @@ | |||
1 | 1 a b c | ||
2 | 2 a + b c | ||
3 | 3 a b c | ||
4 | 4 a b c | ||
5 | 5 a b c | ||
6 | 6 a b + c | ||
7 | 7 a b c | ||
8 | 8 a b c | ||
9 | 9 a b c | ||
diff --git a/shell/hush_test/hush-vars/var_expand_on_ifs.tests b/shell/hush_test/hush-vars/var_expand_on_ifs.tests new file mode 100755 index 000000000..a12ff8ec8 --- /dev/null +++ b/shell/hush_test/hush-vars/var_expand_on_ifs.tests | |||
@@ -0,0 +1,11 @@ | |||
1 | b=' b ' | ||
2 | e='' | ||
3 | echo 1 a $b c | ||
4 | echo 2 a +$b c | ||
5 | echo 3 a $e$b c | ||
6 | echo 4 a "$e"$b c | ||
7 | echo 5 a ""$b c | ||
8 | echo 6 a $b+ c | ||
9 | echo 7 a $b$e c | ||
10 | echo 8 a $b"$e" c | ||
11 | echo 9 a $b"" c | ||