[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