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

Here is one that has been making me think...
I need to execute a system program within a script where I can supply data to stdin and get back a return value. Normally I'd just do the following:

$prog = "/var/qmail/bin/qmail-remote";
$msg = "this is the email message";
$value = system($prog);

But, the program expects data (a mail message) from STDIN. Since I have the data in $msg I could do:

$prog = "/var/qmail/bin/qmail-remote";
$msg = "this is the email message";
open (OUT, "|$prog");
print OUT $msg;
close(OUT);

but this doesn't give me the much needed return code. Do any of you knw the best way to run a system program in a way that I can supply STDIN data and see a return value? I'd rather not write $msg to a file and do:
system("cat $file | $prog");
Thanks Terry

Replies are listed 'Best First'.
Re: system(program) or open(
by stephen (Priest) on Apr 04, 2000 at 04:35 UTC
    You can use open() and get the return value from $?. If you check $? after the program closes, that should contain the return value. Well, kinda: from the entry for $? on the perlman:perlvar page:

    The status returned by the last pipe close, backtick (``) command, or system() operator. Note that this is the status word returned by the wait() system call (or else is made up to look like it). Thus, the exit value of the subprocess is actually ( $? >> 8), and $? & 127 gives which signal, if any, the process died from, and $? & 128 reports whether there was a core dump. (Mnemonic: similar to sh and ksh.)
    Check out perlfunc:open and perlman:perlipc for examples. Since you're writing to the pipe, then you'll probably want to install a handler for SIGPIPE signals, as well. So, your code could be:
    $SIG{PIPE} = sub { die "Your pipe handler here! $!"; }; $prog = "/var/qmail/bin/qmail-remote"; $msg = "this is the email message"; open (OUT, "|$prog") or die "Couldn't open Qmail: $!; stopped"; print OUT $msg; close(OUT) or die "Couldn't close Qmail: $! $?; stopped"; my $return_code = $? >> 8; print STDOUT "My return code was $return_code.\n";

    stephen

Re: system(program) or open(
by jbert (Priest) on Apr 04, 2000 at 14:15 UTC
    Yup. A coupla points

    Always test the result of a 'close' if the 'open' runs a program with the pipe character. Otherwise you have no idea if the program ran successfully.

    Why hard-code you script to run on a box with one particular email system installed. There is a perfectly fine Net::SMTP module out there which is dead easy to use.

    Just dive straight into your local SMTP port and acheive one-ness with the world.

    (OK, well, so you might want to run on a box which is send-only for SMTP, but hey)