home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl501m.zip / lib / IPC / Open3.pm < prev   
Text File  |  1995-07-03  |  4KB  |  139 lines

  1. package IPC::Open3;
  2. require 5.000;
  3. require Exporter;
  4. use Carp;
  5.  
  6. =head1 NAME
  7.  
  8. IPC::Open3, open3 - open a process for reading, writing, and error handling
  9.  
  10. =head1 SYNOPSIS
  11.  
  12.     $pid = open3('WTRFH', 'RDRFH', 'ERRFH' 
  13.             'some cmd and args', 'optarg', ...);
  14.  
  15. =head1 DESCRIPTION
  16.  
  17. Extremely similar to open2(), open3() spawns the given $cmd and
  18. connects RDRFH for reading, WTRFH for writing, and ERRFH for errors.  If
  19. ERRFH is '', or the same as RDRFH, then STDOUT and STDERR of the child are
  20. on the same file handle.
  21.  
  22. If WTRFH begins with ">&", then WTRFH will be closed in the parent, and
  23. the child will read from it directly.  if RDRFH or ERRFH begins with
  24. ">&", then the child will send output directly to that file handle.  In both
  25. cases, there will be a dup(2) instead of a pipe(2) made.
  26.  
  27. All caveats from open2() continue to apply.  See L<open2> for details.
  28.  
  29. =cut
  30.  
  31. @ISA = qw(Exporter);
  32. @EXPORT = qw(open3);
  33.  
  34. # &open3: Marc Horowitz <marc@mit.edu>
  35. # derived mostly from &open2 by tom christiansen, <tchrist@convex.com>
  36. #
  37. # $Id: open3.pl,v 1.1 1993/11/23 06:26:15 marc Exp $
  38. #
  39. # usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
  40. #
  41. # spawn the given $cmd and connect rdr for
  42. # reading, wtr for writing, and err for errors.
  43. # if err is '', or the same as rdr, then stdout and
  44. # stderr of the child are on the same fh.  returns pid
  45. # of child, or 0 on failure.
  46.  
  47.  
  48. # if wtr begins with '>&', then wtr will be closed in the parent, and
  49. # the child will read from it directly.  if rdr or err begins with
  50. # '>&', then the child will send output directly to that fd.  In both
  51. # cases, there will be a dup() instead of a pipe() made.
  52.  
  53.  
  54. # WARNING: this is dangerous, as you may block forever
  55. # unless you are very careful.
  56. #
  57. # $wtr is left unbuffered.
  58. #
  59. # abort program if
  60. #   rdr or wtr are null
  61. #   pipe or fork or exec fails
  62.  
  63. $fh = 'FHOPEN000';  # package static in case called more than once
  64.  
  65. sub open3 {
  66.     local($kidpid);
  67.     local($dad_wtr, $dad_rdr, $dad_err, @cmd) = @_;
  68.     local($dup_wtr, $dup_rdr, $dup_err);
  69.  
  70.     $dad_wtr            || croak "open3: wtr should not be null";
  71.     $dad_rdr            || croak "open3: rdr should not be null";
  72.     $dad_err = $dad_rdr if ($dad_err eq '');
  73.  
  74.     $dup_wtr = ($dad_wtr =~ s/^\>\&//);
  75.     $dup_rdr = ($dad_rdr =~ s/^\>\&//);
  76.     $dup_err = ($dad_err =~ s/^\>\&//);
  77.  
  78.     # force unqualified filehandles into callers' package
  79.     local($package) = caller;
  80.     $dad_wtr =~ s/^[^']+$/$package'$&/;
  81.     $dad_rdr =~ s/^[^']+$/$package'$&/;
  82.     $dad_err =~ s/^[^']+$/$package'$&/;
  83.  
  84.     local($kid_rdr) = ++$fh;
  85.     local($kid_wtr) = ++$fh;
  86.     local($kid_err) = ++$fh;
  87.  
  88.     if (!$dup_wtr) {
  89.     pipe($kid_rdr, $dad_wtr)    || croak "open3: pipe 1 (stdin) failed: $!";
  90.     }
  91.     if (!$dup_rdr) {
  92.     pipe($dad_rdr, $kid_wtr)    || croak "open3: pipe 2 (stdout) failed: $!";
  93.     }
  94.     if ($dad_err ne $dad_rdr && !$dup_err) {
  95.     pipe($dad_err, $kid_err)    || croak "open3: pipe 3 (stderr) failed: $!";
  96.     }
  97.  
  98.     if (($kidpid = fork) < 0) {
  99.         croak "open2: fork failed: $!";
  100.     } elsif ($kidpid == 0) {
  101.     if ($dup_wtr) {
  102.         open(STDIN,  ">&$dad_wtr") if (fileno(STDIN) != fileno($dad_wtr));
  103.     } else {
  104.         close($dad_wtr);
  105.         open(STDIN,  ">&$kid_rdr");
  106.     }
  107.     if ($dup_rdr) {
  108.         open(STDOUT, ">&$dad_rdr") if (fileno(STDOUT) != fileno($dad_rdr));
  109.     } else {
  110.         close($dad_rdr);
  111.         open(STDOUT, ">&$kid_wtr");
  112.     }
  113.     if ($dad_rdr ne $dad_err) {
  114.         if ($dup_err) {
  115.         open(STDERR, ">&$dad_err")
  116.             if (fileno(STDERR) != fileno($dad_err));
  117.         } else {
  118.         close($dad_err);
  119.         open(STDERR, ">&$kid_err");
  120.         }
  121.     } else {
  122.         open(STDERR, ">&STDOUT") if (fileno(STDERR) != fileno(STDOUT));
  123.     }
  124.     local($")=(" ");
  125.     exec @cmd;
  126.         croak "open2: exec of @cmd failed";
  127.     }
  128.  
  129.     close $kid_rdr; close $kid_wtr; close $kid_err;
  130.     if ($dup_wtr) {
  131.     close($dad_wtr);
  132.     }
  133.  
  134.     select((select($dad_wtr), $| = 1)[0]); # unbuffer pipe
  135.     $kidpid;
  136. }
  137. 1; # so require is happy
  138.  
  139.