sh: Fix read with escaped IFS characters at the end.

Characters escaped with a backslash must be treated as if they were not in
IFS. This includes stripping trailing IFS characters.
This commit is contained in:
Jilles Tjoelker 2015-08-30 17:24:22 +00:00
parent a7fc139721
commit f0688a48d2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=287308
3 changed files with 28 additions and 12 deletions

View File

@ -100,6 +100,7 @@ readcmd(int argc __unused, char **argv __unused)
int i; int i;
int is_ifs; int is_ifs;
int saveall = 0; int saveall = 0;
ptrdiff_t lastnonifs, lastnonifsws;
struct timeval tv; struct timeval tv;
char *tvptr; char *tvptr;
fd_set ifds; fd_set ifds;
@ -169,6 +170,7 @@ readcmd(int argc __unused, char **argv __unused)
startword = 2; startword = 2;
backslash = 0; backslash = 0;
STARTSTACKSTR(p); STARTSTACKSTR(p);
lastnonifs = lastnonifsws = -1;
for (;;) { for (;;) {
nread = read(STDIN_FILENO, &c, 1); nread = read(STDIN_FILENO, &c, 1);
if (nread == -1) { if (nread == -1) {
@ -193,6 +195,7 @@ readcmd(int argc __unused, char **argv __unused)
backslash = 0; backslash = 0;
if (c != '\n') { if (c != '\n') {
startword = 0; startword = 0;
lastnonifs = lastnonifsws = p - stackblock();
USTPUTC(c, p); USTPUTC(c, p);
} }
continue; continue;
@ -218,8 +221,10 @@ readcmd(int argc __unused, char **argv __unused)
if (is_ifs == 2 && startword == 1) { if (is_ifs == 2 && startword == 1) {
/* Only one non-whitespace IFS per word */ /* Only one non-whitespace IFS per word */
startword = 2; startword = 2;
if (saveall) if (saveall) {
lastnonifsws = p - stackblock();
USTPUTC(c, p); USTPUTC(c, p);
}
continue; continue;
} }
} }
@ -230,6 +235,7 @@ readcmd(int argc __unused, char **argv __unused)
if (saveall) if (saveall)
/* Not just a spare terminator */ /* Not just a spare terminator */
saveall++; saveall++;
lastnonifs = lastnonifsws = p - stackblock();
USTPUTC(c, p); USTPUTC(c, p);
continue; continue;
} }
@ -240,6 +246,8 @@ readcmd(int argc __unused, char **argv __unused)
if (ap[1] == NULL) { if (ap[1] == NULL) {
/* Last variable needs all IFS chars */ /* Last variable needs all IFS chars */
saveall++; saveall++;
if (is_ifs == 2)
lastnonifsws = p - stackblock();
USTPUTC(c, p); USTPUTC(c, p);
continue; continue;
} }
@ -248,20 +256,17 @@ readcmd(int argc __unused, char **argv __unused)
setvar(*ap, stackblock(), 0); setvar(*ap, stackblock(), 0);
ap++; ap++;
STARTSTACKSTR(p); STARTSTACKSTR(p);
lastnonifs = lastnonifsws = -1;
} }
STACKSTRNUL(p); STACKSTRNUL(p);
/* Remove trailing IFS chars */ /*
for (; stackblock() <= --p; *p = 0) { * Remove trailing IFS chars: always remove whitespace, don't remove
if (!strchr(ifs, *p)) * non-whitespace unless it was naked
break; */
if (strchr(" \t\n", *p)) if (saveall <= 1)
/* Always remove whitespace */ lastnonifsws = lastnonifs;
continue; stackblock()[lastnonifsws + 1] = '\0';
if (saveall > 1)
/* Don't remove non-whitespace unless it was naked */
break;
}
setvar(*ap, stackblock(), 0); setvar(*ap, stackblock(), 0);
/* Set any remaining args to "" */ /* Set any remaining args to "" */

View File

@ -123,6 +123,7 @@ FILES+= read5.0
FILES+= read6.0 FILES+= read6.0
FILES+= read7.0 FILES+= read7.0
FILES+= read8.0 FILES+= read8.0
FILES+= read9.0
FILES+= return1.0 FILES+= return1.0
FILES+= return2.1 FILES+= return2.1
FILES+= return3.1 FILES+= return3.1

View File

@ -0,0 +1,10 @@
# $FreeBSD$
empty=''
read a b c <<EOF
\ \ A B\ \ B C\ \ $empty
EOF
read d e <<EOF
D\ $empty
EOF
[ "$a.$b.$c.$d.$e" = " A.B B.C .D ." ]