diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-12 22:12:10 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-12 22:12:10 +0100 |
commit | 045f4ad92c07434625e168bc8c37aa0e89f6e58e (patch) | |
tree | 83e8c3eeca479d0ad4cc78a83c6da55678f91f0f | |
parent | 7306727d1b2ed05afc91548ba374f7400a2389e3 (diff) | |
download | busybox-w32-045f4ad92c07434625e168bc8c37aa0e89f6e58e.tar.gz busybox-w32-045f4ad92c07434625e168bc8c37aa0e89f6e58e.tar.bz2 busybox-w32-045f4ad92c07434625e168bc8c37aa0e89f6e58e.zip |
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 <vda.linux@googlemail.com>
-rw-r--r-- | 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 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), | |||
31 | const char *opt_u | 31 | const char *opt_u |
32 | ) | 32 | ) |
33 | { | 33 | { |
34 | static const char *const arg_REPLY[] = { "REPLY", NULL }; | ||
35 | |||
36 | unsigned end_ms; /* -t TIMEOUT */ | 34 | unsigned end_ms; /* -t TIMEOUT */ |
37 | int fd; /* -u FD */ | 35 | int fd; /* -u FD */ |
38 | int nchars; /* -n NUM */ | 36 | int nchars; /* -n NUM */ |
@@ -94,8 +92,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags), | |||
94 | fflush_all(); | 92 | fflush_all(); |
95 | } | 93 | } |
96 | 94 | ||
97 | if (argv[0] == NULL) | ||
98 | argv = (char**)arg_REPLY; | ||
99 | if (ifs == NULL) | 95 | if (ifs == NULL) |
100 | ifs = defifs; | 96 | ifs = defifs; |
101 | 97 | ||
@@ -125,7 +121,6 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags), | |||
125 | bufpos = 0; | 121 | bufpos = 0; |
126 | do { | 122 | do { |
127 | char c; | 123 | char c; |
128 | const char *is_ifs; | ||
129 | 124 | ||
130 | if (end_ms) { | 125 | if (end_ms) { |
131 | int timeout; | 126 | int timeout; |
@@ -163,40 +158,53 @@ builtin_read(void (*setvar)(const char *name, const char *val, int flags), | |||
163 | } | 158 | } |
164 | if (c == '\n') | 159 | if (c == '\n') |
165 | break; | 160 | break; |
166 | /* $IFS splitting */ | 161 | |
162 | /* $IFS splitting. NOT done if we run "read" | ||
163 | * without variable names (bash compat). | ||
164 | * Thus, "read" and "read REPLY" are not the same. | ||
165 | */ | ||
166 | if (argv[0]) { | ||
167 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */ | 167 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */ |
168 | is_ifs = strchr(ifs, c); | 168 | const char *is_ifs = strchr(ifs, c); |
169 | if (startword && is_ifs) { | 169 | if (startword && is_ifs) { |
170 | if (isspace(c)) | 170 | if (isspace(c)) |
171 | continue; | ||
172 | /* it is a non-space ifs char */ | ||
173 | startword--; | ||
174 | if (startword == 1) /* first one? */ | ||
175 | continue; /* yes, it is not next word yet */ | ||
176 | } | ||
177 | startword = 0; | ||
178 | if (argv[1] != NULL && is_ifs) { | ||
179 | buffer[bufpos] = '\0'; | ||
180 | bufpos = 0; | ||
181 | setvar(*argv, buffer, 0); | ||
182 | argv++; | ||
183 | /* can we skip one non-space ifs char? (2: yes) */ | ||
184 | startword = isspace(c) ? 2 : 1; | ||
171 | continue; | 185 | continue; |
172 | /* it is a non-space ifs char */ | 186 | } |
173 | startword--; | ||
174 | if (startword == 1) /* first one? */ | ||
175 | continue; /* yes, it is not next word yet */ | ||
176 | } | ||
177 | startword = 0; | ||
178 | if (argv[1] != NULL && is_ifs) { | ||
179 | buffer[bufpos] = '\0'; | ||
180 | bufpos = 0; | ||
181 | setvar(*argv, buffer, 0); | ||
182 | argv++; | ||
183 | /* can we skip one non-space ifs char? (2: yes) */ | ||
184 | startword = isspace(c) ? 2 : 1; | ||
185 | continue; | ||
186 | } | 187 | } |
187 | put: | 188 | put: |
188 | bufpos++; | 189 | bufpos++; |
189 | } while (--nchars); | 190 | } while (--nchars); |
190 | 191 | ||
191 | /* Remove trailing space ifs chars */ | 192 | if (argv[0]) { |
192 | while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL) | 193 | /* Remove trailing space $IFS chars */ |
193 | continue; | 194 | while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL) |
194 | buffer[bufpos + 1] = '\0'; | 195 | continue; |
195 | 196 | buffer[bufpos + 1] = '\0'; | |
196 | setvar(*argv, buffer, 0); | 197 | /* Use the remainder as a value for the next variable */ |
198 | setvar(*argv, buffer, 0); | ||
199 | /* Set the rest to "" */ | ||
200 | while (*++argv) | ||
201 | setvar(*argv, "", 0); | ||
202 | } else { | ||
203 | /* Note: no $IFS removal */ | ||
204 | buffer[bufpos] = '\0'; | ||
205 | setvar("REPLY", buffer, 0); | ||
206 | } | ||
197 | 207 | ||
198 | while (*++argv != NULL) | ||
199 | setvar(*argv, "", 0); | ||
200 | ret: | 208 | ret: |
201 | free(buffer); | 209 | free(buffer); |
202 | if (read_flags & BUILTIN_READ_SILENT) | 210 | if (read_flags & BUILTIN_READ_SILENT) |