diff options
| author | Ron Yorston <rmy@pobox.com> | 2025-06-29 13:33:24 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2025-06-29 13:33:24 +0100 |
| commit | e07a73a1502b0aba8fde7d9e491a3f8cc42dc341 (patch) | |
| tree | bc75937c8c23ddb986fc20a15748371b7bb621d8 /shell | |
| parent | b9fa01c547dc09ff26cb45d8c54cd2c5c5701142 (diff) | |
| download | busybox-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.c | 7 | ||||
| -rw-r--r-- | shell/shell_common.c | 26 |
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(¶ms); | 15812 | r = shell_builtin_read(¶ms); |
| 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; |
