aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2025-06-29 13:33:24 +0100
committerRon Yorston <rmy@pobox.com>2025-06-29 13:33:24 +0100
commite07a73a1502b0aba8fde7d9e491a3f8cc42dc341 (patch)
treebc75937c8c23ddb986fc20a15748371b7bb621d8 /shell
parentb9fa01c547dc09ff26cb45d8c54cd2c5c5701142 (diff)
downloadbusybox-w32-e07a73a1502b0aba8fde7d9e491a3f8cc42dc341.tar.gz
busybox-w32-e07a73a1502b0aba8fde7d9e491a3f8cc42dc341.tar.bz2
busybox-w32-e07a73a1502b0aba8fde7d9e491a3f8cc42dc341.zip
ash: bring 'read' built-in closer to bash
Commit 8e6991733 (ash: fix 'read' shell built-in (1)) noted discrepancies between upstream BusyBox, busybox-w32 and bash. It aligned busybox-w32 with upstream BusyBox. Apply further changes in busybox-w32 to align 'read' more closely with bash. - When a timeout occurs before a newline in the input stream, capture and save the text collected so far. - Return an exit code of 142 on timeout. Also, since our implementation of poll(2) never sets errno to EINTR the code to handle this case can be omitted. Saves 16 bytes in the 64-bit build, adds 16 in 32-bit. (GitHub issue #502)
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c7
-rw-r--r--shell/shell_common.c26
2 files changed, 25 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 3919118f0..efb80dfe4 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -15812,6 +15812,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
15812 r = shell_builtin_read(&params); 15812 r = shell_builtin_read(&params);
15813 INT_ON; 15813 INT_ON;
15814 15814
15815#if !ENABLE_PLATFORM_MINGW32
15815 if ((uintptr_t)r == 1 && errno == EINTR) { 15816 if ((uintptr_t)r == 1 && errno == EINTR) {
15816 /* To get SIGCHLD: sleep 1 & read x; echo $x 15817 /* To get SIGCHLD: sleep 1 & read x; echo $x
15817 * Correct behavior is to not exit "read" 15818 * Correct behavior is to not exit "read"
@@ -15819,9 +15820,11 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
15819 if (pending_sig == 0) 15820 if (pending_sig == 0)
15820 goto again; 15821 goto again;
15821 } 15822 }
15822 15823#else /* ENABLE_PLATFORM_MINGW32 */
15823#if ENABLE_PLATFORM_MINGW32
15824 if ((uintptr_t)r == 2) { 15824 if ((uintptr_t)r == 2) {
15825 /* Timeout, return 128 + SIGALRM */
15826 return 142;
15827 } else if ((uintptr_t)r == 3) {
15825 /* ^C pressed, propagate event */ 15828 /* ^C pressed, propagate event */
15826 if (trap[SIGINT]) { 15829 if (trap[SIGINT]) {
15827 write(STDOUT_FILENO, "^C", 2); 15830 write(STDOUT_FILENO, "^C", 2);
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 7fb5f8c58..2a876acac 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -209,8 +209,13 @@ shell_builtin_read(struct builtin_read_params *params)
209 * 32-bit unix time wrapped (year 2038+). 209 * 32-bit unix time wrapped (year 2038+).
210 */ 210 */
211 if (timeout <= 0) { /* already late? */ 211 if (timeout <= 0) { /* already late? */
212#if ENABLE_PLATFORM_MINGW32
213 retval = (const char *)(uintptr_t)2;
214 break;
215#else
212 retval = (const char *)(uintptr_t)1; 216 retval = (const char *)(uintptr_t)1;
213 goto ret; 217 goto ret;
218#endif
214 } 219 }
215 } 220 }
216 221
@@ -228,8 +233,14 @@ shell_builtin_read(struct builtin_read_params *params)
228 if (poll(pfd, 1, timeout) <= 0) { 233 if (poll(pfd, 1, timeout) <= 0) {
229 /* timed out, or EINTR */ 234 /* timed out, or EINTR */
230 err = errno; 235 err = errno;
236#if ENABLE_PLATFORM_MINGW32
237 /* Windows poll(2) doesn't do EINTR, we timed out */
238 retval = (const char *)(uintptr_t)2;
239 break;
240#else
231 retval = (const char *)(uintptr_t)1; 241 retval = (const char *)(uintptr_t)1;
232 goto ret; 242 goto ret;
243#endif
233 } 244 }
234#if ENABLE_PLATFORM_MINGW32 245#if ENABLE_PLATFORM_MINGW32
235 if (isatty(fd)) { 246 if (isatty(fd)) {
@@ -238,15 +249,18 @@ shell_builtin_read(struct builtin_read_params *params)
238 key = windows_read_key(fd, NULL, timeout); 249 key = windows_read_key(fd, NULL, timeout);
239 if (key == 0x03) { 250 if (key == 0x03) {
240 /* ^C pressed */ 251 /* ^C pressed */
241 retval = (const char *)(uintptr_t)2; 252 retval = (const char *)(uintptr_t)3;
242 goto ret; 253 goto ret;
243 } 254 }
244 else if (key == -1 || (key == 0x1a && bufpos == 0)) { 255 else if (key == -1) {
245 /* timeout or ^Z at start of buffer */ 256 /* timeout */
257 retval = (const char *)(uintptr_t)2;
258 break;
259 } else if (key == 0x1a && bufpos == 0) {
260 /* ^Z at start of buffer */
246 retval = (const char *)(uintptr_t)1; 261 retval = (const char *)(uintptr_t)1;
247 goto ret; 262 break;
248 } 263 } else if (key == '\b') {
249 else if (key == '\b') {
250 if (bufpos > 0) { 264 if (bufpos > 0) {
251 --bufpos; 265 --bufpos;
252 ++nchars; 266 ++nchars;