[git commit master] shell/read: fix "'read' without parameters" bash compat thingy

Denys Vlasenko vda.linux at googlemail.com
Tue Jan 12 21:12:10 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=045f4ad92c07434625e168bc8c37aa0e89f6e58e
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

previous change:

function                                             old     new   delta
builtin_read                                          82    1074    +992
popstring                                            134     140      +6
readcmd                                             1034     148    -886
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 998/-886)          Total: 112 bytes

this change:

builtin_read                                        1074    1096     +22
static.arg_REPLY                                       8       -      -8
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/0 up/down: 22/-8)              Total: 14 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/builtin_read.c |   70 +++++++++++++++++++++++++++----------------------
 1 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/shell/builtin_read.c b/shell/builtin_read.c
index 7f667e9..24cfe08 100644
--- a/shell/builtin_read.c
+++ b/shell/builtin_read.c
@@ -31,8 +31,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
 	const char *opt_u
 )
 {
-	static const char *const arg_REPLY[] = { "REPLY", NULL };
-
 	unsigned end_ms; /* -t TIMEOUT */
 	int fd; /* -u FD */
 	int nchars; /* -n NUM */
@@ -94,8 +92,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
 		fflush_all();
 	}
 
-	if (argv[0] == NULL)
-		argv = (char**)arg_REPLY;
 	if (ifs == NULL)
 		ifs = defifs;
 
@@ -125,7 +121,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
 	bufpos = 0;
 	do {
 		char c;
-		const char *is_ifs;
 
 		if (end_ms) {
 			int timeout;
@@ -163,40 +158,53 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags),
 		}
 		if (c == '\n')
 			break;
-		/* $IFS splitting */
+
+		/* $IFS splitting. NOT done if we run "read"
+		 * without variable names (bash compat).
+		 * Thus, "read" and "read REPLY" are not the same.
+		 */
+		if (argv[0]) {
 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
-		is_ifs = strchr(ifs, c);
-		if (startword && is_ifs) {
-			if (isspace(c))
+			const char *is_ifs = strchr(ifs, c);
+			if (startword && is_ifs) {
+				if (isspace(c))
+					continue;
+				/* it is a non-space ifs char */
+				startword--;
+				if (startword == 1) /* first one? */
+					continue; /* yes, it is not next word yet */
+			}
+			startword = 0;
+			if (argv[1] != NULL && is_ifs) {
+				buffer[bufpos] = '\0';
+				bufpos = 0;
+				setvar(*argv, buffer, 0);
+				argv++;
+				/* can we skip one non-space ifs char? (2: yes) */
+				startword = isspace(c) ? 2 : 1;
 				continue;
-			/* it is a non-space ifs char */
-			startword--;
-			if (startword == 1) /* first one? */
-				continue; /* yes, it is not next word yet */
-		}
-		startword = 0;
-		if (argv[1] != NULL && is_ifs) {
-			buffer[bufpos] = '\0';
-			bufpos = 0;
-			setvar(*argv, buffer, 0);
-			argv++;
-			/* can we skip one non-space ifs char? (2: yes) */
-			startword = isspace(c) ? 2 : 1;
-			continue;
+			}
 		}
  put:
 		bufpos++;
 	} while (--nchars);
 
-	/* Remove trailing space ifs chars */
-	while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL)
-		continue;
-	buffer[bufpos + 1] = '\0';
-
-	setvar(*argv, buffer, 0);
+	if (argv[0]) {
+		/* Remove trailing space $IFS chars */
+		while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL)
+			continue;
+		buffer[bufpos + 1] = '\0';
+		/* Use the remainder as a value for the next variable */
+		setvar(*argv, buffer, 0);
+		/* Set the rest to "" */
+		while (*++argv)
+			setvar(*argv, "", 0);
+	} else {
+		/* Note: no $IFS removal */
+		buffer[bufpos] = '\0';
+		setvar("REPLY", buffer, 0);
+	}
 
-	while (*++argv != NULL)
-		setvar(*argv, "", 0);
  ret:
 	free(buffer);
 	if (read_flags & BUILTIN_READ_SILENT)
-- 
1.6.3.3



More information about the busybox-cvs mailing list