ash: fix $IFS handling in read. closes bug 235

This commit is contained in:
Denis Vlasenko 2009-03-31 19:18:17 +00:00
parent 7566bae197
commit 46aeab9a34
3 changed files with 37 additions and 12 deletions

View File

@ -12574,7 +12574,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#endif #endif
status = 0; status = 0;
startword = 1; startword = 2;
backslash = 0; backslash = 0;
#if ENABLE_ASH_READ_TIMEOUT #if ENABLE_ASH_READ_TIMEOUT
if (timeout) /* NB: ensuring end_ms is nonzero */ if (timeout) /* NB: ensuring end_ms is nonzero */
@ -12582,6 +12582,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#endif #endif
STARTSTACKSTR(p); STARTSTACKSTR(p);
do { do {
const char *is_ifs;
#if ENABLE_ASH_READ_TIMEOUT #if ENABLE_ASH_READ_TIMEOUT
if (end_ms) { if (end_ms) {
struct pollfd pfd[1]; struct pollfd pfd[1];
@ -12611,25 +12613,34 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
continue; continue;
} }
if (!rflag && c == '\\') { if (!rflag && c == '\\') {
backslash++; backslash = 1;
continue; continue;
} }
if (c == '\n') if (c == '\n')
break; break;
if (startword && *ifs == ' ' && strchr(ifs, c)) { is_ifs = strchr(ifs, c);
continue; if (startword && is_ifs) {
if (isspace(c))
continue;
/* non-space ifs char */
startword--;
if (startword == 1) /* first one? */
continue;
} }
startword = 0; startword = 0;
if (ap[1] != NULL && strchr(ifs, c) != NULL) { if (ap[1] != NULL && is_ifs) {
const char *beg;
STACKSTRNUL(p); STACKSTRNUL(p);
setvar(*ap, stackblock(), 0); beg = stackblock();
setvar(*ap, beg, 0);
ap++; ap++;
startword = 1; /* can we skip one non-space ifs? (2: yes) */
startword = isspace(c) ? 2 : 1;
STARTSTACKSTR(p); STARTSTACKSTR(p);
} else { continue;
put:
STPUTC(c, p);
} }
put:
STPUTC(c, p);
} }
/* end of do {} while: */ /* end of do {} while: */
#if ENABLE_ASH_READ_NCHARS #if ENABLE_ASH_READ_NCHARS
@ -12643,8 +12654,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#endif #endif
STACKSTRNUL(p); STACKSTRNUL(p);
/* Remove trailing blanks */ /* Remove trailing space ifs chars */
while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) while ((char *)stackblock() <= --p && isspace(*p) && strchr(ifs, *p) != NULL)
*p = '\0'; *p = '\0';
setvar(*ap, stackblock(), 0); setvar(*ap, stackblock(), 0);
while (*++ap != NULL) while (*++ap != NULL)

View File

@ -0,0 +1,7 @@
.a. .b. .c.
.a. .b. .c.
.a. .. .b,c.
.a. .. .b,c.
.a. .. .c.
.a. .. .c. .d.
.a. .. .b,c,d , ,.

View File

@ -0,0 +1,7 @@
printf 'a\t\tb\tc\n' | ( IFS=$(printf "\t") read a b c; echo ".$a. .$b. .$c." )
printf 'a\t\tb\tc\n' | ( IFS=$(printf " \t") read a b c; echo ".$a. .$b. .$c." )
printf 'a,,b,c\n' | ( IFS="," read a b c; echo ".$a. .$b. .$c." )
printf 'a,,b,c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )
printf 'a ,, c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )
printf 'a ,, c d\n' | ( IFS=" ," read a b c d; echo ".$a. .$b. .$c. .$d." )
printf ' a,,b,c,d , ,\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )