← Commit list

dcd8df258

Ron Yorston
Ron Yorston
2025-07-01
SUCCESS Duration: 156s

Subject

shell: improve bash compatibility of read built-in

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

shell/ash.c+5 -0
@@ -14395,6 +14395,11 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
goto again;
}
+ if ((uintptr_t)r == 2) /* -t SEC timeout? */
+ /* bash: "The exit status is greater than 128 if the timeout is exceeded." */
+ /* The actual value observed with bash 5.2.15: */
+ return 128 + SIGALRM;
+
if ((uintptr_t)r > 1)
ash_msg_and_raise_error(r);
shell/ash_test/ash-read/read_ifs2.right+9 -0
@@ -0,0 +1,9 @@
+|X|Y:Z:|
+|X|Y:Z|
+|X|Y|
+|X|Y|
+|X||
+|X||
+|||
+Whitespace should be trimmed too:
+|X|Y|
shell/ash_test/ash-read/read_ifs2.tests+9 -0
@@ -0,0 +1,9 @@
+echo "X:Y:Z:" | (IFS=": " read x y; echo "|$x|$y|")
+echo "X:Y:Z" | (IFS=": " read x y; echo "|$x|$y|")
+echo "X:Y:" | (IFS=": " read x y; echo "|$x|$y|")
+echo "X:Y" | (IFS=": " read x y; echo "|$x|$y|")
+echo "X:" | (IFS=": " read x y; echo "|$x|$y|")
+echo "X" | (IFS=": " read x y; echo "|$x|$y|")
+echo "" | (IFS=": " read x y; echo "|$x|$y|")
+echo Whitespace should be trimmed too:
+echo "X:Y : " | (IFS=": " read x y; echo "|$x|$y|")
shell/ash_test/ash-read/read_t.right+4 -4
@@ -1,4 +1,4 @@
-><
-><
->test<
->test<
+>te:142<
+>:142<
+>test:0<
+>test:0<
shell/ash_test/ash-read/read_t.tests+9 -9
@@ -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:$?<")
shell/ash_test/printenv.c+1 -3
@@ -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;
shell/ash_test/recho.c+1 -1
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-void strprint();
+void strprint(char *);
int main(int argc, char **argv)
{
shell/hush.c+5 -0
@@ -11175,6 +11175,11 @@ static int FAST_FUNC builtin_read(char **argv)
goto again;
}
+ if ((uintptr_t)r == 2) /* -t SEC timeout? */
+ /* bash: "The exit status is greater than 128 if the timeout is exceeded." */
+ /* The actual value observed with bash 5.2.15: */
+ return 128 + SIGALRM;
+
if ((uintptr_t)r > 1) {
bb_simple_error_msg(r);
r = (char*)(uintptr_t)1;
shell/hush_test/hush-read/read_t.right+4 -4
@@ -1,4 +1,4 @@
-><
-><
->test<
->test<
+>te:142<
+>:142<
+>test:0<
+>test:0<
shell/hush_test/hush-read/read_t.tests+9 -9
@@ -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:$?<")
shell/shell_common.c+7 -3
@@ -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;
}