[repost] Patch to make cpdup's stdout unbuffered

Chris Pressey cpressey at catseye.mine.nu
Tue Jun 8 20:12:30 PDT 2004


Whoops, attached the wrong patch.

The right one should be attached this time.

-Chris

On Tue, 8 Jun 2004 20:07:35 -0700
Chris Pressey <cpressey at xxxxxxxxxxxxxxx> wrote:

> On Tue, 8 Jun 2004 16:23:05 -0700 (PDT)
> Matthew Dillon <dillon at xxxxxxxxxxxxxxxxxxxx> wrote:
> 
> > :Now, we could add a flag for every single program to write unbuffered
> > :(linebuffered) output. Or we could do some (non-POSIX?) magic in libc
> > :to get most of this just fixed by doing a env 
> > :LIBC_STDOUT_BUFFERING=line $program or whatever...
> > :
> > :opinions about this?
> > :
> > :cheers
> > :   simon
> >  
> >     Say what?  No, we are not hacking up libc to turn off buffering in
> >     some magic way.  Buffering is what you want for the vast, vast
> >     majority of programs that are run from the command line.  We
> >     certainly are not going to add yet another environment variable
> >     that libc has to check every time a program is started up.
> > 
> >     Just add an option to cpdup that calls setvbuf() on stdout.
> 
> I'll take that as a green light to commit the previously posted cpdup
> patch.
> 
> However, I think I just discovered a potential general solution.  I
> strongly suspected there would be a way to do it with standard BSD
> mechanisms, and lo and behold there is a userland utility already set up
> to exploit those mechanisms.  On FreeBSD 4.9, try popen()'ing:
> 
>   script -q /dev/null your_favourite_program_with_buffered_output
> 
> According to my testing, the result should be unbuffered.  This is
> thanks to a fairly recent MFC to script(1) which allows its stdin/out
> to be something other than a terminal.  I've ported the MFC - it's
> attached to this e-mail - and I'd like to commit it pending review.
> 
> However, there still seem to be some small issues with combining
> script(1) and popen().  Namely, when the pipe is forcefully pclose()'ed,
> the script(1) process exits, but the cpdup process doesn't :(  So until
> that's sorted out, I'll stick with cpdup -u in the installer.
> 
> -Chris
> 

Index: usr.bin/script/script.c
===================================================================
RCS file: /home/dcvs/src/usr.bin/script/script.c,v
retrieving revision 1.4
diff -u -r1.4 script.c
--- usr.bin/script/script.c	28 Mar 2004 01:02:54 -0000	1.4
+++ usr.bin/script/script.c	9 Jun 2004 02:37:00 -0000
@@ -32,7 +32,7 @@
  *
  * @(#) Copyright (c) 1980, 1992, 1993 The Regents of the University of California.  All rights reserved.
  * @(#)script.c	8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.bin/script/script.c,v 1.11.2.1 2000/07/20 10:35:21 kris Exp $
+ * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/usr.bin/script/script.c,v 1.11.2.2 2004/03/13 09:21:00 cperciva Exp $
  * $DragonFly: src/usr.bin/script/script.c,v 1.4 2004/03/28 01:02:54 cpressey Exp $
  */
 
@@ -58,7 +58,7 @@
 int	master, slave;
 int	child;
 char	*fname;
-int	qflg;
+int	qflg, ttyflg;
 
 struct	termios tt;
 
@@ -118,10 +118,17 @@
 	if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
 		err(1, "%s", fname);
 
-	tcgetattr(STDIN_FILENO, &tt);
-	ioctl(STDIN_FILENO, TIOCGWINSZ, &win);
-	if (openpty(&master, &slave, NULL, &tt, &win) == -1)
-		err(1, "openpty");
+	if (ttyflg = isatty(STDIN_FILENO)) {
+		if (tcgetattr(STDIN_FILENO, &tt) == -1)
+			err(1, "tcgetattr");
+		if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1)
+			err(1, "ioctl");
+		if (openpty(&master, &slave, NULL, &tt, &win) == -1)
+			err(1, "openpty");
+	} else {
+		if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
+			err(1, "openpty");
+	}
 
 	if (!qflg) {
 		tvec = time(NULL);
@@ -129,10 +136,13 @@
 		fprintf(fscript, "Script started on %s", ctime(&tvec));
 		fflush(fscript);
 	}
-	rtt = tt;
-	cfmakeraw(&rtt);
-	rtt.c_lflag &= ~ECHO;
-	tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+
+	if (ttyflg) {
+		rtt = tt;
+		cfmakeraw(&rtt);
+		rtt.c_lflag &= ~ECHO;
+		tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+	}
 
 	child = fork();
 	if (child < 0) {
@@ -161,8 +171,10 @@
 			break;
 		if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
 			cc = read(STDIN_FILENO, ibuf, sizeof(ibuf));
-			if (cc <= 0)
+			if (cc < 0)
 				break;
+			if (cc == 0)
+				write(master, ibuf, 0);
 			if (cc > 0) {
 				write(master, ibuf, cc);
 				if (kflg && tcgetattr(master, &stt) >= 0 &&
@@ -252,7 +264,8 @@
 {
 	time_t tvec;
 
-	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
+	if (ttyflg)
+		tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
 	tvec = time(NULL);
 	if (!qflg) {
 		fprintf(fscript,"\nScript done on %s", ctime(&tvec));




More information about the Submit mailing list