shell: improve bash compatibility of read built-in
No binary (build failed)
—
(log yok)
| @@ -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); | |
| @@ -0,0 +1,9 @@ | |
| + | |X|Y:Z:| |
| + | |X|Y:Z| |
| + | |X|Y| |
| + | |X|Y| |
| + | |X|| |
| + | |X|| |
| + | ||| |
| + | Whitespace should be trimmed too: |
| + | |X|Y| |
| @@ -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|") |
| @@ -1,4 +1,4 @@ | |
| - | >< |
| - | >< |
| - | >test< |
| - | >test< |
| + | >te:142< |
| + | >:142< |
| + | >test:0< |
| + | >test:0< |
| @@ -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:$?<") |
| @@ -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; | |
| @@ -27,7 +27,7 @@ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| - | void strprint(); |
| + | void strprint(char *); |
| int main(int argc, char **argv) | |
| { | |
| @@ -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; | |
| @@ -1,4 +1,4 @@ | |
| - | >< |
| - | >< |
| - | >test< |
| - | >test< |
| + | >te:142< |
| + | >:142< |
| + | >test:0< |
| + | >test:0< |
| @@ -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:$?<") |
| @@ -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; | |
| } | |