Make the read built-in more compatible with bash:
- Return an exit code of 142 on timeout.
- When the timeout expires before a newline is detected in the
input bash captures the partial input. This behaviour is new
since bash version 4.4. BusyBox shells had the pre-4.4 behaviour
where the input was lost.
Update the tests to suit and fix a couple of compiler errors in
the testsuite.
function old new delta
builtin_read 154 174 +20
readcmd 213 228 +15
shell_builtin_read 1364 1370 +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 41/0) Total: 41 bytes
v2: Check for errors other than EINTR. Thanks to Harald van Dijk
for pointing out my misplaced faith in comments.
Signed-off-by: Ron Yorston <[email protected]>
---
shell/ash.c | 3 +++
shell/ash_test/ash-read/read_t.right | 8 ++++----
shell/ash_test/ash-read/read_t.tests | 18 +++++++++---------
shell/ash_test/printenv.c | 4 +---
shell/ash_test/recho.c | 2 +-
shell/hush.c | 3 +++
shell/shell_common.c | 10 +++++++---
7 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/shell/ash.c b/shell/ash.c
index 9173b8608..60b782e41 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -14395,6 +14395,9 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
goto again;
}
+ if ((uintptr_t)r == 2)
+ return 128 + SIGALRM;
+
if ((uintptr_t)r > 1)
ash_msg_and_raise_error(r);
diff --git a/shell/ash_test/ash-read/read_t.right
b/shell/ash_test/ash-read/read_t.right
index 04126cbe6..3eedae275 100644
--- a/shell/ash_test/ash-read/read_t.right
+++ b/shell/ash_test/ash-read/read_t.right
@@ -1,4 +1,4 @@
-><
-><
->test<
->test<
+>te:142<
+>:142<
+>test:0<
+>test:0<
diff --git a/shell/ash_test/ash-read/read_t.tests
b/shell/ash_test/ash-read/read_t.tests
index d65f1aeaa..9fbeec517 100755
--- a/shell/ash_test/ash-read/read_t.tests
+++ b/shell/ash_test/ash-read/read_t.tests
@@ -1,10 +1,10 @@
-# bash 3.2 outputs:
+# bash 5.2 outputs:
-# ><
-{ echo -n 'te'; sleep 2; echo 'st'; } | (read -t 1 reply; echo ">$reply<")
-# ><
-{ sleep 2; echo 'test'; } | (read -t 1 reply; echo ">$reply<")
-# >test<
-{ echo -n 'te'; sleep 1; echo 'st'; } | (read -t 2 reply; echo ">$reply<")
-# >test<
-{ sleep 1; echo 'test'; } | (read -t 2 reply; echo ">$reply<")
+# >te:142<
+{ echo -n 'te'; sleep 2; echo 'st'; } | (read -t 1 reply; echo ">$reply:$?<")
+# >:142<
+{ sleep 2; echo 'test'; } | (read -t 1 reply; echo ">$reply:$?<")
+# >test:0<
+{ echo -n 'te'; sleep 1; echo 'st'; } | (read -t 2 reply; echo ">$reply:$?<")
+# >test:0<
+{ sleep 1; echo 'test'; } | (read -t 2 reply; echo ">$reply:$?<")
diff --git a/shell/ash_test/printenv.c b/shell/ash_test/printenv.c
index c86308d3b..f0f41984d 100644
--- a/shell/ash_test/printenv.c
+++ b/shell/ash_test/printenv.c
@@ -31,9 +31,7 @@
extern char **environ;
int
-main (argc, argv)
- int argc;
- char **argv;
+main (int argc, char **argv)
{
register char **envp, *eval;
int len;
diff --git a/shell/ash_test/recho.c b/shell/ash_test/recho.c
index 42a5feafd..7e96b14cc 100644
--- a/shell/ash_test/recho.c
+++ b/shell/ash_test/recho.c
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-void strprint();
+void strprint(char *);
int main(int argc, char **argv)
{
diff --git a/shell/hush.c b/shell/hush.c
index 4a97293cc..9f94bfdec 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -11175,6 +11175,9 @@ static int FAST_FUNC builtin_read(char **argv)
goto again;
}
+ if ((uintptr_t)r == 2)
+ return 128 + SIGALRM;
+
if ((uintptr_t)r > 1) {
bb_simple_error_msg(r);
r = (char*)(uintptr_t)1;
diff --git a/shell/shell_common.c b/shell/shell_common.c
index e5c2cefb3..9a03f7265 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -204,8 +204,8 @@ shell_builtin_read(struct builtin_read_params *params)
* 32-bit unix time wrapped (year 2038+).
*/
if (timeout <= 0) { /* already late? */
- retval = (const char *)(uintptr_t)1;
- goto ret;
+ retval = (const char *)(uintptr_t)2;
+ break;
}
}
@@ -217,8 +217,12 @@ shell_builtin_read(struct builtin_read_params *params)
pfd[0].events = POLLIN;
//TODO race with a signal arriving just before the poll!
if (poll(pfd, 1, timeout) <= 0) {
- /* timed out, or EINTR */
+ /* timed out, or some error */
err = errno;
+ if (!err) {
+ retval = (const char *)(uintptr_t)2;
+ break;
+ }
retval = (const char *)(uintptr_t)1;
goto ret;
}
--
2.50.0
_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox