aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-04-05 15:16:37 +0100
committerRon Yorston <rmy@pobox.com>2018-04-05 15:32:49 +0100
commitaf122fe83fcdeb47173459715d39a5fe887a406e (patch)
tree7be50dbc074d3d73bcbe41a978e850aed90781ba
parent91ee3425d1d39a86eb0a3460d9f14e57c24e0b83 (diff)
downloadbusybox-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.c38
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;