aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-04-11 16:02:58 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-11 16:02:58 +0200
commit9678636911b39a7adf9b51d5b625cf4dc7e4ac81 (patch)
tree75a0790a958a82015b34fc033d6f22f6f6dd3cb2 /shell
parent34179956f96370f5a53e73073d984d62135cd037 (diff)
downloadbusybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.gz
busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.bz2
busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.zip
hush: IFS fixes
$ IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done |x| $ IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done |x| || function old new delta run_pipe 1789 1870 +81 expand_on_ifs 310 361 +51 pseudo_exec_argv 588 591 +3 builtin_local 50 53 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 138/0) Total: 138 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash_test/ash-vars/var_wordsplit_ifs4.right5
-rwxr-xr-xshell/ash_test/ash-vars/var_wordsplit_ifs4.tests4
-rw-r--r--shell/hush.c38
-rw-r--r--shell/hush_test/hush-vars/var_wordsplit_ifs4.right5
-rwxr-xr-xshell/hush_test/hush-vars/var_wordsplit_ifs4.tests4
5 files changed, 54 insertions, 2 deletions
diff --git a/shell/ash_test/ash-vars/var_wordsplit_ifs4.right b/shell/ash_test/ash-vars/var_wordsplit_ifs4.right
new file mode 100644
index 000000000..c27284c31
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_wordsplit_ifs4.right
@@ -0,0 +1,5 @@
1|x|
2Ok1:0
3|x|
4||
5Ok2:0
diff --git a/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests b/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests
new file mode 100755
index 000000000..638bfbb28
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests
@@ -0,0 +1,4 @@
1IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
2echo Ok1:$?
3IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
4echo Ok2:$?
diff --git a/shell/hush.c b/shell/hush.c
index 248364be2..8e95a26a6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -930,6 +930,7 @@ struct globals {
930 unsigned getopt_count; 930 unsigned getopt_count;
931#endif 931#endif
932 const char *ifs; 932 const char *ifs;
933 char *ifs_whitespace; /* = G.ifs or malloced */
933 const char *cwd; 934 const char *cwd;
934 struct variable *top_var; 935 struct variable *top_var;
935 char **expanded_assignments; 936 char **expanded_assignments;
@@ -5696,10 +5697,20 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
5696 5697
5697 /* We know str here points to at least one IFS char */ 5698 /* We know str here points to at least one IFS char */
5698 last_is_ifs = 1; 5699 last_is_ifs = 1;
5699 str += strspn(str, G.ifs); /* skip IFS chars */ 5700 str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
5700 if (!*str) /* EOL - do not finalize word */ 5701 if (!*str) /* EOL - do not finalize word */
5701 break; 5702 break;
5702 5703
5704 if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
5705 && strchr(G.ifs, *str) /* the second check would fail */
5706 ) {
5707 /* This is a non-whitespace $IFS char */
5708 /* Skip it and IFS whitespace chars, start new word */
5709 str++;
5710 str += strspn(str, G.ifs_whitespace);
5711 goto new_word;
5712 }
5713
5703 /* Start new word... but not always! */ 5714 /* Start new word... but not always! */
5704 /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ 5715 /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
5705 if (output->has_quoted_part 5716 if (output->has_quoted_part
@@ -5710,6 +5721,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
5710 */ 5721 */
5711 || (n > 0 && output->data[output->length - 1]) 5722 || (n > 0 && output->data[output->length - 1])
5712 ) { 5723 ) {
5724 new_word:
5713 o_addchr(output, '\0'); 5725 o_addchr(output, '\0');
5714 debug_print_list("expand_on_ifs", output, n); 5726 debug_print_list("expand_on_ifs", output, n);
5715 n = o_save_ptr(output, n); 5727 n = o_save_ptr(output, n);
@@ -8283,9 +8295,31 @@ static NOINLINE int run_pipe(struct pipe *pi)
8283 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" 8295 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
8284 * Result should be 3 lines: q w e, qwe, q w e 8296 * Result should be 3 lines: q w e, qwe, q w e
8285 */ 8297 */
8298 if (G.ifs_whitespace != G.ifs)
8299 free(G.ifs_whitespace);
8286 G.ifs = get_local_var_value("IFS"); 8300 G.ifs = get_local_var_value("IFS");
8287 if (!G.ifs) 8301 if (G.ifs) {
8302 char *p;
8303 G.ifs_whitespace = (char*)G.ifs;
8304 p = skip_whitespace(G.ifs);
8305 if (*p) {
8306 /* Not all $IFS is whitespace */
8307 char *d;
8308 int len = p - G.ifs;
8309 p = skip_non_whitespace(p);
8310 G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
8311 d = mempcpy(G.ifs_whitespace, G.ifs, len);
8312 while (*p) {
8313 if (isspace(*p))
8314 *d++ = *p;
8315 p++;
8316 }
8317 *d = '\0';
8318 }
8319 } else {
8288 G.ifs = defifs; 8320 G.ifs = defifs;
8321 G.ifs_whitespace = (char*)G.ifs;
8322 }
8289 8323
8290 IF_HUSH_JOB(pi->pgrp = -1;) 8324 IF_HUSH_JOB(pi->pgrp = -1;)
8291 pi->stopped_cmds = 0; 8325 pi->stopped_cmds = 0;
diff --git a/shell/hush_test/hush-vars/var_wordsplit_ifs4.right b/shell/hush_test/hush-vars/var_wordsplit_ifs4.right
new file mode 100644
index 000000000..c27284c31
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_wordsplit_ifs4.right
@@ -0,0 +1,5 @@
1|x|
2Ok1:0
3|x|
4||
5Ok2:0
diff --git a/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests b/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests
new file mode 100755
index 000000000..638bfbb28
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests
@@ -0,0 +1,4 @@
1IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
2echo Ok1:$?
3IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
4echo Ok2:$?