/usr/bin/envpath is in libenv-path-perl 0.19-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | #!/usr/bin/perl
use File::Basename;
use Getopt::Long;
use constant MSWIN => $^O =~ /MSWin32|Windows_NT/i ? 1 : 0;
sub usage {
my $msg = shift;
my $rc = (defined($msg) && !$msg) ? 0 : 2;
if ($rc) {
select STDERR;
print $msg if $msg && $msg =~ /^\d+$/;
}
my $prog = basename($0, qw(.pl));
print <<EOF;
Usage: $prog [VAR=TOKEN,TOKEN,...] ... [-N] [-U]
[-E VAR [-A TOKEN] [-P TOKEN] [-I dir,-|+TOKEN]] [-C old=new]
[--] command ...
$prog [VAR=TOKEN,TOKEN,...] [-E VAR] -L|-S
Flags:
-help Print this message and exit
-A TOKEN Append TOKEN to the path variable named 'VAR'
-C olddir=newdir Change <olddir> to <newdir> within 'VAR'
-P TOKEN Prepend TOKEN to the path variable named 'VAR'
-I dir,(-|+)TOKEN] Insert TOKEN before (-) or after (+) 'dir' in VAR
-L [VAR] List specified pathvar(s) in one-entry-per-line fmt
-N Remove entries which don't exist
-R TOKEN Remove specified dir from path
-S [VAR] Print specified pathvars in form suitable for `eval`
-U Remove redundant entries from path
-W file Like 'whence' ksh builtin - look for 'file' on PATH
Examples:
$prog PATH=/tools/\@PLATFORM@/bin,\@PATH@ -- printenv PATH
$prog CLASSPATH=\@CLASSPATH@,\@JAVA_HOME@/classes printenv CLASSPATH
$prog -E LD_RUN_PATH -A /usr/openwin/lib -U -- ld ...
$prog -E LD_RUN_PATH -I /usr/openwin/lib,-\@LD_LIBRARY_PATH@ ld ...
$prog -L
$prog -E CLASSPATH -L
$prog -C /opt/netscape=/usr/local/netscape -L
eval `$prog -N -U -R /usr/ucb -S`
eval `$prog -E LD_RUN_PATH -I /usr/openwin/lib,-/usr/local/lib -S`
$prog -W cat
In the above, TOKEN refers to a string which may optionally contain
references to environment variables in the form \@VAR@. These will be
replaced by the value \$VAR, and the commas will be replaced by the
appropriate path separator (':' or ';') for the current platform.
See "perldoc $prog" and "perldoc Env::Path" for full documentation.
EOF
exit $rc;
}
sub expand {
my $ev = shift;
while (my($token) = ($ev =~ m%@(\w+)@%)) {
$ev =~ s%\@$token@%$ENV{$token}%;
}
return $ev;
}
usage() if !@ARGV;
my @Paths;
while (my($var, $where, $str) = ($ARGV[0] =~ m%^(\w+)([=+]+)(.*)%)) {
my $param = shift;
push(@Paths, $var);
my @val = split(/,/, $str);
for (@val) { $_ = expand($_) }
my $dsep = MSWIN ? ';' : ':';
if ($where eq '=') {
$ENV{$var} = join($dsep, @val);
} elsif ($where eq '+=') {
$ENV{$var} = join($dsep, @val, $ENV{$var});
} elsif ($where eq '=+') {
$ENV{$var} = join($dsep, $ENV{$var}, @val);
} else {
die "Error: $0: malformed parameter '$param'\n";
}
}
my %opt;
my($opt_help, $opt_verbose);
{
local $Getopt::Long::passthrough = 1;
GetOptions('help' => \$opt_help, 'verbose' => \$opt_verbose);
usage() if $opt_help;
}
local $Getopt::Long::order = $REQUIRE_ORDER;
GetOptions(\%opt, qw(Env=s
Append=s@ Change=s@ Prepend=s@ Insert=s@ Remove=s@
Nonexistent Uniqify
List:s@ Shell:s@ Whence=s)
);
usage() if !@ARGV && !($opt{List} || $opt{Shell} || $opt{Whence});
if (%opt) {
require Env::Path;
push(@Paths, $opt{Env}) if $opt{Env};
push(@Paths, @{$opt{List}}) if $opt{List}->[0];
push(@Paths, @{$opt{Shell}}) if $opt{Shell}->[0];
push(@Paths, 'PATH') if !@Paths;
my $var = $Paths[-1] || 'PATH';
my $path = eval "Env::Path->$var";
for (@{$opt{Prepend}}) { $path->Prepend(expand($_)) }
for (@{$opt{Append}}) { $path->Append(expand($_)) }
for (@{$opt{Remove}}) { $path->Remove(expand($_)) }
for (@{$opt{Change}}) {
my($old, $new) = split '=', $_, 2;
$path->InsertBefore($old, $new);
$path->Remove(expand($old))
}
$path->DeleteNonexistent if $opt{Nonexistent};
$path->Uniqify if $opt{Uniqify};
for (@{$opt{Insert}}) {
if (!m%^(.+?),([+-])(.*)%) {
warn "Warning: $0: malformed -Insert parameter '$_'\n";
next;
}
my($marker, $where, $insert) = (expand($1), $2, expand($3));
if ($where eq '-') {
$path->InsertBefore($marker, $insert);
} else {
$path->InsertAfter($marker, $insert);
}
}
if ($opt{List} && @{$opt{List}}) {
usage(2) if ($opt{Shell} && @{$opt{Shell}}) || $opt{Whence};
for my $pathvar (@Paths) {
my $path = eval "Env::Path->$pathvar";
for ($path->List) { print $_, "\n" }
}
exit 0;
} elsif ($opt{Shell} && @{$opt{Shell}}) {
usage(2) if $opt{Whence};
for my $pathvar (@Paths) {
print Env::Path->$pathvar->Shell, "\n";
}
exit 0;
} elsif ($opt{Whence}) {
for my $pathvar (@Paths) {
my $path = eval "Env::Path->$pathvar";
for ($path->Whence($opt{Whence})) { print $_, "\n" }
}
exit 0;
}
}
print STDERR "+ @ARGV\n" if $opt_verbose;
if (MSWIN) {
exit system @ARGV;
} else {
exec @ARGV;
die "$0: $ARGV[0]: $!\n";
}
__END__
=head1 NAME
envpath - Advanced operations on path variables
=head1 SYNOPSIS
Run this script with the C<-help> option for usage details.
=head1 DESCRIPTION
Parses the command line, modifies the specified path variable(s), and
execs the remaining arguments. There are two modes, B<simple> and
B<advanced>:
=head2 SIMPLE MODE
Simple mode presents an alternative, platform-independent syntax for
specifying paths wherein the path separator is "," and environment
variables can be expanded with @NAME@. For example
envpath PATH=@PATH@,/usr/ucb -- printenv PATH
appends C</usr/ucb> to C<$PATH> and execs I<printenv PATH>. The C<-->
is optional.
You can also specify prepending or appending by using C<+=> or C<=+>
respectively:
# place /usr/ucb at the front
envpath PATH+=/usr/ucb -- printenv PATH
# place /usr/ucb at the back
envpath PATH=+/usr/ucb -- printenv PATH
Simple mode requires only this script; it does not require Env::Path
to be installed.
=head2 ADVANCED MODE
Advanced mode basically provides command-line access to the features of
Env::Path (see), which must be installed. The C<-E> flag selects the
path variable to operate on and other flags specify operations on it.
E.g.
envpath -E MANPATH -A /tmp -R /usr/share/man -N -U -- man ...
would take MANPATH, append /tmp to it, remove any references to
C</usr/share/man>, remove any dirs which don't exist (C<-N>) and
remove redundant entries (C<-U>) before running I<man>.
The -Whence option allows patterns. Thus
envpath -W "cat*"
would find all programs on PATH which match cat*.
=head1 CLEARCASE WINKINS
A big part of the motivation for this script was for use with ClearCase
builds; iff you know or care about ClearCase read on. Typically, during
builds (and not just with ClearCase), pathvars such as PATH, CLASSPATH,
and LD_LIBRARY_PATH must be strictly controlled. One choice is to
force static values of these into the environment during the build
process, another is to simply require/expect users to set their paths
appropriately. Each of these can lead to subtle build or runtime
errors, however, and makes it hard for new users to get up to speed
since their personal environment must be just so.
Another common choice is to use only full pathnames within the
Makefile, avoiding reliance on search paths at all. This is often the
best way to go but can suppress ClearCase winkins. For example, say
you're generating ascii files of some type with a binary executable you
just built:
$(INCDIR)/foo.h: $(BINDIR)/foomaker
$(BINDIR)/foomaker ...
The problem with this is that $(BINDIR) likely contains a platform part
such as 'solaris' or 'hpux', which makes it impossible to wink in the
foo.h file on other platforms even though it's ascii. This same thing
could come up even with a standard pre-built utility that's in
different places on different platforms; C<yacc>, for instance, is in
/usr/bin on Linux and /usr/ccs/bin on Solaris.
You could modify the path on the fly:
$(INCDIR)/foo.h: $(BINDIR)/foomaker
PATH=$(BINDIR)$(SEP)$$PATH foomaker ...
but this suffers from the same problem: since $(BINDIR) and $PATH are
expanded literally within the build script they'll suppress winkins.
Here's a solution using I<envpath>:
$(INCDIR)/foo.h: $(BINDIR)/foomaker
envpath PATH=@BINDIR@,@PATH@ foomaker ...
This hides the evaluation of BINDIR and PATH such that I<clearmake>
never sees anything but the literals, thus clearing the field for
winkins. Of course I<envpath> is capable of doing more than this, but
it's the original reason it was written.
=head1 AUTHOR
David Boyce <dsbperl AT boyski.com>
=head1 COPYRIGHT
Copyright (c) 2000-2001 David Boyce. All rights reserved. This Perl
program is free software; you may redistribute and/or modify it under
the same terms as Perl itself.
=head1 SEE ALSO
perl(1), "perldoc Env::Path"
=cut
|