File Coverage

blib/lib/File/Which.pm
Criterion Covered Total %
statement 52 56 92.8
branch 12 18 66.6
condition 6 14 42.8
subroutine 11 11 100.0
pod 2 2 100.0
total 83 101 82.1


line stmt bran cond sub pod time code
1             package File::Which;
2              
3 2     2   75378 use strict;
  2         15  
  2         57  
4 2     2   10 use warnings;
  2         4  
  2         53  
5 2     2   9 use base qw( Exporter );
  2         4  
  2         266  
6 2     2   14 use File::Spec ();
  2         4  
  2         169  
7              
8             # ABSTRACT: Perl implementation of the which utility as an API
9             our $VERSION = '1.25_01'; # TRIAL VERSION
10             $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
11              
12              
13             our @EXPORT = 'which';
14             our @EXPORT_OK = 'where';
15              
16 2     2   14 use constant IS_VMS => ($^O eq 'VMS');
  2         4  
  2         240  
17 2     2   16 use constant IS_MAC => ($^O eq 'MacOS');
  2         2  
  2         224  
18 2   33 2   18 use constant IS_WIN => ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2');
  2         8  
  2         149  
19 2     2   11 use constant IS_DOS => IS_WIN();
  2         4  
  2         142  
20 2   33 2   14 use constant IS_CYG => ($^O eq 'cygwin' || $^O eq 'msys');
  2         3  
  2         1519  
21              
22             our $IMPLICIT_CURRENT_DIR = IS_WIN || IS_VMS || IS_MAC;
23              
24             # For Win32 systems, stores the extensions used for
25             # executable files
26             # For others, the empty string is used
27             # because 'perl' . '' eq 'perl' => easier
28             my @PATHEXT = ('');
29             if ( IS_WIN ) {
30             # WinNT. PATHEXT might be set on Cygwin, but not used.
31             if ( $ENV{PATHEXT} ) {
32             push @PATHEXT, split /;/, $ENV{PATHEXT};
33             } else {
34             # Win9X or other: doesn't have PATHEXT, so needs hardcoded.
35             push @PATHEXT, qw{.com .exe .bat};
36             }
37             } elsif ( IS_VMS ) {
38             push @PATHEXT, qw{.exe .com};
39             } elsif ( IS_CYG ) {
40             # See this for more info
41             # http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe
42             push @PATHEXT, qw{.exe .com};
43             }
44              
45              
46             sub which {
47 8     8 1 4304 my ($exec) = @_;
48              
49 8 50       38 return undef unless defined $exec;
50 8 100       23 return undef if $exec eq '';
51              
52 6         11 my $all = wantarray; ## no critic (Freenode::Wantarray)
53 6         10 my @results = ();
54              
55             # check for aliases first
56 6         8 if ( IS_VMS ) {
57             my $symbol = `SHOW SYMBOL $exec`;
58             chomp($symbol);
59             unless ( $? ) {
60             return $symbol unless $all;
61             push @results, $symbol;
62             }
63             }
64 6         8 if ( IS_MAC ) {
65             my @aliases = split /\,/, $ENV{Aliases};
66             foreach my $alias ( @aliases ) {
67             # This has not been tested!!
68             # PPT which says MPW-Perl cannot resolve `Alias $alias`,
69             # let's just hope it's fixed
70             if ( lc($alias) eq lc($exec) ) {
71             chomp(my $file = `Alias $alias`);
72             last unless $file; # if it failed, just go on the normal way
73             return $file unless $all;
74             push @results, $file;
75             # we can stop this loop as if it finds more aliases matching,
76             # it'll just be the same result anyway
77             last;
78             }
79             }
80             }
81              
82 6 0 33     23 return $exec ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
      33        
83             if !IS_VMS and !IS_MAC and !IS_WIN and $exec =~ /\// and -f $exec and -x $exec;
84              
85 6         8 my @path;
86 6 50       20 if($^O eq 'MSWin32') {
87             # File::Spec (at least recent versions)
88             # add the implicit . for you on MSWin32,
89             # but we may or may not want to include
90             # that.
91 0         0 @path = split /;/, $ENV{PATH};
92 0         0 s/"//g for @path;
93 0         0 @path = grep length, @path;
94             } else {
95 6         64 @path = File::Spec->path;
96             }
97 6 50       15 if ( $IMPLICIT_CURRENT_DIR ) {
98 0         0 unshift @path, File::Spec->curdir;
99             }
100              
101 6         12 foreach my $base ( map { File::Spec->catfile($_, $exec) } @path ) {
  23         154  
102 17         30 for my $ext ( @PATHEXT ) {
103 17         33 my $file = $base.$ext;
104              
105             # We don't want dirs (as they are -x)
106 17 50       284 next if -d $file;
107              
108 17 100 100     91 if (
109             # Executable, normal case
110             -x _
111             or (
112             # MacOS doesn't mark as executable so we check -e
113             IS_MAC ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
114             ||
115             (
116             ( IS_WIN or IS_CYG )
117             and
118             grep { ## no critic (BuiltinFunctions::ProhibitBooleanGrep)
119             $file =~ /$_\z/i
120             } @PATHEXT[1..$#PATHEXT]
121             )
122             # DOSish systems don't pass -x on
123             # non-exe/bat/com files. so we check -e.
124             # However, we don't want to pass -e on files
125             # that aren't in PATHEXT, like README.
126             and -e _
127             )
128             ) {
129 5 100       36 return $file unless $all;
130 2         9 push @results, $file;
131             }
132             }
133             }
134              
135 3 100       10 if ( $all ) {
136 2         10 return @results;
137             } else {
138 1         8 return undef;
139             }
140             }
141              
142              
143             sub where {
144             # force wantarray
145 1     1 1 958 my @res = which($_[0]);
146 1         6 return @res;
147             }
148              
149             1;
150              
151             __END__