File Coverage

inc/IPC/Run3.pm
Criterion Covered Total %
statement 106 164 64.6
branch 38 110 34.5
condition 20 67 29.8
subroutine 15 18 83.3
pod 1 1 100.0
total 180 360 50.0


line stmt bran cond sub pod time code
1             package IPC::Run3;
2              
3             =head1 NAME
4              
5             IPC::Run3 - run a subprocess in batch mode (a la system) on Unix, Win32, etc.
6              
7             =head1 VERSION
8              
9             version 0.034
10              
11             =cut
12              
13             $VERSION = '0.034';
14              
15             =head1 SYNOPSIS
16              
17             use IPC::Run3; # Exports run3() by default
18              
19             run3 \@cmd, \$in, \$out, \$err;
20             run3 \@cmd, \@in, \&out, \$err;
21              
22             =head1 DESCRIPTION
23              
24             This module allows you to run a subprocess and redirect stdin, stdout,
25             and/or stderr to files and perl data structures. It aims to satisfy 99% of the
26             need for using C, C, and C with a simple, extremely Perlish
27             API and none of the bloat and rarely used features of IPC::Run.
28              
29             Speed, simplicity, and portability are paramount. (That's speed of Perl code;
30             which is often much slower than the kind of buffered I/O that this module uses
31             to spool input to and output from the child command.) Disk space is not.
32              
33             =head2 C<< run3(\@cmd, INPUT, OUTPUT, \$err) >>
34              
35             Note that passing in a reference to C explicitly redirects the
36             associated file descriptor for C, C, or C from or to the
37             local equivalent of C (this does I pass a closed filehandle).
38             Passing in C (or not passing a redirection) allows the child to inherit
39             the corresponding C, C, or C from the parent.
40              
41             Because the redirects come last, this allows C and C to default
42             to the parent's by just not specifying them -- a common use case.
43              
44             B: This means that:
45              
46             run3 \@cmd, undef, \$out; # Pass on parent's STDIN
47              
48             B, it passes on the parent's. Use
49              
50             run3 \@cmd, \undef, \$out; # Close child's STDIN
51              
52             for that. It's not ideal, but it does work.
53              
54             If the exact same value is passed for C<$stdout> and C<$stderr>, then the child
55             will write both to the same filehandle. In general, this means that
56              
57             run3 \@cmd, \undef, "foo.txt", "foo.txt";
58             run3 \@cmd, \undef, \$both, \$both;
59              
60             will DWYM and pass a single file handle to the child for both C and
61             C, collecting all into C<$both>.
62              
63             =head1 DEBUGGING
64              
65             To enable debugging use the IPCRUN3DEBUG environment variable to
66             a non-zero integer value:
67              
68             $ IPCRUN3DEBUG=1 myapp
69              
70             =head1 PROFILING
71              
72             To enable profiling, set IPCRUN3PROFILE to a number to enable emitting profile
73             information to STDERR (1 to get timestamps, 2 to get a summary report at the
74             END of the program, 3 to get mini reports after each run) or to a filename to
75             emit raw data to a file for later analysis.
76              
77             =head1 COMPARISON
78              
79             Here's how it stacks up to existing APIs:
80              
81             =over
82              
83             =item compared to C, C, C, C:
84              
85             =over
86              
87             =item + redirects more than one file descriptor
88              
89             =item + returns TRUE on success, FALSE on failure
90              
91             =item + throws an error if problems occur in the parent process (or the pre-exec child)
92              
93             =item + allows a very perlish interface to Perl data structures and subroutines
94              
95             =item + allows 1 word invocations to avoid the shell easily:
96              
97             run3 ["foo"]; # does not invoke shell
98              
99             =item - does not return the exit code, leaves it in $?
100              
101             =back
102              
103             =item compared to C, C:
104              
105             =over
106              
107             =item + No lengthy, error prone polling / select loop needed
108              
109             =item + Hides OS dependancies
110              
111             =item + Allows SCALAR, ARRAY, and CODE references to source and sink I/O
112              
113             =item + I/O parameter order is like open3() (not like open2()).
114              
115             =item - Does not allow interaction with the subprocess
116              
117             =back
118              
119             =item compared to C:
120              
121             =over
122              
123             =item + Smaller, lower overhead, simpler, more portable
124              
125             =item + No select() loop portability issues
126              
127             =item + Does not fall prey to Perl closure leaks
128              
129             =item - Does not allow interaction with the subprocess (which
130             IPC::Run::run() allows by redirecting subroutines).
131              
132             =item - Lacks many features of IPC::Run::run() (filters, pipes,
133             redirects, pty support).
134              
135             =back
136              
137             =back
138              
139             =cut
140              
141             @EXPORT = qw( run3 );
142             %EXPORT_TAGS = ( all => \@EXPORT );
143             @ISA = qw( Exporter );
144 2     2   122054 use Exporter;
  2         3  
  2         80  
145              
146 2     2   6 use strict;
  2         2  
  2         63  
147 2   50 2   9 use constant debugging => $ENV{IPCRUN3DEBUG} || $ENV{IPCRUNDEBUG} || 0;
  2         2  
  2         135  
148 2   50 2   8 use constant profiling => $ENV{IPCRUN3PROFILE} || $ENV{IPCRUNPROFILE} || 0;
  2         1  
  2         108  
149 2     2   6 use constant is_win32 => 0 <= index $^O, "Win32";
  2         2  
  2         103  
150              
151             BEGIN {
152 2     2   32 if ( is_win32 ) {
153             eval "use Win32 qw( GetOSName ); 1" or die $@;
154             }
155             }
156              
157             #use constant is_win2k => is_win32 && GetOSName() =~ /Win2000/i;
158             #use constant is_winXP => is_win32 && GetOSName() =~ /WinXP/i;
159              
160 2     2   7 use Carp qw( croak );
  2         1  
  2         84  
161 2     2   1348 use File::Temp qw( tempfile );
  2         28547  
  2         109  
162 2     2   977 use POSIX qw( dup dup2 );
  2         8409  
  2         11  
163              
164             # We cache the handles of our temp files in order to
165             # keep from having to incur the (largish) overhead of File::Temp
166             my %fh_cache;
167             my $fh_cache_pid = $$;
168              
169             my $profiler;
170              
171 0     0   0 sub _profiler { $profiler } # test suite access
172              
173             BEGIN {
174 2     2   5018 if ( profiling ) {
175             eval "use Time::HiRes qw( gettimeofday ); 1" or die $@;
176             if ( $ENV{IPCRUN3PROFILE} =~ /\A\d+\z/ ) {
177             require IPC::Run3::ProfPP;
178             IPC::Run3::ProfPP->import;
179             $profiler = IPC::Run3::ProfPP->new(Level => $ENV{IPCRUN3PROFILE});
180             } else {
181             my ( $dest, undef, $class ) =
182             reverse split /(=)/, $ENV{IPCRUN3PROFILE}, 2;
183             $class = "IPC::Run3::ProfLogger"
184             unless defined $class && length $class;
185             if ( not eval "require $class" ) {
186             my $e = $@;
187             $class = "IPC::Run3::$class";
188             eval "require IPC::Run3::$class" or die $e;
189             }
190             $profiler = $class->new( Destination => $dest );
191             }
192             $profiler->app_call( [ $0, @ARGV ], scalar gettimeofday() );
193             }
194             }
195              
196              
197             END {
198 2     2   51348 $profiler->app_exit( scalar gettimeofday() ) if profiling;
199             }
200              
201             sub _spool_data_to_child {
202 8     8   23 my ( $type, $source, $binmode_it ) = @_;
203              
204             # If undef (not \undef) passed, they want the child to inherit
205             # the parent's STDIN.
206 8 50       19 return undef unless defined $source;
207 8         8 warn "binmode()ing STDIN\n" if is_win32 && debugging && $binmode_it;
208              
209 8         8 my $fh;
210 8 100       27 if ( ! $type ) {
    50          
211 3         10 local *FH; # Do this the backcompat way
212 3 50       103 open FH, "<$source" or croak "$!: $source";
213 3         10 $fh = *FH{IO};
214 3         3 if ( is_win32 ) {
215             binmode $fh, ":raw"; # Remove all layers
216             binmode $fh, ":crlf" unless $binmode_it;
217             }
218 3         6 warn "run3(): feeding file '$source' to child STDIN\n"
219             if debugging >= 2;
220             } elsif ( $type eq "FH" ) {
221 0         0 $fh = $source;
222 0         0 warn "run3(): feeding filehandle '$source' to child STDIN\n"
223             if debugging >= 2;
224             } else {
225 5   66     24 $fh = $fh_cache{in} ||= tempfile;
226 5         764 truncate $fh, 0;
227 5         24 seek $fh, 0, 0;
228 5         5 if ( is_win32 ) {
229             binmode $fh, ":raw"; # Remove any previous layers
230             binmode $fh, ":crlf" unless $binmode_it;
231             }
232 5         15 my $seekit;
233 5 50       22 if ( $type eq "SCALAR" ) {
    0          
    0          
234              
235             # When the run3()'s caller asks to feed an empty file
236             # to the child's stdin, we want to pass a live file
237             # descriptor to an empty file (like /dev/null) so that
238             # they don't get surprised by invalid fd errors and get
239             # normal EOF behaviors.
240 5 50       32 return $fh unless defined $$source; # \undef passed
241              
242 0         0 warn "run3(): feeding SCALAR to child STDIN",
243             debugging >= 3
244             ? ( ": '", $$source, "' (", length $$source, " chars)" )
245             : (),
246             "\n"
247             if debugging >= 2;
248              
249 0         0 $seekit = length $$source;
250 0 0       0 print $fh $$source or die "$! writing to temp file";
251              
252             } elsif ( $type eq "ARRAY" ) {
253 0         0 warn "run3(): feeding ARRAY to child STDIN",
254             debugging >= 3 ? ( ": '", @$source, "'" ) : (),
255             "\n"
256             if debugging >= 2;
257              
258 0 0       0 print $fh @$source or die "$! writing to temp file";
259 0         0 $seekit = grep length, @$source;
260             } elsif ( $type eq "CODE" ) {
261 0         0 warn "run3(): feeding output of CODE ref '$source' to child STDIN\n"
262             if debugging >= 2;
263 0         0 my $parms = []; # TODO: get these from $options
264 0         0 while (1) {
265 0         0 my $data = $source->( @$parms );
266 0 0       0 last unless defined $data;
267 0 0       0 print $fh $data or die "$! writing to temp file";
268 0         0 $seekit = length $data;
269             }
270             }
271              
272 0 0 0     0 seek $fh, 0, 0 or croak "$! seeking on temp file for child's stdin"
273             if $seekit;
274             }
275              
276 3 50       8 croak "run3() can't redirect $type to child stdin"
277             unless defined $fh;
278              
279 3         7 return $fh;
280             }
281              
282             sub _fh_for_child_output {
283 8     8   33 my ( $what, $type, $dest, $binmode_it ) = @_;
284              
285 8         8 my $fh;
286 8 50 33     56 if ( $type eq "SCALAR" && $dest == \undef ) {
    50          
    50          
287 0         0 warn "run3(): redirecting child $what to oblivion\n"
288             if debugging >= 2;
289              
290 0   0     0 $fh = $fh_cache{nul} ||= do {
291 0         0 local *FH;
292 0         0 open FH, ">" . File::Spec->devnull;
293 0         0 *FH{IO};
294             };
295             } elsif ( $type eq "FH" ) {
296 0         0 $fh = $dest;
297 0         0 warn "run3(): redirecting $what to filehandle '$dest'\n"
298             if debugging >= 3;
299             } elsif ( !$type ) {
300 8         14 warn "run3(): feeding child $what to file '$dest'\n"
301             if debugging >= 2;
302              
303 8         22 local *FH;
304 8 50       655 open FH, ">$dest" or croak "$!: $dest";
305 8         48 $fh = *FH{IO};
306             } else {
307 0         0 warn "run3(): capturing child $what\n"
308             if debugging >= 2;
309              
310 0   0     0 $fh = $fh_cache{$what} ||= tempfile;
311 0         0 seek $fh, 0, 0;
312 0         0 truncate $fh, 0;
313             }
314              
315 8         14 if ( is_win32 ) {
316             warn "binmode()ing $what\n" if debugging && $binmode_it;
317             binmode $fh, ":raw";
318             binmode $fh, ":crlf" unless $binmode_it;
319             }
320 8         18 return $fh;
321             }
322              
323             sub _read_child_output_fh {
324 0     0   0 my ( $what, $type, $dest, $fh, $options ) = @_;
325              
326 0 0 0     0 return if $type eq "SCALAR" && $dest == \undef;
327              
328 0 0       0 seek $fh, 0, 0 or croak "$! seeking on temp file for child $what";
329              
330 0 0       0 if ( $type eq "SCALAR" ) {
    0          
    0          
331 0         0 warn "run3(): reading child $what to SCALAR\n"
332             if debugging >= 3;
333              
334             # two read()s are used instead of 1 so that the first will be
335             # logged even it reads 0 bytes; the second won't.
336 0         0 my $count = read $fh, $$dest, 10_000;
337 0         0 while (1) {
338 0 0       0 croak "$! reading child $what from temp file"
339             unless defined $count;
340              
341 0 0       0 last unless $count;
342              
343 0         0 warn "run3(): read $count bytes from child $what",
344             debugging >= 3 ? ( ": '", substr( $$dest, -$count ), "'" ) : (),
345             "\n"
346             if debugging >= 2;
347              
348 0         0 $count = read $fh, $$dest, 10_000, length $$dest;
349             }
350             } elsif ( $type eq "ARRAY" ) {
351 0         0 @$dest = <$fh>;
352 0         0 if ( debugging >= 2 ) {
353             my $count = 0;
354             $count += length for @$dest;
355             warn
356             "run3(): read ",
357             scalar @$dest,
358             " records, $count bytes from child $what",
359             debugging >= 3 ? ( ": '", @$dest, "'" ) : (),
360             "\n";
361             }
362             } elsif ( $type eq "CODE" ) {
363 0         0 warn "run3(): capturing child $what to CODE ref\n"
364             if debugging >= 3;
365              
366 0         0 local $_;
367 0         0 while ( <$fh> ) {
368 0         0 warn
369             "run3(): read ",
370             length,
371             " bytes from child $what",
372             debugging >= 3 ? ( ": '", $_, "'" ) : (),
373             "\n"
374             if debugging >= 2;
375              
376 0         0 $dest->( $_ );
377             }
378             } else {
379 0         0 croak "run3() can't redirect child $what to a $type";
380             }
381              
382             }
383              
384             sub _type {
385 24     24   30 my ( $redir ) = @_;
386 24 50       21 return "FH" if eval { $redir->isa("IO::Handle") };
  24         218  
387 24         40 my $type = ref $redir;
388 24 50       57 return $type eq "GLOB" ? "FH" : $type;
389             }
390              
391             sub _max_fd {
392 0     0   0 my $fd = dup(0);
393 0         0 POSIX::close $fd;
394 0         0 return $fd;
395             }
396              
397             my $run_call_time;
398             my $sys_call_time;
399             my $sys_exit_time;
400              
401             sub run3 {
402 8     8 1 95591 $run_call_time = gettimeofday() if profiling;
403              
404 8 50 33     115 my $options = @_ && ref $_[-1] eq "HASH" ? pop : {};
405              
406 8         23 my ( $cmd, $stdin, $stdout, $stderr ) = @_;
407              
408 8         19 print STDERR "run3(): running ",
409             join( " ", map "'$_'", ref $cmd ? @$cmd : $cmd ),
410             "\n"
411             if debugging;
412              
413 8 50       27 if ( ref $cmd ) {
414 8 50       34 croak "run3(): empty command" unless @$cmd;
415 8 50       26 croak "run3(): undefined command" unless defined $cmd->[0];
416 8 50       25 croak "run3(): command name ('')" unless length $cmd->[0];
417             } else {
418 0 0       0 croak "run3(): missing command" unless @_;
419 0 0       0 croak "run3(): undefined command" unless defined $cmd;
420 0 0       0 croak "run3(): command ('')" unless length $cmd;
421             }
422              
423 8         34 my $in_type = _type $stdin;
424 8         18 my $out_type = _type $stdout;
425 8         16 my $err_type = _type $stderr;
426              
427 8 50       57 if ($fh_cache_pid != $$) {
428             # fork detected, close all cached filehandles and clear the cache
429 0         0 close $_ foreach values %fh_cache;
430 0         0 %fh_cache = ();
431 0         0 $fh_cache_pid = $$;
432             }
433            
434             # This routine procedes in stages so that a failure in an early
435             # stage prevents later stages from running, and thus from needing
436             # cleanup.
437              
438             my $in_fh = _spool_data_to_child $in_type, $stdin,
439 8 50       56 $options->{binmode_stdin} if defined $stdin;
440              
441             my $out_fh = _fh_for_child_output "stdout", $out_type, $stdout,
442 8 50       64 $options->{binmode_stdout} if defined $stdout;
443              
444 8   33     88 my $tie_err_to_out =
445             defined $stderr && defined $stdout && $stderr eq $stdout;
446              
447             my $err_fh = $tie_err_to_out
448             ? $out_fh
449             : _fh_for_child_output "stderr", $err_type, $stderr,
450 8 50       27 $options->{binmode_stderr} if defined $stderr;
    50          
451              
452             # this should make perl close these on exceptions
453 8         16 local *STDIN_SAVE;
454 8         17 local *STDOUT_SAVE;
455 8         10 local *STDERR_SAVE;
456              
457 8 50       50 my $saved_fd0 = dup( 0 ) if defined $in_fh;
458              
459             # open STDIN_SAVE, "<&STDIN"# or croak "run3(): $! saving STDIN"
460             # if defined $in_fh;
461 8 50 33     79 open STDOUT_SAVE, ">&STDOUT" or croak "run3(): $! saving STDOUT"
462             if defined $out_fh;
463 8 50 33     58 open STDERR_SAVE, ">&STDERR" or croak "run3(): $! saving STDERR"
464             if defined $err_fh;
465              
466 8         15 my $ok = eval {
467             # The open() call here seems to not force fd 0 in some cases;
468             # I ran in to trouble when using this in VCP, not sure why.
469             # the dup2() seems to work.
470 8 50 33     60 dup2( fileno $in_fh, 0 )
471             # open STDIN, "<&=" . fileno $in_fh
472             or croak "run3(): $! redirecting STDIN"
473             if defined $in_fh;
474              
475             # close $in_fh or croak "$! closing STDIN temp file"
476             # if ref $stdin;
477              
478 8 50 33     161 open STDOUT, ">&" . fileno $out_fh
479             or croak "run3(): $! redirecting STDOUT"
480             if defined $out_fh;
481              
482 8 50 33     113 open STDERR, ">&" . fileno $err_fh
483             or croak "run3(): $! redirecting STDERR"
484             if defined $err_fh;
485              
486 8         16 $sys_call_time = gettimeofday() if profiling;
487              
488             my $r = ref $cmd
489 8         20358962 ? system { $cmd->[0] }
490             is_win32
491             ? map {
492             # Probably need to offer a win32 escaping
493             # option, every command may be different.
494 8 50       20 ( my $s = $_ ) =~ s/"/"""/g;
495             $s = qq{"$s"};
496             $s;
497             } @$cmd
498             : @$cmd
499             : system $cmd;
500              
501 8         89 $sys_exit_time = gettimeofday() if profiling;
502              
503 8 50 33     135 unless ( defined $r && $r != -1 ) {
504 0         0 if ( debugging ) {
505             my $err_fh = defined $err_fh ? \*STDERR_SAVE : \*STDERR;
506             print $err_fh "run3(): system() error $!\n"
507             }
508 0         0 die $!;
509             }
510              
511 8         13 if ( debugging ) {
512             my $err_fh = defined $err_fh ? \*STDERR_SAVE : \*STDERR;
513             print $err_fh "run3(): \$? is $?\n"
514             }
515 8         105 1;
516             };
517 8         34 my $x = $@;
518              
519 8         12 my @errs;
520              
521 8 50       46 if ( defined $saved_fd0 ) {
522 8         93 dup2( $saved_fd0, 0 );
523 8         49 POSIX::close( $saved_fd0 );
524             }
525              
526             # open STDIN, "<&STDIN_SAVE"# or push @errs, "run3(): $! restoring STDIN"
527             # if defined $in_fh;
528 8 50 33     260 open STDOUT, ">&STDOUT_SAVE" or push @errs, "run3(): $! restoring STDOUT"
529             if defined $out_fh;
530 8 50 33     103 open STDERR, ">&STDERR_SAVE" or push @errs, "run3(): $! restoring STDERR"
531             if defined $err_fh;
532              
533 8 50       25 croak join ", ", @errs if @errs;
534              
535 8 50       25 die $x unless $ok;
536              
537 8 50 33     59 _read_child_output_fh "stdout", $out_type, $stdout, $out_fh, $options
      33        
538             if defined $out_fh && $out_type && $out_type ne "FH";
539 8 0 33     51 _read_child_output_fh "stderr", $err_type, $stderr, $err_fh, $options
      33        
      33        
540             if defined $err_fh && $err_type && $err_type ne "FH" && !$tie_err_to_out;
541 8         16 $profiler->run_exit(
542             $cmd,
543             $run_call_time,
544             $sys_call_time,
545             $sys_exit_time,
546             scalar gettimeofday()
547             ) if profiling;
548              
549 8         343 return 1;
550             }
551              
552             =head1 TODO
553              
554             pty support
555              
556             =head1 LIMITATIONS
557              
558             Often uses intermediate files (determined by File::Temp, and thus by the
559             File::Spec defaults and the TMPDIR env. variable) for speed, portability and
560             simplicity.
561              
562             Use extrem caution when using C in a threaded environment if
563             concurrent calls of C are possible. Most likely, I/O from different
564             invocations will get mixed up. The reason is that in most thread
565             implementations all threads in a process share the same STDIN/STDOUT/STDERR.
566             Known failures are Perl ithreads on Linux and Win32. Note that C
567             on Win32 is emulated via Win32 threads and hence I/O mix up is possible
568             between forked children here (C is "fork safe" on Unix, though).
569              
570             =head1 COPYRIGHT
571              
572             Copyright 2003, R. Barrie Slaymaker, Jr., All Rights Reserved
573              
574             =head1 LICENSE
575              
576             You may use this module under the terms of the BSD, Artistic, or GPL licenses,
577             any version.
578              
579             =head1 AUTHOR
580              
581             Barrie Slaymaker ECE
582              
583             Ricardo SIGNES ECE performed some routine maintenance in
584             2005, thanks to help from the following ticket and/or patch submitters: Jody
585             Belka, Roderich Schupp, David Morel, and anonymous others.
586              
587             =cut
588              
589             1;