diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-31 19:18:17 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-31 19:18:17 +0000 |
commit | 46aeab9a349d097307a87d7dfde3057f9e4e6722 (patch) | |
tree | d348fadeb6bc0766c21bfc850a174a059fe4c732 | |
parent | 7566bae19715a493f40fd3fae4d69d10089af411 (diff) | |
download | busybox-w32-46aeab9a349d097307a87d7dfde3057f9e4e6722.tar.gz busybox-w32-46aeab9a349d097307a87d7dfde3057f9e4e6722.tar.bz2 busybox-w32-46aeab9a349d097307a87d7dfde3057f9e4e6722.zip |
ash: fix $IFS handling in read. closes bug 235
-rw-r--r-- | shell/ash.c | 35 | ||||
-rw-r--r-- | shell/ash_test/ash-read/read_ifs.right | 7 | ||||
-rwxr-xr-x | shell/ash_test/ash-read/read_ifs.tests | 7 |
3 files changed, 37 insertions, 12 deletions
diff --git a/shell/ash.c b/shell/ash.c index 13b4329b5..1de989ef3 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -12574,7 +12574,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
12574 | #endif | 12574 | #endif |
12575 | 12575 | ||
12576 | status = 0; | 12576 | status = 0; |
12577 | startword = 1; | 12577 | startword = 2; |
12578 | backslash = 0; | 12578 | backslash = 0; |
12579 | #if ENABLE_ASH_READ_TIMEOUT | 12579 | #if ENABLE_ASH_READ_TIMEOUT |
12580 | if (timeout) /* NB: ensuring end_ms is nonzero */ | 12580 | if (timeout) /* NB: ensuring end_ms is nonzero */ |
@@ -12582,6 +12582,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
12582 | #endif | 12582 | #endif |
12583 | STARTSTACKSTR(p); | 12583 | STARTSTACKSTR(p); |
12584 | do { | 12584 | do { |
12585 | const char *is_ifs; | ||
12586 | |||
12585 | #if ENABLE_ASH_READ_TIMEOUT | 12587 | #if ENABLE_ASH_READ_TIMEOUT |
12586 | if (end_ms) { | 12588 | if (end_ms) { |
12587 | struct pollfd pfd[1]; | 12589 | struct pollfd pfd[1]; |
@@ -12611,25 +12613,34 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
12611 | continue; | 12613 | continue; |
12612 | } | 12614 | } |
12613 | if (!rflag && c == '\\') { | 12615 | if (!rflag && c == '\\') { |
12614 | backslash++; | 12616 | backslash = 1; |
12615 | continue; | 12617 | continue; |
12616 | } | 12618 | } |
12617 | if (c == '\n') | 12619 | if (c == '\n') |
12618 | break; | 12620 | break; |
12619 | if (startword && *ifs == ' ' && strchr(ifs, c)) { | 12621 | is_ifs = strchr(ifs, c); |
12620 | continue; | 12622 | if (startword && is_ifs) { |
12623 | if (isspace(c)) | ||
12624 | continue; | ||
12625 | /* non-space ifs char */ | ||
12626 | startword--; | ||
12627 | if (startword == 1) /* first one? */ | ||
12628 | continue; | ||
12621 | } | 12629 | } |
12622 | startword = 0; | 12630 | startword = 0; |
12623 | if (ap[1] != NULL && strchr(ifs, c) != NULL) { | 12631 | if (ap[1] != NULL && is_ifs) { |
12632 | const char *beg; | ||
12624 | STACKSTRNUL(p); | 12633 | STACKSTRNUL(p); |
12625 | setvar(*ap, stackblock(), 0); | 12634 | beg = stackblock(); |
12635 | setvar(*ap, beg, 0); | ||
12626 | ap++; | 12636 | ap++; |
12627 | startword = 1; | 12637 | /* can we skip one non-space ifs? (2: yes) */ |
12638 | startword = isspace(c) ? 2 : 1; | ||
12628 | STARTSTACKSTR(p); | 12639 | STARTSTACKSTR(p); |
12629 | } else { | 12640 | continue; |
12630 | put: | ||
12631 | STPUTC(c, p); | ||
12632 | } | 12641 | } |
12642 | put: | ||
12643 | STPUTC(c, p); | ||
12633 | } | 12644 | } |
12634 | /* end of do {} while: */ | 12645 | /* end of do {} while: */ |
12635 | #if ENABLE_ASH_READ_NCHARS | 12646 | #if ENABLE_ASH_READ_NCHARS |
@@ -12643,8 +12654,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
12643 | #endif | 12654 | #endif |
12644 | 12655 | ||
12645 | STACKSTRNUL(p); | 12656 | STACKSTRNUL(p); |
12646 | /* Remove trailing blanks */ | 12657 | /* Remove trailing space ifs chars */ |
12647 | while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) | 12658 | while ((char *)stackblock() <= --p && isspace(*p) && strchr(ifs, *p) != NULL) |
12648 | *p = '\0'; | 12659 | *p = '\0'; |
12649 | setvar(*ap, stackblock(), 0); | 12660 | setvar(*ap, stackblock(), 0); |
12650 | while (*++ap != NULL) | 12661 | while (*++ap != NULL) |
diff --git a/shell/ash_test/ash-read/read_ifs.right b/shell/ash_test/ash-read/read_ifs.right new file mode 100644 index 000000000..027ecd18f --- /dev/null +++ b/shell/ash_test/ash-read/read_ifs.right | |||
@@ -0,0 +1,7 @@ | |||
1 | .a. .b. .c. | ||
2 | .a. .b. .c. | ||
3 | .a. .. .b,c. | ||
4 | .a. .. .b,c. | ||
5 | .a. .. .c. | ||
6 | .a. .. .c. .d. | ||
7 | .a. .. .b,c,d , ,. | ||
diff --git a/shell/ash_test/ash-read/read_ifs.tests b/shell/ash_test/ash-read/read_ifs.tests new file mode 100755 index 000000000..cf7cd934c --- /dev/null +++ b/shell/ash_test/ash-read/read_ifs.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | printf 'a\t\tb\tc\n' | ( IFS=$(printf "\t") read a b c; echo ".$a. .$b. .$c." ) | ||
2 | printf 'a\t\tb\tc\n' | ( IFS=$(printf " \t") read a b c; echo ".$a. .$b. .$c." ) | ||
3 | printf 'a,,b,c\n' | ( IFS="," read a b c; echo ".$a. .$b. .$c." ) | ||
4 | printf 'a,,b,c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) | ||
5 | printf 'a ,, c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) | ||
6 | printf 'a ,, c d\n' | ( IFS=" ," read a b c d; echo ".$a. .$b. .$c. .$d." ) | ||
7 | printf ' a,,b,c,d , ,\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) | ||