diff options
author | Ron Yorston <rmy@pobox.com> | 2018-04-05 15:16:37 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-04-05 15:32:49 +0100 |
commit | af122fe83fcdeb47173459715d39a5fe887a406e (patch) | |
tree | 7be50dbc074d3d73bcbe41a978e850aed90781ba | |
parent | 91ee3425d1d39a86eb0a3460d9f14e57c24e0b83 (diff) | |
download | busybox-w32-af122fe83fcdeb47173459715d39a5fe887a406e.tar.gz busybox-w32-af122fe83fcdeb47173459715d39a5fe887a406e.tar.bz2 busybox-w32-af122fe83fcdeb47173459715d39a5fe887a406e.zip |
ash: emulate raw input to read builtin
Use read_key to emulate raw input when reading from the console.
Limit this to cases where raw input is necessary:
- a maximum number of characters is to be read (-n)
- a timeout has been specified (-t)
- a non-standard delimiter is in use (-d)
This should fix GitHub issue #112 (and other things too!).
Also, omit sections of code that serve no purpose on WIN32.
-rw-r--r-- | shell/shell_common.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c index ad9048d89..a44ad0caf 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -70,7 +70,9 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
70 | char **pp; | 70 | char **pp; |
71 | char *buffer; | 71 | char *buffer; |
72 | char delim; | 72 | char delim; |
73 | #if !ENABLE_PLATFORM_MINGW32 | ||
73 | struct termios tty, old_tty; | 74 | struct termios tty, old_tty; |
75 | #endif | ||
74 | const char *retval; | 76 | const char *retval; |
75 | int bufpos; /* need to be able to hold -1 */ | 77 | int bufpos; /* need to be able to hold -1 */ |
76 | int startword; | 78 | int startword; |
@@ -140,6 +142,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
140 | } | 142 | } |
141 | 143 | ||
142 | if (opt_t && end_ms == 0) { | 144 | if (opt_t && end_ms == 0) { |
145 | #if !ENABLE_PLATFORM_MINGW32 | ||
143 | /* "If timeout is 0, read returns immediately, without trying | 146 | /* "If timeout is 0, read returns immediately, without trying |
144 | * to read any data. The exit status is 0 if input is available | 147 | * to read any data. The exit status is 0 if input is available |
145 | * on the specified file descriptor, non-zero otherwise." | 148 | * on the specified file descriptor, non-zero otherwise." |
@@ -150,6 +153,9 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
150 | r = poll(pfd, 1, /*timeout:*/ 0); | 153 | r = poll(pfd, 1, /*timeout:*/ 0); |
151 | /* Return 0 only if poll returns 1 ("one fd ready"), else return 1: */ | 154 | /* Return 0 only if poll returns 1 ("one fd ready"), else return 1: */ |
152 | return (const char *)(uintptr_t)(r <= 0); | 155 | return (const char *)(uintptr_t)(r <= 0); |
156 | #else | ||
157 | return (const char *)(uintptr_t)(1); | ||
158 | #endif | ||
153 | } | 159 | } |
154 | 160 | ||
155 | if (opt_p && isatty(fd)) { | 161 | if (opt_p && isatty(fd)) { |
@@ -160,6 +166,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
160 | if (ifs == NULL) | 166 | if (ifs == NULL) |
161 | ifs = defifs; | 167 | ifs = defifs; |
162 | 168 | ||
169 | #if !ENABLE_PLATFORM_MINGW32 | ||
163 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { | 170 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { |
164 | tcgetattr(fd, &tty); | 171 | tcgetattr(fd, &tty); |
165 | old_tty = tty; | 172 | old_tty = tty; |
@@ -182,6 +189,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
182 | * Ignoring, it's harmless. */ | 189 | * Ignoring, it's harmless. */ |
183 | tcsetattr(fd, TCSANOW, &tty); | 190 | tcsetattr(fd, TCSANOW, &tty); |
184 | } | 191 | } |
192 | #endif | ||
185 | 193 | ||
186 | retval = (const char *)(uintptr_t)0; | 194 | retval = (const char *)(uintptr_t)0; |
187 | startword = 1; | 195 | startword = 1; |
@@ -211,12 +219,12 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
211 | } | 219 | } |
212 | } | 220 | } |
213 | 221 | ||
222 | #if !ENABLE_PLATFORM_MINGW32 | ||
214 | /* We must poll even if timeout is -1: | 223 | /* We must poll even if timeout is -1: |
215 | * we want to be interrupted if signal arrives, | 224 | * we want to be interrupted if signal arrives, |
216 | * regardless of SA_RESTART-ness of that signal! | 225 | * regardless of SA_RESTART-ness of that signal! |
217 | */ | 226 | */ |
218 | errno = 0; | 227 | errno = 0; |
219 | #if !ENABLE_PLATFORM_MINGW32 | ||
220 | pfd[0].events = POLLIN; | 228 | pfd[0].events = POLLIN; |
221 | if (poll(pfd, 1, timeout) <= 0) { | 229 | if (poll(pfd, 1, timeout) <= 0) { |
222 | /* timed out, or EINTR */ | 230 | /* timed out, or EINTR */ |
@@ -224,12 +232,36 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
224 | retval = (const char *)(uintptr_t)1; | 232 | retval = (const char *)(uintptr_t)1; |
225 | goto ret; | 233 | goto ret; |
226 | } | 234 | } |
227 | #endif | ||
228 | if (read(fd, &buffer[bufpos], 1) != 1) { | 235 | if (read(fd, &buffer[bufpos], 1) != 1) { |
229 | err = errno; | 236 | err = errno; |
230 | retval = (const char *)(uintptr_t)1; | 237 | retval = (const char *)(uintptr_t)1; |
231 | break; | 238 | break; |
232 | } | 239 | } |
240 | #else | ||
241 | errno = 0; | ||
242 | if (isatty(fd) && (opt_n || opt_d || opt_t)) { | ||
243 | int64_t key; | ||
244 | |||
245 | key = read_key(fd, NULL, timeout); | ||
246 | if (key == 0x03 || key == -1) { | ||
247 | /* ^C or timeout */ | ||
248 | retval = (const char *)(uintptr_t)1; | ||
249 | goto ret; | ||
250 | } | ||
251 | buffer[bufpos] = key == '\r' ? '\n' : key; | ||
252 | if (!(read_flags & BUILTIN_READ_SILENT)) { | ||
253 | /* echo input if not in silent mode */ | ||
254 | putchar(buffer[bufpos]); | ||
255 | } | ||
256 | } | ||
257 | else { | ||
258 | if (read(fd, &buffer[bufpos], 1) != 1) { | ||
259 | err = errno; | ||
260 | retval = (const char *)(uintptr_t)1; | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | #endif | ||
233 | 265 | ||
234 | c = buffer[bufpos]; | 266 | c = buffer[bufpos]; |
235 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) | 267 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) |
@@ -297,8 +329,10 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
297 | 329 | ||
298 | ret: | 330 | ret: |
299 | free(buffer); | 331 | free(buffer); |
332 | #if !ENABLE_PLATFORM_MINGW32 | ||
300 | if (read_flags & BUILTIN_READ_SILENT) | 333 | if (read_flags & BUILTIN_READ_SILENT) |
301 | tcsetattr(fd, TCSANOW, &old_tty); | 334 | tcsetattr(fd, TCSANOW, &old_tty); |
335 | #endif | ||
302 | 336 | ||
303 | errno = err; | 337 | errno = err; |
304 | return retval; | 338 | return retval; |