From abf2460f02e0651605b060c82000a07f0defa99b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 15 Aug 2026 09:42:00 +0300 Subject: [PATCH] cdba: read stdin even when it is not a tty Driving cdba from a script -- a fifo or a pipe on stdin -- silently does nothing. The board boots, the console output arrives as usual, but every keystroke written to stdin is discarded without an error or a warning, so it looks like the board is ignoring input rather than like cdba never sending it. tty_unbuffer() returns NULL when stdin is not a tty, which commit 7c12435aae39 ("cdba: Gracefully handle stdin not being a tty") introduced precisely so that cdba stays usable when launched from cron and friends. The select loop, however, uses that same pointer to decide whether to watch stdin at all: if (orig_tios) { FD_SET(STDIN_FILENO, &rfds); nfds = MAX(nfds, STDIN_FILENO); } so a non-tty stdin is never added to the read set and never read. The pointer answers "did we change the termios, and must we restore it", which is not the same question as "can we read stdin", and conflating the two undoes the graceful handling it was meant to preserve. Track the two separately: always watch stdin, and stop watching it once it reports EOF or an error. The latter matters because a closed pipe stays readable forever, and without unregistering it select() would spin. Tested against a DB820c through a plain fifo with stdout redirected to a file and no pty anywhere: the login and the commands that follow now reach the console. Fixes: 1e92a38df167 ("cdba: Make exit code reflect exit cause") Assisted-by: Claude:claude-opus-5 Signed-off-by: Dmitry Baryshkov --- cdba.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cdba.c b/cdba.c index a3343d0..881dc2d 100644 --- a/cdba.c +++ b/cdba.c @@ -501,7 +501,7 @@ static int tty_callback(int *ssh_fds) ssize_t n; n = read(STDIN_FILENO, buf, sizeof(buf)); - if (n < 0) + if (n <= 0) return n; for (k = 0; k < n; k++) { @@ -553,7 +553,7 @@ static int tty_callback(int *ssh_fds) } } - return 0; + return n; } /** @@ -909,6 +909,7 @@ int main(int argc, char **argv) struct timeval timeout_total_tv; struct timeval *timeout = NULL; struct termios *orig_tios; + bool watch_stdin = true; const char *server_binary = "cdba-server"; const char *status_pipe = NULL; bool bump_inactivity_timer; @@ -1054,7 +1055,7 @@ int main(int argc, char **argv) FD_SET(ssh_fds[2], &rfds); nfds = MAX(ssh_fds[1], ssh_fds[2]); - if (orig_tios) { + if (watch_stdin) { FD_SET(STDIN_FILENO, &rfds); nfds = MAX(nfds, STDIN_FILENO); @@ -1092,8 +1093,10 @@ int main(int argc, char **argv) bump_inactivity_timer = false; - if (FD_ISSET(STDIN_FILENO, &rfds)) - tty_callback(ssh_fds); + if (watch_stdin && FD_ISSET(STDIN_FILENO, &rfds)) { + if (tty_callback(ssh_fds) <= 0) + watch_stdin = false; + } if (FD_ISSET(ssh_fds[2], &rfds)) { n = read(ssh_fds[2], buf, sizeof(buf));