File Coverage

blib/lib/Shell.pm
Criterion Covered Total %
statement 57 62 91.9
branch 16 24 66.6
condition 7 11 63.6
subroutine 12 13 92.3
pod 0 1 0.0
total 92 111 82.8


line stmt bran cond sub pod time code
1             package Shell;
2 2     2   48776 use 5.006_001;
  2         8  
3 2     2   11 use strict;
  2         4  
  2         55  
4 2     2   10 use warnings;
  2         9  
  2         119  
5 2     2   1812 use File::Spec::Functions;
  2         1892  
  2         487  
6              
7             our($capture_stderr, $raw, $VERSION, $AUTOLOAD);
8              
9             $VERSION = '0.73';
10             $VERSION = eval $VERSION;
11              
12 1     1 0 11 sub new { bless \my $foo, shift }
13       0     sub DESTROY { }
14              
15             sub import {
16 2     2   19 my $self = shift;
17 2         16 my ($callpack, $callfile, $callline) = caller;
18 2         4 my @EXPORT;
19 2 50       9 if (@_) {
20 0         0 @EXPORT = @_;
21             } else {
22 2         6 @EXPORT = 'AUTOLOAD';
23             }
24 2         6 foreach my $sym (@EXPORT) {
25 2     2   12 no strict 'refs';
  2         5  
  2         205  
26 2         4 *{"${callpack}::$sym"} = \&{"Shell::$sym"};
  2         28  
  2         8  
27             }
28             }
29              
30             # NOTE: this is used to enable constant folding in
31             # expressions like (OS eq 'MSWin32') and
32             # (OS eq 'os2') just like it happened in 0.6 version
33             # which used eval "string" to install subs on the fly.
34 2     2   13 use constant OS => $^O;
  2         3  
  2         1684  
35              
36             =begin private
37              
38             =over
39              
40             =item B<_make_cmd>
41              
42             $sub = _make_cmd($cmd);
43             $sub = $shell->_make_cmd($cmd);
44              
45             Creates a closure which invokes the system command C<$cmd>.
46              
47             =back
48              
49             =end private
50              
51             =cut
52              
53             sub _make_cmd {
54 3 50 33 3   16 shift if ref $_[0] && $_[0]->isa( 'Shell' );
55 3         8 my $cmd = shift;
56 3         12 my $null = File::Spec::Functions::devnull();
57 3   100     25 $Shell::capture_stderr ||= 0;
58             # closing over $^O, $cmd, and $null
59             return sub {
60 5 100 66 5   1162 shift if ref $_[0] && $_[0]->isa( 'Shell' );
61 5 100       23 if (@_ < 1) {
62 3 50       1097178 $Shell::capture_stderr == 1 ? `$cmd 2>&1` :
    100          
63             $Shell::capture_stderr == -1 ? `$cmd 2>$null` :
64             `$cmd`;
65             } elsif (OS eq 'os2') {
66             local(*SAVEOUT, *READ, *WRITE);
67              
68             open SAVEOUT, '>&STDOUT' or die;
69             pipe READ, WRITE or die;
70             open STDOUT, '>&WRITE' or die;
71             close WRITE;
72              
73             my $pid = system(1, $cmd, @_);
74             die "Can't execute $cmd: $!\n" if $pid < 0;
75              
76             open STDOUT, '>&SAVEOUT' or die;
77             close SAVEOUT;
78              
79             if (wantarray) {
80             my @ret = ;
81             close READ;
82             waitpid $pid, 0;
83             @ret;
84             } else {
85             local($/) = undef;
86             my $ret = ;
87             close READ;
88             waitpid $pid, 0;
89             $ret;
90             }
91             } else {
92 2         8 my $a;
93 2         15 my @arr = @_;
94 2 50       20 unless( $Shell::raw ){
95 2         9 if (OS eq 'MSWin32') {
96             # XXX this special-casing should not be needed
97             # if we do quoting right on Windows. :-(
98             #
99             # First, escape all quotes. Cover the case where we
100             # want to pass along a quote preceded by a backslash
101             # (i.e., C<"param \""" end">).
102             # Ugly, yup? You know, windoze.
103             # Enclose in quotes only the parameters that need it:
104             # try this: c:> dir "/w"
105             # and this: c:> dir /w
106             for (@arr) {
107             s/"/\\"/g;
108             s/\\\\"/\\\\"""/g;
109             $_ = qq["$_"] if /\s/;
110             }
111             } else {
112 2         17 for (@arr) {
113 2         14 s/(['\\])/\\$1/g;
114 2         12 $_ = $_;
115             }
116             }
117             }
118 2 50       14 push @arr, '2>&1' if $Shell::capture_stderr == 1;
119 2 50       146 push @arr, '2>$null' if $Shell::capture_stderr == -1;
120 2 50       6500 open(SUBPROC, join(' ', $cmd, @arr, '|'))
121             or die "Can't exec $cmd: $!\n";
122 2 50       51 if (wantarray) {
123 2         8755 my @ret = ;
124 2         138 close SUBPROC; # XXX Oughta use a destructor.
125 2         115 @ret;
126             } else {
127 0         0 local($/) = undef;
128 0         0 my $ret = ;
129 0         0 close SUBPROC;
130 0         0 $ret;
131             }
132             }
133 3         57 };
134             }
135              
136             sub AUTOLOAD {
137 3 100 66 3   2919 shift if ref $_[0] && $_[0]->isa( 'Shell' );
138 3         13 my $cmd = $AUTOLOAD;
139 3         30 $cmd =~ s/^.*:://;
140 2     2   12 no strict 'refs';
  2         4  
  2         165  
141 3         17 *$AUTOLOAD = _make_cmd($cmd);
142 3         19 goto &$AUTOLOAD;
143             }
144              
145             1;
146              
147             __END__