Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I want to construct the STDIN for a program that I call with the "system" command. I am working on perl 5.8.0.

I've put an idiot version of the code below (Notice the print in the middle.)

use strict; # Read all the data from STDIN in the $buffer variable my $buffer = do { local $/; <STDIN> }; #Do a subtitution. $buffer =~s/essage/assage/sg; # Put $buffer back in STDIN so our system call can read it. # DOES NOT WORK. print STDIN "$buffer"; # Call our second program. unshift(ARGV,"printout.pl"); unshift(ARGV,"perl"); system @ARGV;
Any help would be appreciated.

Replies are listed 'Best First'.
Re: Constructing STDIN for an external progam
by Ovid (Cardinal) on Sep 11, 2006 at 12:02 UTC

    You want to read perlopentut. That should answer your questions. Specifically, I think you don't want system but instead want to open the external command with a leading pipe.

    open(PRINTER, "| lpr -Plp1") || die "can't run lpr: $!"; print PRINTER "stuff\n"; close(PRINTER) || die "can't close lpr: $!";

    However, you'll also want to read perlsec.

    Cheers,
    Ovid

    New address of my CGI Course.

      To build on Ovid's response, this should do what you want:
      use strict; my $cmdout = join " ", "perl printout.pl", @ARGV; open OUT, "|$cmdout" or die "Cannot run $cmdout: $!\n"; while (<STDIN>) { s/essage/assage/sg; print OUT $_ or die "Error writing to $cmdout: $!\n"; } close STDIN; close OUT or die "Error closing $cmdout: $!\n";
        What if one of the args was two words? or it's? Your code won't work in those everyday situations, nevermind the security implications. You've invoking the shell without quoting and escaping your command. Use IPC::Open3, IPC::Run or IPC::Run3 to avoid having to do so.
Re: Constructing STDIN for an external progam
by xdg (Monsignor) on Sep 11, 2006 at 14:33 UTC

    I strongly suggest looking into IPC::Run3. For this purpose, it replaces "system" and has some nice syntax for supplying STDIN or capturing STDOUT/STDERR. It's also very portable.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Constructing STDIN for an external progam
by davorg (Chancellor) on Sep 11, 2006 at 12:04 UTC

    Yeah, printing to a read-only filehandle isn't going to work :-)

    How about redirecting the second program's STDIN so that it reads from your data. Something like this (untested).

    # Read all the data from STDIN in the $buffer variable my $buffer = do { local $/; <STDIN> }; #Do a subtitution. $buffer =~s/essage/assage/sg; system("echo $buffer | perl printout.pl");

    Update: Or what Ovid said. Much better idea.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg