[repost] Patch to make cpdup's stdout unbuffered

Chris Pressey cpressey at catseye.mine.nu
Tue Jun 8 15:21:01 PDT 2004


On Tue, 8 Jun 2004 23:34:15 +0200
Simon 'corecode' Schubert <corecode at xxxxxxxxxxxx> wrote:

> On 08.06.2004, at 23:02, Chris Pressey wrote:
> 
> > The installer popen()'s "cpdup -vvv src dest" and it reads from this
> > pipe to monitor cpdup's progress.  Unfortunately, since cpdup's
> > output is fully buffered, cpdup's progress can't be usefully
> > measured this way.
> > This patch simply gives us a way to make cpdup's output unbuffered,
> > so we can get it through the pipe as cpdup generates it.
> 
> As I wrote some months ago: this is a thing a lot of programs could
> use (sed, awk, grep etc IIRC)
> 
> 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?

The man pages make it sound a bit like this is already possible, but I
can't figure out how to do it.

man 2 execve:

"File descriptors open in the calling process image remain open in the
new process image, except for those for which the close-on-exec flag is
set (see close(2) and fcntl(2)).  Descriptors that remain open are
unaffected by execve()."

man 2 close:

"For this reason, the call ``fcntl(d, F_SETFD, 1)'' is provided, which
arranges that a descriptor will be closed after a successful execve;
the call ``fcntl(d, F_SETFD, 0)'' restores the default, which is to not
close the descriptor."

So by the sounds of it, the attached program should be able to run
another program, forcing that other program's stdout to be unbufferred. 
But in (a small amount of) testing, I couldn't seem to get that
behaviour.

It's possible that libc unconditionally sets the output to fully
bufferred in the prologue code, in which case it might be a simple
matter of making that conditional on something, then using a little hack
like the attached program.  I'll look at the libc startup code a little
later.

-Chris
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

extern char **environ;

int
main(int argc, char **argv)
{
	setvbuf(stdout, NULL, _IONBF, 0);
	fcntl(STDOUT_FILENO, F_SETFD, 0);
	execve(argv[1], &argv[1], environ);
}




More information about the Submit mailing list