xref: /openbsd-src/gnu/usr.bin/perl/ext/IPC-Open3/lib/IPC/Open3.pm (revision a0747c9f67a4ae71ccb71e62a28d1ea19e06a63c)
1package IPC::Open3;
2
3use strict;
4no strict 'refs'; # because users pass me bareword filehandles
5our ($VERSION, @ISA, @EXPORT);
6
7require Exporter;
8
9use Carp;
10use Symbol qw(gensym qualify);
11
12$VERSION	= '1.21';
13@ISA		= qw(Exporter);
14@EXPORT		= qw(open3);
15
16=head1 NAME
17
18IPC::Open3 - open a process for reading, writing, and error handling using open3()
19
20=head1 SYNOPSIS
21
22    use Symbol 'gensym'; # vivify a separate handle for STDERR
23    my $pid = open3(my $chld_in, my $chld_out, my $chld_err = gensym,
24		    'some', 'cmd', 'and', 'args');
25    # or pass the command through the shell
26    my $pid = open3(my $chld_in, my $chld_out, my $chld_err = gensym,
27		    'some cmd and args');
28
29    # read from parent STDIN
30    # send STDOUT and STDERR to already open handle
31    open my $outfile, '>>', 'output.txt' or die "open failed: $!";
32    my $pid = open3('<&STDIN', $outfile, undef,
33		    'some', 'cmd', 'and', 'args');
34
35    # write to parent STDOUT and STDERR
36    my $pid = open3(my $chld_in, '>&STDOUT', '>&STDERR',
37		    'some', 'cmd', 'and', 'args');
38
39    # reap zombie and retrieve exit status
40    waitpid( $pid, 0 );
41    my $child_exit_status = $? >> 8;
42
43=head1 DESCRIPTION
44
45Extremely similar to open2(), open3() spawns the given command and
46connects $chld_out for reading from the child, $chld_in for writing to
47the child, and $chld_err for errors.  If $chld_err is false, or the
48same file descriptor as $chld_out, then STDOUT and STDERR of the child
49are on the same filehandle.  This means that an autovivified lexical
50cannot be used for the STDERR filehandle, but gensym from L<Symbol> can
51be used to vivify a new glob reference, see L</SYNOPSIS>.  The $chld_in
52will have autoflush turned on.
53
54If $chld_in begins with C<< <& >>, then $chld_in will be closed in the
55parent, and the child will read from it directly.  If $chld_out or
56$chld_err begins with C<< >& >>, then the child will send output
57directly to that filehandle.  In both cases, there will be a L<dup(2)>
58instead of a L<pipe(2)> made.
59
60If either reader or writer is the empty string or undefined, this will
61be replaced by an autogenerated filehandle.  If so, you must pass a
62valid lvalue in the parameter slot so it can be overwritten in the
63caller, or an exception will be raised.
64
65The filehandles may also be integers, in which case they are understood
66as file descriptors.
67
68open3() returns the process ID of the child process.  It doesn't return on
69failure: it just raises an exception matching C</^open3:/>.  However,
70C<exec> failures in the child (such as no such file or permission denied),
71are just reported to $chld_err under Windows and OS/2, as it is not possible
72to trap them.
73
74If the child process dies for any reason, the next write to $chld_in is
75likely to generate a SIGPIPE in the parent, which is fatal by default.
76So you may wish to handle this signal.
77
78Note if you specify C<-> as the command, in an analogous fashion to
79C<open(my $fh, "-|")> the child process will just be the forked Perl
80process rather than an external command.  This feature isn't yet
81supported on Win32 platforms.
82
83open3() does not wait for and reap the child process after it exits.
84Except for short programs where it's acceptable to let the operating system
85take care of this, you need to do this yourself.  This is normally as
86simple as calling C<waitpid $pid, 0> when you're done with the process.
87Failing to do this can result in an accumulation of defunct or "zombie"
88processes.  See L<perlfunc/waitpid> for more information.
89
90If you try to read from the child's stdout writer and their stderr
91writer, you'll have problems with blocking, which means you'll want
92to use select() or L<IO::Select>, which means you'd best use
93sysread() instead of readline() for normal stuff.
94
95This is very dangerous, as you may block forever.  It assumes it's
96going to talk to something like L<bc(1)>, both writing to it and reading
97from it.  This is presumably safe because you "know" that commands
98like L<bc(1)> will read a line at a time and output a line at a time.
99Programs like L<sort(1)> that read their entire input stream first,
100however, are quite apt to cause deadlock.
101
102The big problem with this approach is that if you don't have control
103over source code being run in the child process, you can't control
104what it does with pipe buffering.  Thus you can't just open a pipe to
105C<cat -v> and continually read and write a line from it.
106
107=head1 See Also
108
109=over 4
110
111=item L<IPC::Open2>
112
113Like Open3 but without STDERR capture.
114
115=item L<IPC::Run>
116
117This is a CPAN module that has better error handling and more facilities
118than Open3.
119
120=back
121
122=head1 WARNING
123
124The order of arguments differs from that of open2().
125
126=cut
127
128# &open3: Marc Horowitz <marc@mit.edu>
129# derived mostly from &open2 by tom christiansen, <tchrist@convex.com>
130# fixed for 5.001 by Ulrich Kunitz <kunitz@mai-koeln.com>
131# ported to Win32 by Ron Schmidt, Merrill Lynch almost ended my career
132# fixed for autovivving FHs, tchrist again
133# allow fd numbers to be used, by Frank Tobin
134# allow '-' as command (c.f. open "-|"), by Adam Spiers <perl@adamspiers.org>
135#
136# usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
137#
138# spawn the given $cmd and connect rdr for
139# reading, wtr for writing, and err for errors.
140# if err is '', or the same as rdr, then stdout and
141# stderr of the child are on the same fh.  returns pid
142# of child (or dies on failure).
143
144
145# if wtr begins with '<&', then wtr will be closed in the parent, and
146# the child will read from it directly.  if rdr or err begins with
147# '>&', then the child will send output directly to that fd.  In both
148# cases, there will be a dup() instead of a pipe() made.
149
150
151# WARNING: this is dangerous, as you may block forever
152# unless you are very careful.
153#
154# $wtr is left unbuffered.
155#
156# abort program if
157#   rdr or wtr are null
158#   a system call fails
159
160our $Me = 'open3 (bug)';	# you should never see this, it's always localized
161
162# Fatal.pm needs to be fixed WRT prototypes.
163
164sub xpipe {
165    pipe $_[0], $_[1] or croak "$Me: pipe($_[0], $_[1]) failed: $!";
166}
167
168# I tried using a * prototype character for the filehandle but it still
169# disallows a bareword while compiling under strict subs.
170
171sub xopen {
172    open $_[0], $_[1], @_[2..$#_] and return;
173    local $" = ', ';
174    carp "$Me: open(@_) failed: $!";
175}
176
177sub xclose {
178    $_[0] =~ /\A=?(\d+)\z/
179	? do { my $fh; open($fh, $_[1] . '&=' . $1) and close($fh); }
180	: close $_[0]
181	or croak "$Me: close($_[0]) failed: $!";
182}
183
184sub xfileno {
185    return $1 if $_[0] =~ /\A=?(\d+)\z/;  # deal with fh just being an fd
186    return fileno $_[0];
187}
188
189use constant FORCE_DEBUG_SPAWN => 0;
190use constant DO_SPAWN => $^O eq 'os2' || $^O eq 'MSWin32' || FORCE_DEBUG_SPAWN;
191
192sub _open3 {
193    local $Me = shift;
194
195    # simulate autovivification of filehandles because
196    # it's too ugly to use @_ throughout to make perl do it for us
197    # tchrist 5-Mar-00
198
199    # Historically, open3(undef...) has silently worked, so keep
200    # it working.
201    splice @_, 0, 1, undef if \$_[0] == \undef;
202    splice @_, 1, 1, undef if \$_[1] == \undef;
203    unless (eval  {
204	$_[0] = gensym unless defined $_[0] && length $_[0];
205	$_[1] = gensym unless defined $_[1] && length $_[1];
206	1; })
207    {
208	# must strip crud for croak to add back, or looks ugly
209	$@ =~ s/(?<=value attempted) at .*//s;
210	croak "$Me: $@";
211    }
212
213    my @handles = ({ mode => '<', handle => \*STDIN },
214		   { mode => '>', handle => \*STDOUT },
215		   { mode => '>', handle => \*STDERR },
216		  );
217
218    foreach (@handles) {
219	$_->{parent} = shift;
220	$_->{open_as} = gensym;
221    }
222
223    if (@_ > 1 and $_[0] eq '-') {
224	croak "Arguments don't make sense when the command is '-'"
225    }
226
227    $handles[2]{parent} ||= $handles[1]{parent};
228    $handles[2]{dup_of_out} = $handles[1]{parent} eq $handles[2]{parent};
229
230    my $package;
231    foreach (@handles) {
232	$_->{dup} = ($_->{parent} =~ s/^[<>]&//);
233
234	if ($_->{parent} !~ /\A=?(\d+)\z/) {
235	    # force unqualified filehandles into caller's package
236	    $package //= caller 1;
237	    $_->{parent} = qualify $_->{parent}, $package;
238	}
239
240	next if $_->{dup} or $_->{dup_of_out};
241	if ($_->{mode} eq '<') {
242	    xpipe $_->{open_as}, $_->{parent};
243	} else {
244	    xpipe $_->{parent}, $_->{open_as};
245	}
246    }
247
248    my $kidpid;
249    if (!DO_SPAWN) {
250	# Used to communicate exec failures.
251	xpipe my $stat_r, my $stat_w;
252
253	$kidpid = fork;
254	croak "$Me: fork failed: $!" unless defined $kidpid;
255	if ($kidpid == 0) {  # Kid
256	    eval {
257		# A tie in the parent should not be allowed to cause problems.
258		untie *STDIN;
259		untie *STDOUT;
260		untie *STDERR;
261
262		close $stat_r;
263		require Fcntl;
264		my $flags = fcntl $stat_w, &Fcntl::F_GETFD, 0;
265		croak "$Me: fcntl failed: $!" unless $flags;
266		fcntl $stat_w, &Fcntl::F_SETFD, $flags|&Fcntl::FD_CLOEXEC
267		    or croak "$Me: fcntl failed: $!";
268
269		# If she wants to dup the kid's stderr onto her stdout I need to
270		# save a copy of her stdout before I put something else there.
271		if (!$handles[2]{dup_of_out} && $handles[2]{dup}
272			&& xfileno($handles[2]{parent}) == fileno \*STDOUT) {
273		    my $tmp = gensym;
274		    xopen($tmp, '>&', $handles[2]{parent});
275		    $handles[2]{parent} = $tmp;
276		}
277
278		foreach (@handles) {
279		    if ($_->{dup_of_out}) {
280			xopen \*STDERR, ">&STDOUT"
281			    if defined fileno STDERR && fileno STDERR != fileno STDOUT;
282		    } elsif ($_->{dup}) {
283			xopen $_->{handle}, $_->{mode} . '&', $_->{parent}
284			    if fileno $_->{handle} != xfileno($_->{parent});
285		    } else {
286			xclose $_->{parent}, $_->{mode};
287			xopen $_->{handle}, $_->{mode} . '&=',
288			    fileno $_->{open_as};
289		    }
290		}
291		return 1 if ($_[0] eq '-');
292		exec @_ or do {
293		    local($")=(" ");
294		    croak "$Me: exec of @_ failed: $!";
295		};
296	    } and do {
297                close $stat_w;
298                return 0;
299            };
300
301	    my $bang = 0+$!;
302	    my $err = $@;
303	    utf8::encode $err if $] >= 5.008;
304	    print $stat_w pack('IIa*', $bang, length($err), $err);
305	    close $stat_w;
306
307	    eval { require POSIX; POSIX::_exit(255); };
308	    exit 255;
309	}
310	else {  # Parent
311	    close $stat_w;
312	    my $to_read = length(pack('I', 0)) * 2;
313	    my $bytes_read = read($stat_r, my $buf = '', $to_read);
314	    if ($bytes_read) {
315		(my $bang, $to_read) = unpack('II', $buf);
316		read($stat_r, my $err = '', $to_read);
317		waitpid $kidpid, 0; # Reap child which should have exited
318		if ($err) {
319		    utf8::decode $err if $] >= 5.008;
320		} else {
321		    $err = "$Me: " . ($! = $bang);
322		}
323		$! = $bang;
324		die($err);
325	    }
326	}
327    }
328    else {  # DO_SPAWN
329	# All the bookkeeping of coincidence between handles is
330	# handled in spawn_with_handles.
331
332	my @close;
333
334	foreach (@handles) {
335	    if ($_->{dup_of_out}) {
336		$_->{open_as} = $handles[1]{open_as};
337	    } elsif ($_->{dup}) {
338		$_->{open_as} = $_->{parent} =~ /\A[0-9]+\z/
339		    ? $_->{parent} : \*{$_->{parent}};
340		push @close, $_->{open_as};
341	    } else {
342		push @close, \*{$_->{parent}}, $_->{open_as};
343	    }
344	}
345	require IO::Pipe;
346	$kidpid = eval {
347	    spawn_with_handles(\@handles, \@close, @_);
348	};
349	die "$Me: $@" if $@;
350    }
351
352    foreach (@handles) {
353	next if $_->{dup} or $_->{dup_of_out};
354	xclose $_->{open_as}, $_->{mode};
355    }
356
357    # If the write handle is a dup give it away entirely, close my copy
358    # of it.
359    xclose $handles[0]{parent}, $handles[0]{mode} if $handles[0]{dup};
360
361    select((select($handles[0]{parent}), $| = 1)[0]); # unbuffer pipe
362    $kidpid;
363}
364
365sub open3 {
366    if (@_ < 4) {
367	local $" = ', ';
368	croak "open3(@_): not enough arguments";
369    }
370    return _open3 'open3', @_
371}
372
373sub spawn_with_handles {
374    my $fds = shift;		# Fields: handle, mode, open_as
375    my $close_in_child = shift;
376    my ($fd, %saved, @errs);
377
378    foreach $fd (@$fds) {
379	$fd->{tmp_copy} = IO::Handle->new_from_fd($fd->{handle}, $fd->{mode});
380	$saved{fileno $fd->{handle}} = $fd->{tmp_copy} if $fd->{tmp_copy};
381    }
382    foreach $fd (@$fds) {
383	bless $fd->{handle}, 'IO::Handle'
384	    unless eval { $fd->{handle}->isa('IO::Handle') } ;
385	# If some of handles to redirect-to coincide with handles to
386	# redirect, we need to use saved variants:
387    my $open_as = $fd->{open_as};
388    my $fileno = fileno($open_as);
389    $fd->{handle}->fdopen(defined($fileno)
390                  ? $saved{$fileno} || $open_as
391                  : $open_as,
392                  $fd->{mode});
393    }
394    unless ($^O eq 'MSWin32') {
395	require Fcntl;
396	# Stderr may be redirected below, so we save the err text:
397	foreach $fd (@$close_in_child) {
398	    next unless fileno $fd;
399	    fcntl($fd, Fcntl::F_SETFD(), 1) or push @errs, "fcntl $fd: $!"
400		unless $saved{fileno $fd}; # Do not close what we redirect!
401	}
402    }
403
404    my $pid;
405    unless (@errs) {
406	if (FORCE_DEBUG_SPAWN) {
407	    pipe my $r, my $w or die "Pipe failed: $!";
408	    $pid = fork;
409	    die "Fork failed: $!" unless defined $pid;
410	    if (!$pid) {
411		{ no warnings; exec @_ }
412		print $w 0 + $!;
413		close $w;
414		require POSIX;
415		POSIX::_exit(255);
416	    }
417	    close $w;
418	    my $bad = <$r>;
419	    if (defined $bad) {
420		$! = $bad;
421		undef $pid;
422	    }
423	} else {
424	    $pid = eval { system 1, @_ }; # 1 == P_NOWAIT
425	}
426	if($@) {
427	    push @errs, "IO::Pipe: Can't spawn-NOWAIT: $@";
428	} elsif(!$pid || $pid < 0) {
429	    push @errs, "IO::Pipe: Can't spawn-NOWAIT: $!";
430	}
431    }
432
433    # Do this in reverse, so that STDERR is restored first:
434    foreach $fd (reverse @$fds) {
435	$fd->{handle}->fdopen($fd->{tmp_copy}, $fd->{mode});
436    }
437    foreach (values %saved) {
438	$_->close or croak "Can't close: $!";
439    }
440    croak join "\n", @errs if @errs;
441    return $pid;
442}
443
4441; # so require is happy
445