diff --git a/usr.bin/script/script.1 b/usr.bin/script/script.1 index 3aa03e55e279..cd3f800c051d 100644 --- a/usr.bin/script/script.1 +++ b/usr.bin/script/script.1 @@ -166,3 +166,12 @@ The slave terminal mode is checked for ECHO mode to check when to avoid manual echo logging. This does not work when in a raw mode where the program being run is doing manual echo. +.Pp +If the +.Nm +reads zero bytes from the terminal it switches to a mode when it probes read +only once a second until it gets some data. +This prevents the +.Nm +spinning on zero-byte reads, but might cause a 1-second delay in +processing of the user input. diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c index ad9972170bc1..ea5a1f6ca04f 100644 --- a/usr.bin/script/script.c +++ b/usr.bin/script/script.c @@ -86,6 +86,7 @@ main(int argc, char *argv[]) char ibuf[BUFSIZ]; fd_set rfd; int flushtime = 30; + int readstdin; aflg = kflg = 0; while ((ch = getopt(argc, argv, "aqkt:")) != -1) @@ -155,19 +156,21 @@ main(int argc, char *argv[]) doshell(argv); close(slave); - if (flushtime > 0) - tvp = &tv; - else - tvp = NULL; - - start = time(0); - FD_ZERO(&rfd); + start = tvec = time(0); + readstdin = 1; for (;;) { + FD_ZERO(&rfd); FD_SET(master, &rfd); - FD_SET(STDIN_FILENO, &rfd); - if (flushtime > 0) { - tv.tv_sec = flushtime; + if (readstdin) + FD_SET(STDIN_FILENO, &rfd); + if ((!readstdin && ttyflg) || flushtime > 0) { + tv.tv_sec = !readstdin && ttyflg ? 1 : + flushtime - (tvec - start); tv.tv_usec = 0; + tvp = &tv; + readstdin = 1; + } else { + tvp = NULL; } n = select(master + 1, &rfd, 0, 0, tvp); if (n < 0 && errno != EINTR) @@ -176,8 +179,13 @@ main(int argc, char *argv[]) cc = read(STDIN_FILENO, ibuf, BUFSIZ); if (cc < 0) break; - if (cc == 0) - (void)write(master, ibuf, 0); + if (cc == 0) { + if (tcgetattr(master, &stt) == 0 && + (stt.c_lflag & ICANON) != 0) { + (void)write(master, &stt.c_cc[VEOF], 1); + } + readstdin = 0; + } if (cc > 0) { (void)write(master, ibuf, cc); if (kflg && tcgetattr(master, &stt) >= 0 &&