From 045f4ad92c07434625e168bc8c37aa0e89f6e58e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Jan 2010 22:12:10 +0100 Subject: [PATCH] shell/read: fix "'read' without parameters" bash compat thingy 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 --- shell/builtin_read.c | 70 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/shell/builtin_read.c b/shell/builtin_read.c index 7f667e9c1..24cfe08fb 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'; + 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); + } - setvar(*argv, buffer, 0); - - while (*++argv != NULL) - setvar(*argv, "", 0); ret: free(buffer); if (read_flags & BUILTIN_READ_SILENT)