home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / perl / 7054 < prev    next >
Encoding:
Text File  |  1992-11-18  |  5.0 KB  |  165 lines

  1. Newsgroups: comp.lang.perl
  2. Path: sparky!uunet!ferkel.ucsb.edu!taco!rock!concert!sas!mozart.unx.sas.com!foster!sherman
  3. From: sherman@unx.sas.com (Chris Sherman)
  4. Subject: Re: Distinguishing stdout and stderr on a pipe
  5. Sender: news@unx.sas.com (Noter of Newsworthy Events)
  6. Message-ID: <sherman.722141044@foster>
  7. Date: Thu, 19 Nov 1992 02:44:04 GMT
  8. References: <BxxI3B.G8p@da_vinci.it.uswc.uswest.com>
  9. Nntp-Posting-Host: foster.unx.sas.com
  10. Organization: SAS Institute Inc.
  11. Lines: 152
  12.  
  13. In <BxxI3B.G8p@da_vinci.it.uswc.uswest.com> rray@lookout.it.uswc.uswest.com (Randy J. Ray) writes:
  14.  
  15. >Is there a way to read from a pipe and capture both stdout and stderr, but
  16. >still be able to distunguish them? I need to run a command while formatting
  17. >returned data one way, and errors a different way.
  18.  
  19. >I have not been able to find any references to this in the Camel book or the
  20. >USENIX tutorial.
  21.  
  22. This hit the newsgroup a long time ago.  It may be useful...
  23.  
  24. ---------------------------------------------------------------------------
  25.  
  26. >From comp.lang.perl Mon Mar 23 01:32:19 1992
  27. Path: wagner.unx.sas.com!mozart.unx.sas.com!sas!rock!taco!lll-winken!ames!agate!spool.mu.edu!caen!uvaarpa!mmdf
  28. From: marc@mit.edu (Marc Horowitz)
  29. Newsgroups: comp.lang.perl
  30. Subject: Re: how to grab STDERR of backticked command
  31. Message-ID: <1992Mar22.084122.25819@uvaarpa.Virginia.EDU>
  32. Date: 22 Mar 92 08:41:22 GMT
  33. Sender: mmdf@uvaarpa.Virginia.EDU (Mail System)
  34. Reply-To: Marc Horowitz <marc@mit.edu>
  35. Organization: The Internet
  36. Lines: 121
  37.  
  38. |> This is all very well, but I have a different situation where I want
  39. |> to catch stdout and stderr and do different things with them!
  40.  
  41. I have a modified version of open2, called open3, which lets you do
  42. different things with stdout and stderr.  You might do something like:
  43.  
  44. open(LOGFILE,">logfile");
  45. $child = &open3('INPUT','>&LOGFILE','ERRORS','cc','foo.c');
  46. while(<ERRORS>) {
  47.     # do whatever
  48. }
  49.  
  50.         Marc
  51.  
  52. --cut--
  53. # &open3: Marc Horowitz <marc@mit.edu>
  54. # derived mostly from &open2 by tom christiansen, <tchrist@convex.com>
  55. #
  56. # usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
  57. #
  58. # spawn the given $cmd and connect rdr for
  59. # reading, wtr for writing, and err for errors.
  60. # if err is '', or the same as rdr, then stdout and
  61. # stderr of the child are on the same fh.  returns pid
  62. # of child, or 0 on failure.
  63.  
  64.  
  65. # if wtr begins with '>&', then wtr will be closed in the parent, and
  66. # the child will read from it directly.  if rdr or err begins with
  67. # '>&', then the child will send output directly to that fd.  In both
  68. # cases, there will be a dup() instead of a pipe() made.
  69.  
  70.  
  71. # WARNING: this is dangerous, as you may block forever
  72. # unless you are very careful.
  73. #
  74. # $wtr is left unbuffered.
  75. #
  76. # abort program if
  77. #   rdr or wtr are null
  78. #   pipe or fork or exec fails
  79.  
  80. package open3;
  81.  
  82. $fh = 'FHOPEN000';  # package static in case called more than once
  83.  
  84. sub main'open3 {
  85.     local($kidpid);
  86.     local($dad_wtr, $dad_rdr, $dad_err, @cmd) = @_;
  87.     local($dup_wtr, $dup_rdr, $dup_err);
  88.  
  89.     $dad_wtr            || die "open3: wtr should not be null";
  90.     $dad_rdr            || die "open3: rdr should not be null";
  91.     $dad_err = $dad_rdr if ($dad_err eq '');
  92.  
  93.     $dup_wtr = ($dad_wtr =~ s/^\>\&//);
  94.     $dup_rdr = ($dad_rdr =~ s/^\>\&//);
  95.     $dup_err = ($dad_err =~ s/^\>\&//);
  96.  
  97.     # force unqualified filehandles into callers' package
  98.     local($package) = caller;
  99.     $dad_wtr =~ s/^[^']+$/$package'$&/;
  100.     $dad_rdr =~ s/^[^']+$/$package'$&/;
  101.     $dad_err =~ s/^[^']+$/$package'$&/;
  102.  
  103.     local($kid_rdr) = ++$fh;
  104.     local($kid_wtr) = ++$fh;
  105.     local($kid_err) = ++$fh;
  106.  
  107.     if (!$dup_wtr) {
  108.     pipe($kid_rdr, $dad_wtr)    || die "open3: pipe 1 (stdin) failed: $!";
  109.     }
  110.     if (!$dup_rdr) {
  111.     pipe($dad_rdr, $kid_wtr)    || die "open3: pipe 2 (stdout) failed: $!";
  112.     }
  113.     if ($dad_err ne $dad_rdr && !$dup_err) {
  114.     pipe($dad_err, $kid_err)    || die "open3: pipe 3 (stderr) failed: $!";
  115.     }
  116.  
  117.     if (($kidpid = fork) < 0) {
  118.         die "open2: fork failed: $!";
  119.     } elsif ($kidpid == 0) {
  120.     if ($dup_wtr) {
  121.         open(STDIN,  ">&$dad_wtr") if (fileno(STDIN) != fileno($dad_wtr));
  122.     } else {
  123.         close($dad_wtr);
  124.         open(STDIN,  ">&$kid_rdr");
  125.     }
  126.     if ($dup_rdr) {
  127.         open(STDOUT, ">&$dad_rdr") if (fileno(STDOUT) != fileno($dad_rdr));
  128.     } else {
  129.         close($dad_rdr);
  130.         open(STDOUT, ">&$kid_wtr");
  131.     }
  132.     if ($dad_rdr ne $dad_err) {
  133.         if ($dup_err) {
  134.         open(STDERR, ">&$dad_err")
  135.             if (fileno(STDERR) != fileno($dad_err));
  136.         } else {
  137.         close($dad_err);
  138.         open(STDERR, ">&$kid_err");
  139.         }
  140.     } else {
  141.         open(STDERR, ">&STDOUT") if (fileno(STDERR) != fileno(STDOUT));
  142.     }
  143.     exec @cmd;
  144.  
  145.     local($")=(" ");
  146.         die "open2: exec of @cmd failed";
  147.     }
  148.  
  149.     close $kid_rdr; close $kid_wtr; close $kid_err;
  150.     if ($dup_wtr) {
  151.     close($dad_wtr);
  152.     }
  153.  
  154.     select((select($dad_wtr), $| = 1)[0]); # unbuffer pipe
  155.     $kidpid;
  156. }
  157. 1; # so require is happy
  158. --cut--
  159.  
  160. -- 
  161.      ____/     /     /     __  /    _  _/    ____/
  162.     /         /     /     /   /      /     /          Chris Sherman
  163.    /         ___   /        _/      /          /
  164.  _____/   __/   __/   __/ _\    _____/   _____/           sherman@unx.sas.com
  165.