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:
parent
a7fc139721
commit
f0688a48d2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=287308
@ -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 "" */
|
||||||
|
@ -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
|
||||||
|
10
bin/sh/tests/builtins/read9.0
Normal file
10
bin/sh/tests/builtins/read9.0
Normal 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 ." ]
|
Loading…
Reference in New Issue
Block a user