This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
integrate changes#6252..6256,6259..6260
[perl5.git] / lib / IPC / Open3.pm
1 package IPC::Open3;
2
3 use strict;
4 no strict 'refs'; # because users pass me bareword filehandles
5 our ($VERSION, @ISA, @EXPORT);
6
7 require Exporter;
8
9 use Carp;
10 use Symbol qw(gensym qualify);
11
12 $VERSION        = 1.0103;
13 @ISA            = qw(Exporter);
14 @EXPORT         = qw(open3);
15
16 =head1 NAME
17
18 IPC::Open3, open3 - open a process for reading, writing, and error handling
19
20 =head1 SYNOPSIS
21
22     $pid = open3(\*WTRFH, \*RDRFH, \*ERRFH,
23                     'some cmd and args', 'optarg', ...);
24
25     my($wtr, $rdr, $err);
26     $pid = open3($wtr, $rdr, $err,
27                     'some cmd and args', 'optarg', ...);
28
29 =head1 DESCRIPTION
30
31 Extremely similar to open2(), open3() spawns the given $cmd and
32 connects RDRFH for reading, WTRFH for writing, and ERRFH for errors.  If
33 ERRFH is false, or the same file descriptor as RDRFH, then STDOUT and 
34 STDERR of the child are on the same filehandle.  The WTRFH will have
35 autoflush turned on.
36
37 If WTRFH begins with C<< <& >>, then WTRFH will be closed in the parent, and
38 the child will read from it directly.  If RDRFH or ERRFH begins with
39 C<< >& >>, then the child will send output directly to that filehandle.
40 In both cases, there will be a dup(2) instead of a pipe(2) made.
41
42 If either reader or writer is the null string, this will be replaced
43 by an autogenerated filehandle.  If so, you must pass a valid lvalue
44 in the parameter slot so it can be overwritten in the caller, or 
45 an exception will be raised.
46
47 The filehandles may also be integers, in which case they are understood
48 as file descriptors.
49
50 open3() returns the process ID of the child process.  It doesn't return on
51 failure: it just raises an exception matching C</^open3:/>.  However,
52 C<exec> failures in the child are not detected.  You'll have to 
53 trap SIGPIPE yourself.
54
55 open3() does not wait for and reap the child process after it exits.  
56 Except for short programs where it's acceptable to let the operating system
57 take care of this, you need to do this yourself.  This is normally as 
58 simple as calling C<waitpid $pid, 0> when you're done with the process.
59 Failing to do this can result in an accumulation of defunct or "zombie"
60 processes.  See L<perlfunc/waitpid> for more information.
61
62 If you try to read from the child's stdout writer and their stderr
63 writer, you'll have problems with blocking, which means you'll want
64 to use select() or the IO::Select, which means you'd best use
65 sysread() instead of readline() for normal stuff.
66
67 This is very dangerous, as you may block forever.  It assumes it's
68 going to talk to something like B<bc>, both writing to it and reading
69 from it.  This is presumably safe because you "know" that commands
70 like B<bc> will read a line at a time and output a line at a time.
71 Programs like B<sort> that read their entire input stream first,
72 however, are quite apt to cause deadlock.
73
74 The big problem with this approach is that if you don't have control
75 over source code being run in the child process, you can't control
76 what it does with pipe buffering.  Thus you can't just open a pipe to
77 C<cat -v> and continually read and write a line from it.
78
79 =head1 WARNING
80
81 The order of arguments differs from that of open2().
82
83 =cut
84
85 # &open3: Marc Horowitz <marc@mit.edu>
86 # derived mostly from &open2 by tom christiansen, <tchrist@convex.com>
87 # fixed for 5.001 by Ulrich Kunitz <kunitz@mai-koeln.com>
88 # ported to Win32 by Ron Schmidt, Merrill Lynch almost ended my career
89 # fixed for autovivving FHs, tchrist again
90 # allow fd numbers to be used, by Frank Tobin
91 #
92 # $Id: open3.pl,v 1.1 1993/11/23 06:26:15 marc Exp $
93 #
94 # usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
95 #
96 # spawn the given $cmd and connect rdr for
97 # reading, wtr for writing, and err for errors.
98 # if err is '', or the same as rdr, then stdout and
99 # stderr of the child are on the same fh.  returns pid
100 # of child (or dies on failure).
101
102
103 # if wtr begins with '<&', then wtr will be closed in the parent, and
104 # the child will read from it directly.  if rdr or err begins with
105 # '>&', then the child will send output directly to that fd.  In both
106 # cases, there will be a dup() instead of a pipe() made.
107
108
109 # WARNING: this is dangerous, as you may block forever
110 # unless you are very careful.
111 #
112 # $wtr is left unbuffered.
113 #
114 # abort program if
115 #   rdr or wtr are null
116 #   a system call fails
117
118 our $Me = 'open3 (bug)';        # you should never see this, it's always localized
119
120 # Fatal.pm needs to be fixed WRT prototypes.
121
122 sub xfork {
123     my $pid = fork;
124     defined $pid or croak "$Me: fork failed: $!";
125     return $pid;
126 }
127
128 sub xpipe {
129     pipe $_[0], $_[1] or croak "$Me: pipe($_[0], $_[1]) failed: $!";
130 }
131
132 # I tried using a * prototype character for the filehandle but it still
133 # disallows a bearword while compiling under strict subs.
134
135 sub xopen {
136     open $_[0], $_[1] or croak "$Me: open($_[0], $_[1]) failed: $!";
137 }
138
139 sub xclose {
140     close $_[0] or croak "$Me: close($_[0]) failed: $!";
141 }
142
143 sub fh_is_fd {
144     return $_[0] =~ /\A=?(\d+)\z/;
145 }
146
147 sub xfileno {
148     return $1 if $_[0] =~ /\A=?(\d+)\z/;  # deal with fh just being an fd
149     return fileno $_[0];
150 }
151
152 my $do_spawn = $^O eq 'os2' || $^O eq 'MSWin32';
153
154 sub _open3 {
155     local $Me = shift;
156     my($package, $dad_wtr, $dad_rdr, $dad_err, @cmd) = @_;
157     my($dup_wtr, $dup_rdr, $dup_err, $kidpid);
158
159     # simulate autovivification of filehandles because
160     # it's too ugly to use @_ throughout to make perl do it for us
161     # tchrist 5-Mar-00
162
163     unless (eval  {
164         $dad_wtr = $_[1] = gensym unless defined $dad_wtr && length $dad_wtr;
165         $dad_rdr = $_[2] = gensym unless defined $dad_rdr && length $dad_rdr;
166         1; }) 
167     {
168         # must strip crud for croak to add back, or looks ugly
169         $@ =~ s/(?<=value attempted) at .*//s;
170         croak "$Me: $@";
171     } 
172
173     $dad_err ||= $dad_rdr;
174
175     $dup_wtr = ($dad_wtr =~ s/^[<>]&//);
176     $dup_rdr = ($dad_rdr =~ s/^[<>]&//);
177     $dup_err = ($dad_err =~ s/^[<>]&//);
178
179     # force unqualified filehandles into caller's package
180     $dad_wtr = qualify $dad_wtr, $package unless fh_is_fd($dad_wtr);
181     $dad_rdr = qualify $dad_rdr, $package unless fh_is_fd($dad_rdr);
182     $dad_err = qualify $dad_err, $package unless fh_is_fd($dad_err);
183
184     my $kid_rdr = gensym;
185     my $kid_wtr = gensym;
186     my $kid_err = gensym;
187
188     xpipe $kid_rdr, $dad_wtr if !$dup_wtr;
189     xpipe $dad_rdr, $kid_wtr if !$dup_rdr;
190     xpipe $dad_err, $kid_err if !$dup_err && $dad_err ne $dad_rdr;
191
192     $kidpid = $do_spawn ? -1 : xfork;
193     if ($kidpid == 0) {         # Kid
194         # If she wants to dup the kid's stderr onto her stdout I need to
195         # save a copy of her stdout before I put something else there.
196         if ($dad_rdr ne $dad_err && $dup_err
197                 && xfileno($dad_err) == fileno(STDOUT)) {
198             my $tmp = gensym;
199             xopen($tmp, ">&$dad_err");
200             $dad_err = $tmp;
201         }
202
203         if ($dup_wtr) {
204             xopen \*STDIN,  "<&$dad_wtr" if fileno(STDIN) != xfileno($dad_wtr);
205         } else {
206             xclose $dad_wtr;
207             xopen \*STDIN,  "<&=" . fileno $kid_rdr;
208         }
209         if ($dup_rdr) {
210             xopen \*STDOUT, ">&$dad_rdr" if fileno(STDOUT) != xfileno($dad_rdr);
211         } else {
212             xclose $dad_rdr;
213             xopen \*STDOUT, ">&=" . fileno $kid_wtr;
214         }
215         if ($dad_rdr ne $dad_err) {
216             if ($dup_err) {
217                 # I have to use a fileno here because in this one case
218                 # I'm doing a dup but the filehandle might be a reference
219                 # (from the special case above).
220                 xopen \*STDERR, ">&" . xfileno($dad_err)
221                     if fileno(STDERR) != xfileno($dad_err);
222             } else {
223                 xclose $dad_err;
224                 xopen \*STDERR, ">&=" . fileno $kid_err;
225             }
226         } else {
227             xopen \*STDERR, ">&STDOUT" if fileno(STDERR) != fileno(STDOUT);
228         }
229         local($")=(" ");
230         exec @cmd # XXX: wrong process to croak from
231             or croak "$Me: exec of @cmd failed";
232     } elsif ($do_spawn) {
233         # All the bookkeeping of coincidence between handles is
234         # handled in spawn_with_handles.
235
236         my @close;
237         if ($dup_wtr) {
238           $kid_rdr = \*{$dad_wtr};
239           push @close, $kid_rdr;
240         } else {
241           push @close, \*{$dad_wtr}, $kid_rdr;
242         }
243         if ($dup_rdr) {
244           $kid_wtr = \*{$dad_rdr};
245           push @close, $kid_wtr;
246         } else {
247           push @close, \*{$dad_rdr}, $kid_wtr;
248         }
249         if ($dad_rdr ne $dad_err) {
250             if ($dup_err) {
251               $kid_err = \*{$dad_err};
252               push @close, $kid_err;
253             } else {
254               push @close, \*{$dad_err}, $kid_err;
255             }
256         } else {
257           $kid_err = $kid_wtr;
258         }
259         require IO::Pipe;
260         $kidpid = eval {
261             spawn_with_handles( [ { mode => 'r',
262                                     open_as => $kid_rdr,
263                                     handle => \*STDIN },
264                                   { mode => 'w',
265                                     open_as => $kid_wtr,
266                                     handle => \*STDOUT },
267                                   { mode => 'w',
268                                     open_as => $kid_err,
269                                     handle => \*STDERR },
270                                 ], \@close, @cmd);
271         };
272         die "$Me: $@" if $@;
273     }
274
275     xclose $kid_rdr if !$dup_wtr;
276     xclose $kid_wtr if !$dup_rdr;
277     xclose $kid_err if !$dup_err && $dad_rdr ne $dad_err;
278     # If the write handle is a dup give it away entirely, close my copy
279     # of it.
280     xclose $dad_wtr if $dup_wtr;
281
282     select((select($dad_wtr), $| = 1)[0]); # unbuffer pipe
283     $kidpid;
284 }
285
286 sub open3 {
287     if (@_ < 4) {
288         local $" = ', ';
289         croak "open3(@_): not enough arguments";
290     }
291     return _open3 'open3', scalar caller, @_
292 }
293
294 sub spawn_with_handles {
295     my $fds = shift;            # Fields: handle, mode, open_as
296     my $close_in_child = shift;
297     my ($fd, $pid, @saved_fh, $saved, %saved, @errs);
298     require Fcntl;
299
300     foreach $fd (@$fds) {
301         $fd->{tmp_copy} = IO::Handle->new_from_fd($fd->{handle}, $fd->{mode});
302         $saved{fileno $fd->{handle}} = $fd->{tmp_copy};
303     }
304     foreach $fd (@$fds) {
305         bless $fd->{handle}, 'IO::Handle'
306             unless eval { $fd->{handle}->isa('IO::Handle') } ;
307         # If some of handles to redirect-to coincide with handles to
308         # redirect, we need to use saved variants:
309         $fd->{handle}->fdopen($saved{fileno $fd->{open_as}} || $fd->{open_as},
310                               $fd->{mode});
311     }
312     unless ($^O eq 'MSWin32') {
313         # Stderr may be redirected below, so we save the err text:
314         foreach $fd (@$close_in_child) {
315             fcntl($fd, Fcntl::F_SETFD(), 1) or push @errs, "fcntl $fd: $!"
316                 unless $saved{fileno $fd}; # Do not close what we redirect!
317         }
318     }
319
320     unless (@errs) {
321         $pid = eval { system 1, @_ }; # 1 == P_NOWAIT
322         push @errs, "IO::Pipe: Can't spawn-NOWAIT: $!" if !$pid || $pid < 0;
323     }
324
325     foreach $fd (@$fds) {
326         $fd->{handle}->fdopen($fd->{tmp_copy}, $fd->{mode});
327         $fd->{tmp_copy}->close or croak "Can't close: $!";
328     }
329     croak join "\n", @errs if @errs;
330     return $pid;
331 }
332
333 1; # so require is happy