1## 2## path -- Deal with program paths 3## Copyright (c) 1998-2008 Ralf S. Engelschall <rse@engelschall.com> 4## 5## This file is part of shtool and free software; you can redistribute 6## it and/or modify it under the terms of the GNU General Public 7## License as published by the Free Software Foundation; either version 8## 2 of the License, or (at your option) any later version. 9## 10## This file is distributed in the hope that it will be useful, 11## but WITHOUT ANY WARRANTY; without even the implied warranty of 12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13## General Public License for more details. 14## 15## You should have received a copy of the GNU General Public License 16## along with this program; if not, write to the Free Software 17## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 18## USA, or contact Ralf S. Engelschall <rse@engelschall.com>. 19## 20 21str_tool="path" 22str_usage="[-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename] [-m|--magic] [-p|--path <path>] <str> [<str> ...]" 23gen_tmpfile=yes 24arg_spec="1+" 25opt_spec="s.r.d.b.m.p:" 26opt_alias="s:suppress,r:reverse,d:dirname,b:basename,m:magic,p:path" 27opt_s=no 28opt_r=no 29opt_d=no 30opt_b=no 31opt_m=no 32opt_p="$PATH" 33 34. ./sh.common 35 36namelist="$*" 37 38# check whether the test command supports the -x option 39if [ -x /bin/sh ] 2>/dev/null; then 40 minusx="-x" 41else 42 minusx="-r" 43fi 44 45# split path string 46paths="`echo $opt_p |\ 47 sed -e 's/^:/.:/' \ 48 -e 's/::/:.:/g' \ 49 -e 's/:$/:./' \ 50 -e 's/:/ /g'`" 51 52# SPECIAL REQUEST 53# translate forward to reverse path 54if [ ".$opt_r" = .yes ]; then 55 if [ "x$namelist" = "x." ]; then 56 rp='.' 57 else 58 rp='' 59 for pe in `IFS="$IFS/"; echo $namelist`; do 60 rp="../$rp" 61 done 62 fi 63 echo $rp | sed -e 's:/$::' 64 shtool_exit 0 65fi 66 67# SPECIAL REQUEST 68# strip out directory or base name 69if [ ".$opt_d" = .yes ]; then 70 echo "$namelist" |\ 71 sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' 72 shtool_exit 0 73fi 74if [ ".$opt_b" = .yes ]; then 75 echo "$namelist" |\ 76 sed -e 's;.*/\([^/]*\)$;\1;' 77 shtool_exit 0 78fi 79 80# MAGIC SITUATION 81# Perl Interpreter (perl) 82if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then 83 rm -f $tmpfile >/dev/null 2>&1 84 touch $tmpfile 85 found=0 86 pc=99 87 for dir in $paths; do 88 dir=`echo $dir | sed -e 's;/*$;;'` 89 nc=99 90 for name in perl perl5 miniperl; do 91 if [ $minusx "$dir/$name" ] && [ ! -d "$dir/$name" ]; then 92 perl="$dir/$name" 93 pv=`$perl -e 'printf("%.3f", $]);'` 94 echo "$pv:$pc:$nc:$perl" >>$tmpfile 95 found=1 96 fi 97 nc=`expr $nc - 1` 98 done 99 pc=`expr $pc - 1` 100 done 101 if [ $found = 1 ]; then 102 perl="`cat $tmpfile | sort -r -u | sed -e 'q' | cut -d: -f4`" 103 rm -f $tmpfile >/dev/null 2>&1 104 echo "$perl" 105 shtool_exit 0 106 fi 107 rm -f $tmpfile >/dev/null 2>&1 108 shtool_exit 1 109fi 110 111# MAGIC SITUATION 112# C pre-processor (cpp) 113if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then 114 echo >$tmpfile.c "#include <assert.h>" 115 echo >>$tmpfile.c "Syntax Error" 116 # 1. try the standard cc -E approach 117 cpp="${CC-cc} -E" 118 (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out 119 my_error=`grep -v '^ *+' $tmpfile.out` 120 if [ ".$my_error" != . ]; then 121 # 2. try the cc -E approach and GCC's -traditional-ccp option 122 cpp="${CC-cc} -E -traditional-cpp" 123 (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out 124 my_error=`grep -v '^ *+' $tmpfile.out` 125 if [ ".$my_error" != . ]; then 126 # 3. try a standalone cpp command in path and lib dirs 127 for path in $paths /lib /usr/lib /usr/local/lib; do 128 path=`echo $path | sed -e 's;/*$;;'` 129 if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then 130 cpp="$path/cpp" 131 break 132 fi 133 done 134 if [ ".$cpp" != . ]; then 135 (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out 136 my_error=`grep -v '^ *+' $tmpfile.out` 137 if [ ".$my_error" != . ]; then 138 # ok, we gave up... 139 cpp='' 140 fi 141 fi 142 fi 143 fi 144 rm -f $tmpfile >/dev/null 2>&1 145 rm -f $tmpfile.c $tmpfile.out >/dev/null 2>&1 146 if [ ".$cpp" != . ]; then 147 echo "$cpp" 148 shtool_exit 0 149 fi 150 shtool_exit 1 151fi 152 153# STANDARD SITUATION 154# iterate over names 155for name in $namelist; do 156 # iterate over paths 157 for path in $paths; do 158 path=`echo $path | sed -e 's;/*$;;'` 159 if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then 160 if [ ".$opt_s" != .yes ]; then 161 echo "$path/$name" 162 fi 163 shtool_exit 0 164 fi 165 done 166done 167 168shtool_exit 1 169 170## 171## manual page 172## 173 174=pod 175 176=head1 NAME 177 178B<shtool path> - B<GNU shtool> command dealing with shell path variables 179 180=head1 SYNOPSIS 181 182B<shtool path> 183[B<-s>|B<--suppress>] 184[B<-r>|B<--reverse>] 185[B<-d>|B<--dirname>] 186[B<-b>|B<--basename>] 187[B<-m>|B<--magic>] 188[B<-p>|B<--path> I<path>] 189I<str> [I<str> ...] 190 191=head1 DESCRIPTION 192 193This command deals with shell C<$PATH> variables. It can find a program 194through one or more filenames given by one or more I<str> arguments. 195It prints the absolute filesystem path to the program displayed on 196C<stdout> plus an exit code of 0 if it was really found. 197 198=head1 OPTIONS 199 200The following command line options are available. 201 202=over 4 203 204=item B<-s>, B<--suppress> 205 206Supress output. Useful to only test whether a program exists with the 207help of the return code. 208 209=item B<-r>, B<--reverse> 210 211Transform a forward path to a subdirectory into a reverse path. 212 213=item B<-d>, B<--dirname> 214 215Output the directory name of I<str>. 216 217=item B<-b>, B<--basename> 218 219Output the base name of I<str>. 220 221=item B<-m>, B<--magic> 222 223Enable advanced magic search for "C<perl>" and "C<cpp>". 224 225=item B<-p>, B<--path> I<path> 226 227Search in I<path>. Default is to search in $PATH. 228 229=back 230 231=head1 EXAMPLE 232 233 # shell script 234 awk=`shtool path -p "${PATH}:." gawk nawk awk` 235 perl=`shtool path -m perl` 236 cpp=`shtool path -m cpp` 237 revpath=`shtool path -r path/to/subdir` 238 239=head1 HISTORY 240 241The B<GNU shtool> B<path> command was originally written by Ralf S. 242Engelschall E<lt>rse@engelschall.comE<gt> in 1998 for B<Apache>. It was 243later taken over into B<GNU shtool>. 244 245=head1 SEE ALSO 246 247shtool(1), which(1). 248 249=cut 250 251