On Sun, 18 Sep 2011 20:24:23 +0300 Kostik Belousov wrote:

 KB> On Sun, Sep 18, 2011 at 02:54:34PM +0300, Mikolaj Golub wrote:
 >> 
 >> On Sun, 18 Sep 2011 13:25:26 +0200 Ronald Klop wrote:
 >> 
 >>  RK> It is a while since I programmed C, but why will writing 0 bytes give
 >>  RK> the reader an end-of-file? Shouldn't the fd be closed to indicate
 >>  RK> end-of-file?
 >> 
 >> AFAIR, this trick with writing 0 to emulate EOF because we can't close the 
 >> fd
 >> -- we still want to read from it.  Poor shutdown(2) for non-socket :-).
 >> 
 >> Colin might tell more...

 KB> Please note that interpreting the receiving of 0 bytes on the terminal 
 KB> as EOF is only a convention. If done absolutely properly, script shall
 KB> not interpret zero-byte read as EOF. Might be, the reasonable thing to
 KB> do would be to only look at the stdin once in a second after receiving
 KB> zero-bytes, and switching it back to normal mode if something is read.

Ok. I see. Below is the patch that does something like this.

-- 
Mikolaj Golub

Index: usr.bin/script/script.c
===================================================================
--- usr.bin/script/script.c	(revision 225653)
+++ usr.bin/script/script.c	(working copy)
@@ -53,6 +53,7 @@ static const char sccsid[] = "@(#)script.c	8.1 (Be
 #include <libutil.h>
 #include <paths.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -86,6 +87,7 @@ main(int argc, char *argv[])
 	char ibuf[BUFSIZ];
 	fd_set rfd;
 	int flushtime = 30;
+	bool readstdin;
 
 	aflg = kflg = 0;
 	while ((ch = getopt(argc, argv, "aqkt:")) != -1)
@@ -155,19 +157,20 @@ 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 = true;
 	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 || flushtime > 0) {
+			tv.tv_sec = !readstdin ? 1 : flushtime - (tvec - start);
 			tv.tv_usec = 0;
+			tvp = &tv;
+			readstdin = true;
+		} else {
+			tvp = NULL;
 		}
 		n = select(master + 1, &rfd, 0, 0, tvp);
 		if (n < 0 && errno != EINTR)
@@ -176,8 +179,10 @@ main(int argc, char *argv[])
 			cc = read(STDIN_FILENO, ibuf, BUFSIZ);
 			if (cc < 0)
 				break;
-			if (cc == 0)
+			if (cc == 0) {
 				(void)write(master, ibuf, 0);
+				readstdin = false;
+			}
 			if (cc > 0) {
 				(void)write(master, ibuf, cc);
 				if (kflg && tcgetattr(master, &stt) >= 0 &&
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"

Reply via email to