Which.pm
Go to the documentation of this file.
1 # Original package File::Which downloaded from CPAN on 6/15/2012. This module
2 # has been modified by Andreas Schuh on 6/15/2012 to make it part of BASIS.
3 
4 package BASIS::File::Which;
5 
6 use 5.004;
7 use strict;
8 use Exporter ();
9 use File::Spec ();
10 
11 use vars qw{$VERSION @ISA @EXPORT @EXPORT_OK};
12 BEGIN {
13  $VERSION = '1.09';
14  @ISA = 'Exporter';
15  @EXPORT = 'which';
16  @EXPORT_OK = 'where';
17 }
18 
19 use constant IS_VMS => ($^O eq 'VMS');
20 use constant IS_MAC => ($^O eq 'MacOS');
21 use constant IS_DOS => ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2');
22 
23 # For Win32 systems, stores the extensions used for
24 # executable files
25 # For others, the empty string is used
26 # because 'perl' . '' eq 'perl' => easier
27 my @PATHEXT = ('');
28 if ( IS_DOS ) {
29  # WinNT. PATHEXT might be set on Cygwin, but not used.
30  if ( $ENV{PATHEXT} ) {
31  push @PATHEXT, split ';', $ENV{PATHEXT};
32  } else {
33  # Win9X or other: doesn't have PATHEXT, so needs hardcoded.
34  push @PATHEXT, qw{.com .exe .bat};
35  }
36 } elsif ( IS_VMS ) {
37  push @PATHEXT, qw{.exe .com};
38 }
39 
40 sub which {
41  my ($exec) = @_;
42 
43  return undef unless $exec;
44 
45  # in case of absolute paths, return whether file exists or not
46  if (File::Spec->file_name_is_absolute($exec)) {
47  stat($exec);
48  if (
49  # Executable, normal case
50  -x _
51  or (
52  # MacOS doesn't mark as executable so we check -e
53  IS_MAC
54  ||
55  (
56  IS_DOS
57  and
58  grep {
59  $exec =~ /$_\z/i
60  } @PATHEXT[1..$#PATHEXT]
61  )
62  # DOSish systems don't pass -x on
63  # non-exe/bat/com files. so we check -e.
64  # However, we don't want to pass -e on files
65  # that aren't in PATHEXT, like README.
66  and -e _
67  )
68  ) {
69  return $exec;
70  }
71  # absolute file path is not an executable file
72  return undef;
73  }
74 
75  my $all = wantarray;
76  my @results = ();
77 
78  # check for aliases first
79  if ( IS_VMS ) {
80  my $symbol = `SHOW SYMBOL $exec`;
81  chomp($symbol);
82  unless ( $? ) {
83  return $symbol unless $all;
84  push @results, $symbol;
85  }
86  }
87  if ( IS_MAC ) {
88  my @aliases = split /\,/, $ENV{Aliases};
89  foreach my $alias ( @aliases ) {
90  # This has not been tested!!
91  # PPT which says MPW-Perl cannot resolve `Alias $alias`,
92  # let's just hope it's fixed
93  if ( lc($alias) eq lc($exec) ) {
94  chomp(my $file = `Alias $alias`);
95  last unless $file; # if it failed, just go on the normal way
96  return $file unless $all;
97  push @results, $file;
98  # we can stop this loop as if it finds more aliases matching,
99  # it'll just be the same result anyway
100  last;
101  }
102  }
103  }
104 
105  my @path = File::Spec->path;
106  if ( IS_DOS or IS_VMS or IS_MAC ) {
107  unshift @path, File::Spec->curdir;
108  }
109 
110  foreach my $base ( map { File::Spec->catfile($_, $exec) } @path ) {
111  for my $ext ( @PATHEXT ) {
112  my $file = $base.$ext;
113 
114  # We don't want dirs (as they are -x)
115  next if -d $file;
116 
117  if (
118  # Executable, normal case
119  -x _
120  or (
121  # MacOS doesn't mark as executable so we check -e
122  IS_MAC
123  ||
124  (
125  IS_DOS
126  and
127  grep {
128  $file =~ /$_\z/i
129  } @PATHEXT[1..$#PATHEXT]
130  )
131  # DOSish systems don't pass -x on
132  # non-exe/bat/com files. so we check -e.
133  # However, we don't want to pass -e on files
134  # that aren't in PATHEXT, like README.
135  and -e _
136  )
137  ) {
138  return $file unless $all;
139  push @results, $file;
140  }
141  }
142  }
143 
144  if ( $all ) {
145  return @results;
146  } else {
147  return undef;
148  }
149 }
150 
151 sub where {
152  # force wantarray
153  my @res = which($_[0]);
154  return @res;
155 }
156 
157 1;
158 
159 __END__
160 
161 =pod
162 
163 =head1 NAME
164 
165 BASIS::File::Which - Portable implementation of the `which' utility
166 
167 =head1 SYNOPSIS
168 
169  use BASIS::File::Which; # exports which()
170  use BASIS::File::Which qw(which where); # exports which() and where()
171 
172  my $exe_path = which('perldoc');
173 
174  my @paths = where('perl');
175  - Or -
176  my @paths = which('perl'); # an array forces search for all of them
177 
178 =head1 DESCRIPTION
179 
180 C<BASIS::File::Which> was created to be able to get the paths to executable programs
181 on systems under which the `which' program wasn't implemented in the shell.
182 
183 C<BASIS::File::Which> searches the directories of the user's C<PATH> (as returned by
184 C<File::Spec-E<gt>path()>), looking for executable files having the name
185 specified as a parameter to C<which()>. Under Win32 systems, which do not have a
186 notion of directly executable files, but uses special extensions such as C<.exe>
187 and C<.bat> to identify them, C<BASIS::File::Which> takes extra steps to assure that
188 you will find the correct file (so for example, you might be searching for
189 C<perl>, it'll try F<perl.exe>, F<perl.bat>, etc.)
190 
191 Original package is File::Which downloaded from CPAN. This module has been modified
192 by Andreas Schuh on 6/15/2012 in order to make it a subpackage of the SBIA namespace.
193 
194 =head1 Steps Used on Win32, DOS, OS2 and VMS
195 
196 =head2 Windows NT
197 
198 Windows NT has a special environment variable called C<PATHEXT>, which is used
199 by the shell to look for executable files. Usually, it will contain a list in
200 the form C<.EXE;.BAT;.COM;.JS;.VBS> etc. If C<BASIS::File::Which> finds such an
201 environment variable, it parses the list and uses it as the different
202 extensions.
203 
204 =head2 Windows 9x and other ancient Win/DOS/OS2
205 
206 This set of operating systems don't have the C<PATHEXT> variable, and usually
207 you will find executable files there with the extensions C<.exe>, C<.bat> and
208 (less likely) C<.com>. C<BASIS::File::Which> uses this hardcoded list if it's running
209 under Win32 but does not find a C<PATHEXT> variable.
210 
211 =head2 VMS
212 
213 Same case as Windows 9x: uses C<.exe> and C<.com> (in that order).
214 
215 =head1 Functions
216 
217 =head2 which($short_exe_name)
218 
219 Exported by default.
220 
221 C<$short_exe_name> is the name used in the shell to call the program (for
222 example, C<perl>).
223 
224 If it finds an executable with the name you specified, C<which()> will return
225 the absolute path leading to this executable (for example, F</usr/bin/perl> or
226 F<C:\Perl\Bin\perl.exe>).
227 
228 If it does I<not> find the executable, it returns C<undef>.
229 
230 If C<which()> is called in list context, it will return I<all> the
231 matches.
232 
233 =head2 where($short_exe_name)
234 
235 Not exported by default.
236 
237 Same as C<which($short_exe_name)> in array context. Same as the
238 C<`where'> utility, will return an array containing all the path names
239 matching C<$short_exe_name>.
240 
241 =head1 BUGS AND CAVEATS
242 
243 Not tested on VMS or MacOS, although there is platform specific code
244 for those. Anyone who haves a second would be very kind to send me a
245 report of how it went.
246 
247 File::Spec adds the current directory to the front of PATH if on
248 Win32, VMS or MacOS. I have no knowledge of those so don't know if the
249 current directory is searced first or not. Could someone please tell
250 me?
251 
252 =head1 SUPPORT
253 
254 Bugs should be reported via the CPAN bug tracker at
255 
256 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=File-Which>
257 
258 For other issues, contact the maintainer.
259 
260 =head1 AUTHOR
261 
262 Andreas Schuh E<lt>andreas.schuh.84@googlemail.comE<gt>
263 
264 Adam Kennedy E<lt>adamk@cpan.orgE<gt>
265 
266 Per Einar Ellefsen E<lt>pereinar@cpan.orgE<gt>
267 
268 Modified by Andreas Schuh on 6/15/2012 in order to make it a subpackage
269 of the SBIA namespace for inclusion with the BASIS package. Moreover,
270 changed which() function to deal with given absolute file paths differently.
271 
272 Originated in F<modperl-2.0/lib/Apache/Build.pm>. Changed for use in DocSet
273 (for the mod_perl site) and Win32-awareness by me, with slight modifications
274 by Stas Bekman, then extracted to create C<BASIS::File::Which>.
275 
276 Version 0.04 had some significant platform-related changes, taken from
277 the Perl Power Tools C<`which'> implementation by Abigail with
278 enhancements from Peter Prymmer. See
279 L<http://www.perl.com/language/ppt/src/which/index.html> for more
280 information.
281 
282 =head1 COPYRIGHT
283 
284 Copyright 2002 Per Einar Ellefsen.
285 
286 Some parts copyright 2009 Adam Kennedy.
287 Some parts copyright 2012 University of Pennsylvania.
288 
289 This program is free software; you can redistribute it and/or modify
290 it under the same terms as Perl itself.
291 
292 =head1 SEE ALSO
293 
294 L<File::Spec>, L<which(1)>, Perl Power Tools:
295 L<http://www.perl.com/language/ppt/index.html>.
296 
297 =cut