system($command) will print $command's STDERR to your STDERR and $command's STDOUT to 
your STDOUT.  Apache's error log contains the STDERR output of the scripts you run 
through the webserver, so if you want system($command)'s STDERR output to show up in 
the browser, just redirect STDERR to STDOUT: system($command 2>&1).

If you would like to be able to know if the system call was successful (which you can 
do based on system's return code) and collect the output of an external command (which 
you can do with backticks ($output =  `$command`) all in one command, you can use a 
subroutine similar to the one below.  (Unfortunately, neither system or backticks can 
do both.  I assume this is what system2() does, but I haven't had a chance to look).

It redirects STDOUT and STDERR to a tempfile, system()'s the arguments, collects the 
output from the tempfile, and returns the output from the command if the system() was 
successful, or dies with the output as an argument if the system() was unsuccessful.  
I'm not sure how robust it is, but it works on Windows and Unix.  I use it all the 
time.  I got the idea from some Perl book.

eval { $output = system_with_out($command) };

if ($@) {
   # do something with error
}

Jon


sub system_with_out {
  my @args = @_;

  # create dups of STDOUT and STDERR
  open SAVEOUT, ">&STDOUT"     or confess "Couldn't open dup of STDOUT: $!";
  open SAVEERR, ">&STDERR"     or confess "Couldn't open dup of STDERR: $!";

  # system output and error will go to $tmpfile
  my $tmpfile;
  do {
    $tmpfile = tmpnam();
  } until sysopen(STDOUT, $tmpfile, O_WRONLY | O_EXCL | O_CREAT);

  # alias STDERR to STDOUT
  *STDERR = *STDOUT;

  # run the command
  if(system(@args) != 0) {       
    # don't confess until we get stdout and stderr back and cleanup
    open TMP, $tmpfile;
    my @return = <TMP>;
    close TMP;

    unlink $tmpfile;
    open STDOUT, ">&SAVEOUT";
    open STDERR, ">&SAVEERR";
    confess "Error: @args: @return";
  }
    
  # restore STDOUT and STDERR
  open STDOUT, ">&SAVEOUT"     or confess "Couldn't open STDOUT as dup of SAVEOUT: $!";
  open STDERR, ">&SAVEERR"     or confess "Couldn't open STDERR as dup of SAVEERR: $!";

  # get system output
  open TMP, $tmpfile        close SAVEOUT; close SAVEERR; # prevent warnings
  my @return = <TMP>;
  close TMP;
  unlink $tmpfile              or confess "Couldn't delete $tmpfile: $!";

  close SAVEOUT; close SAVEERR; # prevent warnings

  return wantarray ? @return : join "" => @return;
}





Hi all,

I have a situation where I need to exec a command-line based perl 
program from a CGI wrapper.  I want to do this safely, but I also 
want to see the same output from the command line program in the
browser that I would normally.

I'm not quite sure how I should go about doing this, and have it safe 
as well.  I'm assuming the best option is using the list form of 
system()?  If so, how do I get STDERR to the browser as well?

Will 'fatalsToBrowser' accomplish this?  Currently stderr seems to 
end up in the apache error log.

Thanks for you input.

-- 

Seeya,
Paul
----

                          God Bless America!

        ...we don't need to be perfect to be the best around,
                and we never stop trying to be better. 
                       Tom Clancy, The Bear and The Dragon


Reply via email to