File Coverage

blib/lib/Shell.pm
Criterion Covered Total %
statement 58 64 90.6
branch 16 24 66.6
condition 7 11 63.6
subroutine 12 13 92.3
pod 0 1 0.0
total 93 113 82.3


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