File Coverage

blib/lib/IPC/ShellCmd.pm
Criterion Covered Total %
statement 18 408 4.4
branch 0 268 0.0
condition 0 132 0.0
subroutine 6 22 27.2
pod 10 10 100.0
total 34 840 4.0


line stmt bran cond sub pod time code
1             package IPC::ShellCmd;
2              
3 1     1   931 use strict;
  1         4  
  1         46  
4 1     1   5 use Carp qw(carp croak);
  1         1  
  1         74  
5 1     1   18 use Scalar::Util;
  1         2  
  1         44  
6 1     1   994 use IO::Pipe;
  1         27051  
  1         58  
7 1     1   1411 use POSIX qw(:sys_wait_h);
  1         15743  
  1         12  
8 1     1   1611 use 5.008004; # May work with lower, unwilling to support unless you provide patches :)
  1         4  
  1         6760  
9              
10             our $VERSION = '0.001';
11             $VERSION = eval $VERSION;
12              
13             $IPC::ShellCmd::BufferLength = 16384;
14              
15             =head1 NAME
16              
17             IPC::ShellCmd - Run a command with a given environment and capture output
18              
19             =head1 SYNOPSIS
20              
21             my $isc = IPC::ShellCmd->new(["perl", "Makefile.PL"])
22             ->working_directory("/path/to/IPC_ShellCmd-0.01")
23             ->stdin(-filename => "/dev/null")
24             ->add_envs(PERL5LIB => "/home/mbm/cpanlib/lib/perl5")
25             ->chain_prog(
26             IPC::ShellCmd::Sudo->new(
27             User => 'cpanbuild',
28             SetHome => 1,
29             )
30             )->run();
31              
32             my $stdout = $isc->stdout();
33             my $status = $isc->status();
34              
35             =head1 DESCRIPTION
36              
37             This module comes from the nth time I've had to implement a select loop
38             and wanted appropriate sudo/su privilege magic, environment variables that
39             are set in the child, working directories set etc.
40              
41             It aims to provide a reasonable interface for setting up command execution
42             environment (working directory, environment variables, stdin, stdout and
43             stderr redirection if necessary), but allowing for ssh and sudo and magicing
44             in the appropriate shell quoting.
45              
46             It tries to be flexible about how you might want to capture output, exit
47             status and other such, but in such a way as it's hopefully easy to understand
48             and make it work.
49              
50             Setup method calls are chainable in a L kind of a way.
51              
52             =head2 my I<$isc> = IPC::ShellCmd->B(\I<@cmd>, I<%opts>)
53              
54             Creates a new IPC::ShellCmd object linking to the command and arguments. Possible options:
55              
56             =over 4
57              
58             =item -nowarn
59              
60             Don't throw warnings for overwriting values that have already been set
61              
62             =item -debug
63              
64             Set the debug level
65              
66             =back
67              
68             =cut
69              
70             sub new {
71 0     0 1   my $package = shift;
72 0           my $cmd = shift;
73 0           my %options = @_;
74              
75 0 0 0       if(!$cmd || !ref($cmd) || ref($cmd) ne "ARRAY") {
      0        
76 0           croak "Expecting an ARRAYREF for the command";
77             }
78              
79 0           my @cmd = @$cmd;
80              
81 0 0         if(!@cmd) {
82 0           croak "Must specify at least one thing to run";
83             }
84              
85 0           for my $cmd_el (@cmd) {
86 0 0 0       croak "Command arguments must all be strings"
87             if(!defined $cmd_el || ref($cmd_el));
88             }
89              
90 0           my $self = bless {cmd => [@cmd], opts => {}}, $package;
91              
92 0           $self->_init(\%options);
93              
94 0           $self->_debug(2, "Constructor succeeded");
95              
96 0           return $self;
97             }
98              
99             sub _init {
100 0     0     my $self = shift;
101 0           my $opts = shift;
102              
103 0 0         $self->{opts}->{warn} = 1
104             unless $opts->{'-nowarn'};
105              
106 0           $self->{select}->[0] =
107             $self->{select}->[1] =
108             $self->{select}->[2] = 1;
109              
110 0           $self->{debug} = 0;
111 0 0 0       $self->{debug} = $opts->{'-debug'}
112             if($opts->{'-debug'} && $opts->{'-debug'} =~ /^\d+$/);
113              
114 0           $self->{'argv0'} = $self->{cmd}->[0];
115 0 0 0       $self->{'argv0'} = $opts->{'-argv0'}
116             if($opts->{'-argv0'} && !ref $opts->{'-argv0'});
117             }
118              
119             sub _debug {
120 0     0     my $self = shift;
121 0           my $level = shift;
122 0           my $string = shift;
123              
124 0 0         carp sprintf("%s::debug%d: %s", ref($self), $level, $string)
125             if ($level <= $self->{debug});
126             }
127              
128             =head2 I<$isc>->B(I<$mask>)
129              
130             Sets the umask that this command is going to have, and returns
131             I<> so that it can be chained.
132              
133             =cut
134              
135             sub set_umask {
136 0     0 1   my $self = shift;
137 0           my $umask = shift;
138              
139 0 0 0       if($self->{opts}->{warn} && defined $self->{umask}) {
140 0           carp "Overwriting umask";
141             }
142              
143 0 0         if(!defined $umask) {
144 0           croak "Can't use an undefined umask";
145             }
146              
147 0 0         if($self->{run}) {
148 0           croak "Can't change setup after command has been run";
149             }
150              
151 0 0 0       if(ref $umask || $umask !~ /^\d+$/) {
152 0           croak "Invalid umask";
153             }
154              
155 0           $self->{umask} = $umask;
156              
157 0           return $self;
158             }
159              
160             =head2 I<$isc>->B([I<$path>])
161              
162             Sets the working directory that this command is going to run under,
163             and returns I<> so that it can be chained, or returns the
164             current setting with no arguments.
165              
166             =cut
167              
168             sub working_dir {
169 0     0 1   my $self = shift;
170              
171 0 0 0       if(@_ && !defined $_[0]) {
172 0           croak "Can't set working directory to undefined path";
173             }
174              
175 0           my $path = shift;
176              
177 0 0 0       if($self->{opts}->{warn} && defined $self->{wd}) {
178 0           carp "Overwriting working directory";
179             }
180              
181 0 0 0       if($self->{run} && defined $path) {
182 0           croak "Can't change setup after command has been run";
183             }
184              
185 0 0 0       if(defined $path && !ref $path) {
    0          
186 0           $self->_debug(2, "Setting working directory to \"$path\"");
187 0           $self->{wd} = $path;
188 0           return $self;
189             }
190             elsif(defined $path) {
191 0           croak "Expecting a string as working dir path";
192             }
193 0           return $self->{wd};
194             }
195              
196             =head2 I<$isc>->B(I<$env1> => I<$val1> [, I<$env2> => I<$val2>, ...])
197              
198             Adds environment variables to be setup when the command is run.
199             Returns I<> so that it can be chained.
200              
201             =cut
202              
203             sub add_envs {
204 0     0 1   my $self = shift;
205 0           my %env = @_;
206              
207 0 0         croak "Can't change setup after command has been run"
208             if($self->{run});
209              
210 0 0         croak "No envs specified"
211             unless @_;
212              
213 0           my $count = 0;
214              
215 0           for my $e (keys %env) {
216 0           $count++;
217 0 0 0       if($self->{opts}->{warn} && exists $self->{env}->{$e}) {
218 0           carp "Overwriting environment \"$e\"";
219             }
220 0           $self->{env}->{$e} = $env{$e};
221 0           $self->_debug(2, "Adding environment '$e' => '$env{$e}'");
222             }
223              
224 0           return $self;
225             }
226              
227             =head2 I<$isc>->B(I<$chain_obj>, [I<$opt> => I<$val>, ...])
228              
229             Adds a chain object, for example IPC::ShellCmd::Sudo->new(User => 'root')
230             into the chain. Returns I<> so that it can be chained.
231              
232             Valid options are:
233              
234             =over 4
235              
236             =item -include-stdin
237              
238             If set, and stdin is a filename (rather than a pipe, open filehandle, or
239             other type of descriptor) then the file will be included in the chain.
240              
241             =item -include-stdout
242              
243             As above but with stdout.
244              
245             =item -include-stderr
246              
247             As above but with stderr.
248              
249             =back
250              
251             =cut
252              
253             sub chain_prog {
254 0     0 1   my $self = shift;
255 0           my $obj = shift;
256 0           my %opts = @_;
257              
258 0 0         croak "Can't change setup after command has been run"
259             if($self->{run});
260              
261 0 0 0       croak "Expecting a IPC::ShellCmd::Chain type of object"
262             unless Scalar::Util::blessed($obj) && $obj->can("chain");
263              
264 0 0         $self->{chain} = []
265             unless $self->{chain};
266              
267 0           my $opt = {};
268 0 0         if($opts{'-include-stdin'}) {
269 0           $opt->{stdin} = 1;
270             }
271 0 0         if($opts{'-include-stdout'}) {
272 0           $opt->{stdout} = 1;
273             }
274 0 0         if($opts{'-include-stderr'}) {
275 0           $opt->{stderr} = 1;
276             }
277              
278 0           $self->_debug(2, "chaining a " . ref($obj) . " object");
279              
280 0           push(@{$self->{chain}}, {obj => $obj, opt => $opt});
  0            
281              
282 0           return $self;
283             }
284              
285             =head2 I<$isc>->B($stdin)
286              
287             =head2 I<$isc>->B($type, $stdin)
288              
289             The 1 argument form takes either
290              
291             =over 4
292              
293             =item A scalar
294              
295             This is the input to the command in full.
296              
297             =item A scalar ref
298              
299             This is a reference to the input that will be passed.
300              
301             =item A code ref
302              
303             This is expected to generate the text to send to stdin. It is
304             called with an argument of the number of bytes that the caller
305             wants to read. If it generates more, some may be lost - you have
306             been warned.
307              
308             =back
309              
310             The 2 argument form takes a type and then a ref, handle or other.
311             Valid types:
312              
313             =over 4
314              
315             =item -inherit
316              
317             The argument to this is ignored. If specified this takes stdin
318             from whatever the caller is reading from.
319              
320             =item -file
321              
322             The argument to this is a perl filehandle.
323              
324             =item -fd
325              
326             The argument to this is a system file descriptor.
327              
328             =item -filename
329              
330             The argument to this is a filename which is opened.
331              
332             =back
333              
334             Both of these return I<> for chaining. The default is
335             an empty scalar.
336              
337             =cut
338              
339             sub stdin {
340 0     0 1   my $self = shift;
341              
342 0 0         croak "Can't change setup after command has been run"
343             if ($self->{run});
344              
345 0 0 0       carp "Overwriting stdin"
346             if ($self->{opts}->{warn} && $self->{stdin});
347              
348 0 0         if(@_ == 1) {
    0          
349 0 0         if (!defined $_[0]) {
350 0           croak "Argument wasn't defined";
351             }
352              
353 0 0 0       if (ref $_[0] && ref $_[0] ne "CODE" && ref $_[0] ne "SCALAR") {
    0 0        
    0          
    0          
354 0           croak "Expecting string, coderef or scalarref for one-argument form";
355             }
356             elsif(!ref $_[0]) {
357 0           $self->{stdin} = [plain => $_[0]];
358 0           $self->{select}->[0] = 1;
359             }
360             elsif(ref $_[0] eq "CODE") {
361 0           $self->{stdin} = [coderef => $_[0]];
362 0           $self->{select}->[0] = 1;
363             }
364             elsif(ref $_[0] eq "SCALAR") {
365 0           $self->{stdin} = [scalarref => $_[0]];
366 0           $self->{select}->[0] = 1;
367             }
368             else {
369 0           die "Should be unreachable";
370             }
371             }
372             elsif(@_ == 2) {
373 0 0         if(!defined $_[0]) {
374 0           croak "Type wasn't defined";
375             }
376              
377 0 0         if($_[0] eq "-inherit") {
    0          
    0          
    0          
378 0           $self->{stdin} = [file => \*STDIN];
379 0           $self->{select}->[0] = 0;
380             }
381             elsif($_[0] eq "-file") {
382 0           $self->{stdin} = [file => $_[1]];
383 0           $self->{select}->[0] = 0;
384             }
385             elsif($_[0] eq "-filename") {
386 0 0 0       if(!defined $_[1] || ref $_[1] || $_[1] =~ /\000/) {
      0        
387 0           croak "Argument to -filename wasn't a valid filename";
388             }
389 0           $self->{stdin} = [filename => $_[1]];
390 0           $self->{select}->[0] = 0;
391             }
392             elsif($_[0] eq "-fd") {
393 0 0 0       if(!defined $_[1] || ref $_[1] || $_[1] !~ /^\d+$/) {
      0        
394 0           croak "Argument to -fd wasn't a file descriptor";
395             }
396 0           $self->{stdin} = [fd => $_[1]];
397 0           $self->{select}->[0] = 0;
398             }
399             else {
400 0           croak "Unknown type \"$_[0]\"";
401             }
402             }
403             else {
404 0           croak "Expecting 1 or 2 arguments";
405             }
406              
407 0           $self->_debug(2, "Updating stdin to be of type '" . $self->{stdin}->[0] . "'");
408              
409 0           return $self;
410             }
411              
412             =head2 I<$isc>->B()
413              
414             =head2 I<$isc>->B()
415              
416             These 0-argument forms return the captured stdout/stderr if the
417             default stdout/stderr handler is set and B() has been called.
418             If either has been setup elsewhere, then these will croak() an
419             error.
420              
421             =head2 I<$isc>->B(I<$value>)
422              
423             =head2 I<$isc>->B(I<$value>)
424              
425             =head2 I<$isc>->B(I<$type>, I<$value>)
426              
427             =head2 I<$isc>->B(I<$type>, I<$value>)
428              
429             These setup stdout/stderr as appropriate. The forms are similar
430             to the B method above.
431              
432             The 1 argument form takes either
433              
434             =over 4
435              
436             =item A scalar ref
437              
438             This is a reference to a scalar that will have the output appended
439             to it.
440              
441             =item A code ref
442              
443             This code will be called (probably more than once) with a scalar
444             of text to be appended which has been read from stdout/stderr.
445              
446             =back
447              
448             The 2 argument form takes a type and then a ref, handle or other.
449             Valid types:
450              
451             =over 4
452              
453             =item -inherit
454              
455             The argument to this is ignored. If specified this takes stdout/stderr
456             from whatever the caller is set to.
457              
458             =item -file
459              
460             The argument to this is a perl filehandle.
461              
462             =item -fd
463              
464             The argument to this is a system file descriptor.
465              
466             =item -filename
467              
468             The argument to this is a filename which is opened.
469              
470             =back
471              
472             All of these forms return I<> for chaining. The default is
473             that it will populate an internal variable to be used by the
474             corresponding 0-argument form.
475              
476             =cut
477              
478             sub stdout {
479 0     0 1   my $self = shift;
480 0           return $self->_access_out("stdout", 1, @_);
481             }
482              
483             sub stderr {
484 0     0 1   my $self = shift;
485 0           return $self->_access_out("stderr", 2, @_);
486             }
487              
488             sub _access_out {
489 0     0     my $self = shift;
490 0           my $name = shift;
491 0           my $fd = shift;
492              
493 0 0         if(@_ == 0) {
494 0 0         if($self->{run}) {
495 0 0         if(exists $self->{$name . "_text"}) {
496 0           return $self->{$name . "_text"};
497             }
498             else {
499 0           croak "Can't read $name from type \"" . $self->{$name}->[0] . \"";
500             }
501             }
502             else {
503 0           croak "Can't get $name until run() has happened";
504             }
505             }
506              
507             # At this point, we're in a >0 argument form
508              
509 0 0         croak "Can't change setup after command has been run"
510             if($self->{run});
511              
512 0 0         if(@_ == 1) {
    0          
513 0 0         if(!defined $_[0]) {
514 0           croak "Argument wasn't defined";
515             }
516              
517 0 0 0       if(!ref $_[0] || ref $_[0] ne "CODE" && ref $_[0] ne "SCALAR") {
    0 0        
    0          
518 0           croak "Expecting coderef or scalarref for one-argument form";
519             }
520             elsif(ref $_[0] eq "CODE") {
521 0           $self->{$name} = [coderef => $_[0]];
522 0           $self->{select}->[$fd] = 1;
523             }
524             elsif(ref $_[0] eq "SCALAR") {
525 0           $self->{$name} = [scalarref => $_[0]];
526 0           $self->{select}->[$fd] = 1;
527             }
528             else {
529 0           die "Should be unreachable";
530             }
531             }
532             elsif(@_ == 2) {
533 0 0         if(!defined $_[0]) {
534 0           croak "Type wasn't defined";
535             }
536              
537 0 0         if($_[0] eq "-inherit") {
    0          
    0          
    0          
538 0 0         if($name eq "stdout") {
539 0           $self->{$name} = [file => \*STDOUT];
540             }
541             else {
542 0           $self->{$name} = [file => \*STDERR];
543             }
544 0           $self->{select}->[$fd] = 0;
545             }
546             elsif($_[0] eq "-file") {
547 0           $self->{$name} = [file => $_[1]];
548 0           $self->{select}->[$fd] = 0;
549             }
550             elsif($_[0] eq "-filename") {
551 0 0 0       if(!defined $_[1] || ref $_[1] || $_[1] =~ /\000/) {
      0        
552 0           croak "Argument to -filename wasn't a valid filename";
553             }
554 0           $self->{$name} = [filename => $_[1]];
555 0           $self->{select}->[$fd] = 0;
556             }
557             elsif($_[0] eq "-fd") {
558 0 0 0       if(!defined $_[1] || ref $_[1] || $_[1] !~ /^\d+$/) {
      0        
559 0           croak "Argument to -fd wasn't a file descriptor";
560             }
561 0           $self->{$name} = [fd => $_[1]];
562 0           $self->{select}->[$fd] = 0;
563             }
564             else {
565 0           croak "Unknown type \"$_[0]\"";
566             }
567             }
568             else {
569 0           croak "Expecting 0, 1 or 2 arguments";
570             }
571              
572 0           $self->_debug(2, "Updating $name to be of type '" . $self->{$name}->[0] . "'");
573              
574 0           return $self;
575             }
576              
577             =head2 I<$isc>->B()
578              
579             Returns the exit status of the command if it got run.
580              
581             =cut
582              
583             sub status {
584 0     0 1   my $self = shift;
585              
586 0 0         if($self->{run}) {
587 0           return($self->{status});
588             }
589             else {
590 0           croak "Can't get status before command has been run";
591             }
592             }
593              
594             =head2 I<$isc>->B()
595              
596             Runs the command with all the setup that has been done.
597              
598             =cut
599              
600             sub run {
601 0     0 1   my $self = shift;
602              
603 0           my @cmd = $self->_transform_cmd();
604              
605 0           $self->_debug(1, "About to run \`" . join("', \`", @cmd) . "'");
606              
607 0           $self->_verify_fh();
608              
609 0           for my $fh (qw(stdin stdout stderr)) {
610 0           my $select = $self->{select}->[{stdin => 0, stdout => 1, stderr => 2}->{$fh}];
611 0 0         if($select) {
612 0           my $pipe = IO::Pipe->new();
613 0 0         if(!defined $pipe) {
614 0           die "pipe(): $!";
615             }
616 0           push(@{$self->{$fh}}, $pipe);
  0            
617             }
618             }
619              
620 0           my $pid = fork();
621              
622 0 0         if(!defined $pid) {
623 0           die "fork(): $!";
624             }
625 0 0         if(!$pid) {
626             # child
627             # In here, we only die, we don't croak, as the caller is very definitely parent only
628              
629 0           my $ret;
630 0 0         if(defined $self->{umask}) {
631 0           $ret = umask $self->{umask};
632 0 0         if(!defined $ret) {
633 0           die "umask(): $!\n";
634             }
635             }
636 0 0         if(defined $self->{wd}) {
637 0           $ret = chdir($self->{wd});
638 0 0         if(!defined $ret) {
639 0           die "chdir(): $!\n";
640             }
641             }
642 0 0         if(keys %{$self->{env}||{}}) {
  0 0          
643 0           for my $e (keys %{$self->{env}}) {
  0            
644 0           $ENV{$e} = $self->{env}->{$e};
645             }
646             }
647              
648 0 0         if($self->{stdin}->[0] eq "file") {
649 0 0         if(!open(STDIN, "<&", $self->{stdin}->[1])) {
650 0           die("dup2(stdin): $!\n");
651             }
652             }
653             else {
654 0           $self->{stdin}->[2]->reader();
655 0 0         if(!open(STDIN, "<&", $self->{stdin}->[2])) {
656 0           die("dup2(stdin): $!\n");
657             }
658             }
659              
660 0 0         if($self->{stdout}->[0] eq "file") {
661 0 0         if(!open(STDOUT, ">>&", $self->{stdout}->[1])) {
662 0           die("dup2(stdout): $!\n");
663             }
664             }
665             else {
666 0           $self->{stdout}->[2]->writer();
667 0 0         if(!open(STDOUT, ">>&", $self->{stdout}->[2])) {
668 0           die("dup2(stdout): $!\n");
669             }
670             }
671              
672 0 0         if($self->{stderr}->[0] eq "file") {
673 0 0         if(!open(STDERR, ">>&", $self->{stderr}->[1])) {
674 0           die("dup2(stderr): $!\n");
675             }
676             }
677             else {
678 0           $self->{stderr}->[2]->writer();
679 0 0         if(!open(STDERR, ">>&", $self->{stderr}->[2])) {
680 0           die("dup2(stderr): $!\n");
681             }
682             }
683              
684 0           for(my $i = 3 ; $i < 16384; $i++) {
685 0           POSIX::close($i);
686             }
687              
688 0           exec(@cmd);
689 0           die("exec: $!\n");
690             }
691             else {
692             # parent
693              
694 0           $self->_debug(2, "After fork: child $pid");
695              
696 0           for my $fh (qw(stdin stdout stderr)) {
697 0 0         if($self->{$fh}->[0] eq "file") {
698 0 0         if($self->{$fh}->[2]) {
699 0           $self->_debug(2, "Closing $fh in parent due to being a file");
700 0           close($self->{$fh}->[1]);
701             }
702             }
703             else {
704 0 0         if($fh eq "stdin") {
705 0           $self->_debug(2, "Setting $fh as non-block writer in parent");
706 0           $self->{$fh}->[2]->writer();
707 0           $self->{$fh}->[2]->blocking(0);
708             }
709             else {
710 0           $self->_debug(2, "Setting $fh as non-block reader in parent");
711 0           $self->{$fh}->[2]->reader();
712 0           $self->{$fh}->[2]->blocking(0);
713             }
714             }
715             }
716              
717 0           $self->_select_wait($pid);
718             }
719              
720 0           $self->{run} = 1;
721              
722 0           return $self;
723             }
724              
725             sub _select_wait {
726 0     0     my $self = shift;
727 0           my $pid = shift;
728              
729 0           local $Carp::CarpLevel = 1;
730              
731             # select loop
732 0           my($rin, $win, $ein, $rout, $wout, $eout) = ("", "", "");
733              
734 0 0         if($self->{stdin}->[0] ne "file") {
735 0           $self->_debug(3, "Adding stdin to writers");
736 0           vec($win, fileno($self->{stdin}->[2]), 1) = 1;
737             }
738              
739 0           for my $fh (qw(stdout stderr)) {
740 0 0         if($self->{$fh}->[0] ne "file") {
741 0           $self->_debug(3, "Adding $fh to readers");
742 0           vec($rin, fileno($self->{$fh}->[2]), 1) = 1;
743             }
744             }
745              
746 0   0       while($rin =~ /[^\0]/ || $win =~ /[^\0]/) {
747 0           select($rout = $rin, $wout = $win, $eout = $ein, 0.01);
748              
749 0 0 0       if($self->{stdin}->[0] ne "file" && vec($wout, fileno($self->{stdin}->[2]), 1)) {
750 0 0         if($self->{stdin}->[0] eq "plain") {
    0          
    0          
751 0           my $length = length($self->{stdin}->[1]);
752 0 0         if($length) {
753 0 0         $length = $IPC::ShellCmd::BufferLength
754             if($length > $IPC::ShellCmd::BufferLength);
755 0           $self->_debug(3, "Writing into stdin from plain scalar");
756 0           my $rc = syswrite($self->{stdin}->[2], $self->{stdin}->[1], $length);
757 0 0         if(!defined $rc) {
758 0           die("write(->stdin): $!\n");
759             }
760              
761 0           $self->{stdin}->[1] = substr($self->{stdin}->[1], $rc);
762             }
763 0 0         if(!length($self->{stdin}->[1])) {
764 0           $self->_debug(3, "Removing stdin from writers, and closing");
765 0           vec($win, fileno($self->{stdin}->[2]), 1) = 0;
766 0           close($self->{stdin}->[2]);
767             }
768             }
769             elsif($self->{stdin}->[0] eq "scalarref") {
770 0 0         $self->{stdin}->[3] = 0 unless defined $self->{stdin}->[3];
771 0           my $length = length(${$self->{stdin}->[1]}) - $self->{stdin}->[3];
  0            
772 0 0         if($length) {
773 0 0         $length = $IPC::ShellCmd::BufferLength
774             if($length > $IPC::ShellCmd::BufferLength);
775 0           $self->_debug(3, "Writing into stdin from scalarref");
776 0           my $rc = syswrite($self->{stdin}->[2],
777 0           substr(${$self->{stdin}->[1]}, $self->{stdin}->[3]), $length);
778 0 0         if(!defined $rc) {
779 0           die("write(->stdin): $!\n");
780             }
781              
782 0           $self->{stdin}->[3] += $rc;
783             }
784 0 0         if(length(${$self->{stdin}->[1]}) == $self->{stdin}->[3]) {
  0            
785 0           $self->_debug(3, "Removing stdin from writers, and closing");
786 0           vec($win, fileno($self->{stdin}->[2]), 1) = 0;
787 0           close($self->{stdin}->[2]);
788             }
789             }
790             elsif($self->{stdin}->[0] eq "coderef") {
791 0 0         $self->{stdin}->[3] = ""
792             unless defined $self->{stdin}->[3];
793              
794 0 0         $self->{stdin}->[4] = 0
795             unless defined $self->{stdin}->[4];
796 0           my $finished = $self->{stdin}->[4];
797              
798 0 0 0       if(!$finished && length $self->{stdin}->[3] < $IPC::ShellCmd::BufferLength) {
799 0           my $data = $self->{stdin}->[1]->($IPC::ShellCmd::BufferLength - length($self->{stdin}->[3]));
800 0 0         if(!defined $data) {
801 0           $finished = 1;
802             }
803              
804 0           $self->{stdin}->[3] .= $data;
805 0 0         if(length($self->{stdin}->[3]) > $IPC::ShellCmd::BufferLength) {
806 0           $self->{stdin}->[3] = substr($self->{stdin}->[3], 0, $IPC::ShellCmd::BufferLength);
807              
808             }
809             }
810              
811 0 0         if(length($self->{stdin}->[3])) {
812 0           $self->_debug(3, sprintf("Writing %d into stdin from coderef", length($self->{stdin}->[3])));
813 0           my $rc = syswrite($self->{stdin}->[2], $self->{stdin}->[3], length($self->{stdin}->[3]));
814 0 0         if(!defined $rc) {
815 0           die("write(->stdin): $!\n");
816             }
817              
818 0           $self->{stdin}->[3] = substr($self->{stdin}->[3], $rc);
819             }
820              
821 0           $self->{stdin}->[4] = $finished;
822              
823 0 0 0       if($finished && !length($self->{stdin}->[3])) {
824 0           $self->_debug(3, "Removing stdin from writers, and closing");
825 0           vec($win, fileno($self->{stdin}->[2]), 1) = 0;
826 0           close($self->{stdin}->[2]);
827             }
828             }
829             }
830              
831 0           for my $fh (qw(stdout stderr)) {
832 0 0 0       if($self->{$fh}->[0] ne "file" && vec($rout, fileno($self->{$fh}->[2]), 1)) {
833 0           my $buff = "";
834 0           $self->_debug(3, "Reading $IPC::ShellCmd::BufferLength from $fh");
835 0           my $rc = sysread($self->{$fh}->[2], $buff, $IPC::ShellCmd::BufferLength);
836 0 0         if(!defined $rc) {
837 0           die("read(->$fh): $!\n");
838             }
839 0 0         if(!$rc) {
840 0           $self->_debug(3, "Removing $fh from readers, and closing");
841 0           vec($rin, fileno($self->{$fh}->[2]), 1) = 0;
842 0           close($self->{$fh}->[2]);
843             }
844             else {
845 0 0         if($self->{$fh}->[0] eq "scalarref") {
    0          
846 0           ${$self->{$fh}->[1]} .= $buff;
  0            
847             }
848             elsif($self->{$fh}->[0] eq "coderef") {
849 0           $self->{$fh}->[1]->($buff);
850             }
851             }
852             }
853             }
854              
855 0 0 0       if(!defined $self->{status} && waitpid($pid, WNOHANG)) {
856 0           $self->_debug(3, "Reaped child $pid in loop");
857 0           $win = "";
858 0           $self->{status} = $?;
859             }
860             }
861              
862 0 0 0       if($rin !~ /[^\0]/ && $win !~ /[^\0]/ && !defined $self->{status}) {
      0        
863 0           $self->_debug(3, "Trying to reap child $pid");
864 0           my $rc = waitpid($pid, 0);
865 0           $self->_debug(3, "Reaped child $pid");
866 0 0         if(defined $rc) {
867 0           $self->{status} = $?;
868             }
869             else {
870 0           die("waitpid: $!\n");
871             }
872             }
873 0           return;
874             }
875              
876             sub _verify_fh {
877 0     0     my $self = shift;
878              
879 0           for my $fh (qw(stdin stdout stderr)) {
880 0 0         if(!$self->{$fh}) {
881 0           croak "Defaulting didn't happen for $fh";
882             }
883              
884 0           my $type = $self->{$fh}->[0];
885 0           my $select = $self->{select}->[{stdin => 0, stdout => 1, stderr => 2}->{$fh}];
886              
887             # all of the "filename" and "fd" types should have been got rid of as a part
888             # of the _transform_cmd called before this.
889              
890             # First check the types of all the fhs
891 0 0 0       if($type ne "plain" && $type ne "coderef" && $type ne "scalarref" &&
    0 0        
      0        
      0        
892             $type ne "file") {
893             # this is an assert so there's no CarpLevel...
894 0           croak "Unrecognised type $type for $fh";
895             }
896             elsif($type eq "plain" && $fh ne "stdin") {
897 0           croak "Plain is only useful for stdin, not $fh";
898             }
899              
900             # Then we check that select is correctly set.
901 0 0 0       if($type eq "plain" || $type eq "coderef" || $type eq "scalarref") {
      0        
902 0 0         if(!$select) {
903 0           croak "$type should be selected on but isn't for $fh";
904             }
905             }
906             else {
907 0 0         if($select) {
908 0           croak "$type shouldn't be selected on but is for $fh";
909             }
910             }
911             }
912             }
913              
914             sub _transform_cmd {
915 0     0     my $self = shift;
916              
917 0           my $count = 1;
918              
919 0           my $file = { stdin => 0, stdout => 0, stderr => 0 };
920              
921 0           for my $fh (qw(stdin stdout stderr)) {
922 0 0 0       if($self->{$fh} && $self->{$fh}->[0] eq "filename") {
923 0           $file->{$fh} = 1;
924             }
925             }
926              
927 0           my @cmd = @{$self->{cmd}};
  0            
928              
929 0 0         for my $el (@{$self->{chain}||[]}) {
  0            
930 0           $self->_debug(2, "Before chain $count cmd = \`" . join("', \`", @cmd) . "'");
931              
932 0           my @args = ();
933 0 0         if($count == 1) {
934 0 0         if(defined($self->{wd})) {
935 0           push(@args, "-wd", $self->{wd});
936 0           delete $self->{wd};
937             }
938 0 0         if(keys %{$self->{env}}) {
  0            
939 0           push(@args, "-env", {%{$self->{env}}});
  0            
940 0           delete $self->{env};
941             }
942 0 0         if(defined($self->{umask})) {
943 0           push(@args, "-umask", $self->{umask});
944 0           delete $self->{umask};
945             }
946             }
947              
948 0           for my $fh (qw(stdin stdout stderr)) {
949 0 0 0       if($file->{$fh} && $el->{opt}->{$fh}) {
950 0           push(@args, "-" . $fh, $self->{$fh}->[1]);
951 0           $file->{$fh} = 0;
952             # in this sub bit, because of $file->{fh}, this must be
953             # a filename, so we can do the following.
954 0           $self->{$fh}->[1] = "/dev/null";
955             }
956             }
957              
958 0           $self->_debug(2, "Calling chain $count with args = \`" . join("', \`", @args) . "'");
959 0           @cmd = $el->{obj}->chain([@cmd], {@args});
960              
961 0           $self->_debug(2, "After chain $count cmd = \`" . join("', \`", @cmd) . "'");
962              
963 0           $count++;
964             }
965              
966             # Figure out all the command defaults
967 0 0         if(!$self->{stdin}) {
968 0           $self->{stdin} = [filename => "/dev/null"];
969 0           $self->{select}->[0] = 0;
970             }
971 0           for my $fh (qw(stdout stderr)) {
972 0 0         if(!$self->{$fh}) {
973 0           $self->{$fh . "_text"} = "";
974 0           my $ref = \$self->{$fh . "_text"};
975 0           $self->{$fh} = [scalarref => $ref];
976             }
977             }
978              
979             # as a side effect of this sub, we also end up transforming filenames and fds
980             # into file handles.
981 0           for my $fh (qw(stdin stdout stderr)) {
982 0           local $Carp::CarpLevel = 1;
983 0 0 0       if($self->{$fh} && $self->{$fh}->[0] eq "filename") {
    0 0        
984 0           my $pfh;
985 0 0         if(open($pfh, ($fh eq "stdin"?"<":">>"), $self->{$fh}->[1])) {
    0          
986 0           $self->{$fh} = [file => $pfh, 1];
987             }
988             else {
989 0           croak "Couldn't open file \"" . $self->{$fh}->[1] . "\": $!";
990             }
991             }
992             elsif($self->{$fh} && $self->{$fh}->[0] eq "fd") {
993 0           my $pfh;
994 0 0         if(open($pfh, ($fh eq "stdin"?"<&=":">>&="), $self->{$fh}->[1])) {
    0          
995 0           $self->{$fh} = [file => $pfh];
996             }
997             else {
998 0           croak "Couldn't fdopen " . $self->{$fh}->[1] . ": $!";
999             }
1000             }
1001             }
1002              
1003 0           return @cmd;
1004             }
1005              
1006             =head1 BUGS
1007              
1008             Apart from the ones that are probably in there and that I don't know
1009             about, this is a very UNIX-centric view of the world, it really should
1010             cope with Win32 concepts etc.
1011              
1012             =head1 SEE ALSO
1013              
1014             L, L, L, L, L
1015              
1016             =head1 AUTHORS
1017              
1018             Matthew Byng-Maddick
1019              
1020             Tomas Doran (t0m)
1021              
1022             =head1 COPYRIGHT
1023              
1024             Copyright (c) 2009 the British Broadcasting Corperation.
1025              
1026             =head1 LICENSE
1027              
1028             This library is free software and may be distributed under the same terms as perl itself.
1029              
1030             =cut
1031              
1032             1;