aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 15:48:57 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 15:48:57 +0000
commit9db164d6e39050d09f38288c6045cd2a2cbf6d63 (patch)
treeea5dc2d28d15da0de25c197ed7d059c3656af1a0 /shell
parent1118c95535ea51961437089fc3dece5ab4ea7e1b (diff)
parentd84b175cb6948eb17f847313bf912174e2f934e1 (diff)
downloadbusybox-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.c81
-rw-r--r--shell/hush.c117
-rw-r--r--shell/hush_test/hush-parsing/starquoted2.right3
-rwxr-xr-xshell/hush_test/hush-parsing/starquoted2.tests6
-rw-r--r--shell/hush_test/hush-vars/var_expand_on_ifs.right9
-rwxr-xr-xshell/hush_test/hush-vars/var_expand_on_ifs.tests11
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
164ret:
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
2302static void o_addQblock(o_string *o, const char *str, int len) 2302static 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-'.
4754static 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 */
4760static 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 */
5475void re_execute_shell(char ***to_free, const char *s,
5476 char *g_argv0, char **g_argv,
5477 char **builtin_argv) NORETURN;
5478
5479static void switch_off_special_sigs(unsigned mask) 5522static 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 */
5543void re_execute_shell(char ***to_free, const char *s,
5544 char *g_argv0, char **g_argv,
5545 char **builtin_argv) NORETURN;
5546
5498static void reset_traps_to_defaults(void) 5547static 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 @@
1Should be printed 1Should be printed
2Would not be printed by bash
3Would not be printed by bash
4Would not be printed by bash
2Should be printed 5Should be printed
3Empty: 6Empty:
4Empty: 7Empty:
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.
11for a in "$@"""; do echo Should not be printed; done 11for a in "$@"""; do echo Would not be printed by bash; done
12for a in """$@"; do echo Should not be printed; done 12for a in """$@"; do echo Would not be printed by bash; done
13for a in """$@"''"$@"''; do echo Should not be printed; done 13for a in """$@"''"$@"''; do echo Would not be printed by bash; done
14for a in ""; do echo Should be printed; done 14for 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 @@
11 a b c
22 a + b c
33 a b c
44 a b c
55 a b c
66 a b + c
77 a b c
88 a b c
99 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 @@
1b=' b '
2e=''
3echo 1 a $b c
4echo 2 a +$b c
5echo 3 a $e$b c
6echo 4 a "$e"$b c
7echo 5 a ""$b c
8echo 6 a $b+ c
9echo 7 a $b$e c
10echo 8 a $b"$e" c
11echo 9 a $b"" c