[Santa-rosa-pm] Launching child processes with STDERR redirection

Geoffrey Broadwell geoff at broadwell.org
Sat Dec 29 14:30:17 PST 2007


I keep forgetting to post this, and Bob's post reminded me.  The code
below launches a child process while capturing both STDOUT and STDERR
*without* using shell redirections.  This allows the list form of exec()
to be used, thus improving security and correctness.

Both routines die if the piped open (fork) or exec fails.  Otherwise,
they return either the pipe filehandle alone, or the pipe filehandle and
the child's process ID, depending on calling context.

The difference between the two routines is that one returns a filehandle
that expects to be read from, and the other expects to be written to.
Code-wise it's only swapping two characters in the open() call, so I
could have just made a single routine with a special argument choosing
pipe mode.  Instead, I made two separate routines so that calling code
can be a little cleaner and self-documenting:

    my $pipe = pipe_from_command(@command_and_args);
    while (<$pipe>) { ... }

    my $slave = pipe_to_command(@command_and_args);
    print $slave "Bow before me!\n";

Anyway, here's the code:

#######

sub pipe_from_command {
    my $pid = open my $pipe, '-|';
    die "Could not fork: $!" unless defined $pid;

    unless ($pid) {
        open STDERR, ">&STDOUT";
        exec @_ or die "Could not exec: $!";
    }

    return wantarray ? ($pipe, $pid) : $pipe;
}

sub pipe_to_command {
    my $pid = open my $pipe, '|-';
    die "Could not fork: $!" unless defined $pid;

    unless ($pid) {
        open STDERR, ">&STDOUT";
        exec @_ or die "Could not exec: $!";
    }

    return wantarray ? ($pipe, $pid) : $pipe;
}

#######


-'f




More information about the Santa-rosa-pm mailing list