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