#!/usr/bin/perl # # Copyright © 1995, 1996 Jörg Wunsch # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # whereis -- search for binaries, man pages and source directories. # # Rewritten from scratch for FreeBSD after the 4.3BSD manual page. # # $FreeBSD: src/usr.bin/whereis/whereis.pl,v 1.8 1999/08/28 01:07:37 peter Exp $ # $DragonFly: src/usr.bin/whereis/Attic/whereis.pl,v 1.2 2003/06/17 04:29:33 dillon Exp $ # sub usage { print STDERR "usage: $0 [-bms] [-u] [-BMS dir... -f] name ...\n"; exit 1; } sub scanopts { local($i, $j); arg: while ($ARGV[$i] =~ /^-/) { opt: for ($j = 1; $j < length($ARGV[$i]); $j++) { local($_) = substr($ARGV[$i], $j, 1); local($what, @list); $opt_b++, next opt if /b/; $opt_m++, next opt if /m/; $opt_s++, next opt if /s/; $opt_u++, next opt if /u/; &usage unless /[BMS]/; # directory list processing $what = $_; @list = (); push(@list, substr($ARGV[$i], $j+1)) if $j+1 < length($ARGV[$i]); $i++; while ($i <= $#ARGV && $ARGV[$i] !~ /^-/) { push(@list, $ARGV[$i++]); } if ($what eq "B") {@binaries = @list;} elsif ($what eq "M") {@manuals = @list;} elsif ($what eq "S") {@sources = @list;} $i++, last arg if $ARGV[$i] =~ /^-f$/; next arg; } $i++; } &usage if $i > $#ARGV; while ($ARGV[$i]) { push(@names, $ARGV[$i++]); } } sub decolonify { local($list) = @_; local($_, @rv); foreach(split(/:/, $list)) { push(@rv, $_); } return @rv; } &scanopts; # default to all if no type requested if ($opt_b + $opt_m + $opt_s == 0) {$opt_b = $opt_m = $opt_s = 1;} if (!defined(@binaries)) { # # first, use default path, then append /usr/libexec and the user's path # local($cs_path) = `/sbin/sysctl -n user.cs_path`; local(@list, %path); chop($cs_path); @list = &decolonify($cs_path); push(@list, "/usr/libexec"); push(@list, &decolonify($ENV{'PATH'})); # resolve ~, remove duplicates foreach (@list) { s/^~/$ENV{'HOME'}/ if /^~/; push(@binaries, $_) if !$path{$_}; $path{$_}++; } } if (!defined(@manuals)) { # # first, use default manpath, then append user's $MANPATH # local($usermanpath) = $ENV{'MANPATH'}; delete $ENV{'MANPATH'}; local($manpath) = `/usr/bin/manpath`; local(@list, %path, $i); chop($manpath); @list = &decolonify($manpath); push(@list, &decolonify($usermanpath)); # remove duplicates foreach (@list) { push(@manuals, $_) if !$path{$_}; $path{$_}++; } } if (!defined(@sources)) { # # default command sources # local($_); @sources = ("/usr/src/bin", "/usr/src/usr.bin", "/usr/src/sbin", "/usr/src/usr.sbin", "/usr/src/libexec", "/usr/src/gnu/bin", "/usr/src/gnu/usr.bin", "/usr/src/gnu/sbin", "/usr/src/gnu/usr.sbin", "/usr/src/gnu/libexec", "/usr/src/contrib"); # # if /usr/ports exists, look in all its subdirs, too # if (-d "/usr/ports" && opendir(PORTS, "/usr/ports")) { while ($_ = readdir(PORTS)) { next if /^\.\.?$/; next if /^distfiles$/; # magic next if ! -d "/usr/ports/$_"; push(@sources, "/usr/ports/$_"); } closedir(PORTS); } } if ($opt_m) { # construct a new MANPATH foreach (@manuals) { next if ! -d $_; if ($manpath) { $manpath .= ":$_"; } else { $manpath = $_; } } } # # main loop # foreach $name (@names) { $name =~ s|^.*/||; # strip leading path name component $name =~ s/,v$//; $name =~ s/^s\.//; # RCS or SCCS suffix/prefix $name =~ s/\.(Z|z|gz)$//; # compression suffix $line = ""; $unusual = 0; if ($opt_b) { # # Binaries have to match exactly, and must be regular executable # files. # $unusual++; foreach (@binaries) { $line .= " $_/$name", $unusual--, last if -f "$_/$name" && -x _; } } if ($opt_m) { # # Ask the man command to do the search for us. # $unusual++; chop($result = `man -S 1:8 -M $manpath -w $name 2> /dev/null`); if ($result ne '') { $unusual--; ($cat, $junk, $src) = split(/[() \t\n]+/, $result); if ($src ne '') { $line .= " $src"; } else { $line .= " $cat"; } } } if ($opt_s) { # # Sources match if a subdir with the exact name is found. # $found = 0; $unusual++; foreach (@sources) { $line .= " $_/$name", $unusual--, $found++ if -d "$_/$name"; } # # If not yet found, ask locate(1) to do the search for us. # This will find sources for things like lpr, but take longer. # Do only match locate output that starts with one of our # source directories, and at least one further level of # subdirectories. # if (!$found && open(LOCATE, "locate */$name 2>/dev/null |")) { locate_item: while (chop($loc = )) { foreach (@sources) { $line .= " $loc", $unusual--, last locate_item if $loc =~ m|^$_/[^/]+/|; } } close(LOCATE); } } if ($opt_u) { print "$name:\n" if $unusual; } else { print "$name:$line\n"; } }