blob: 31241efa5fcf682684eb9d45fbb340aa91e6c966 (
plain)
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
|
#!/bin/sh
set -e
die() {
fmt=$1
shift
printf "nextbin %s failed: $fmt\n" "$orig_exe" "$@" >&2
exit 1
}
usage() {
# shellcheck disable=SC2016
echo 'usage: nextbin [-v] "$0" "$@"' >&2
}
case "$1" in
-v) action="echo"; shift;;
-*|'') usage; exit 1;;
*) action="exec"
esac
orig_exe=$1
shift
exe_name=${orig_exe##*/}
case ":$PATH:" in
::) die 'empty PATH not supported' ;;
*:[!/]*) die 'relative PATH elements not supported' ;;
*:*/./*:*|*:*/../*:*) die 'PATH elements containing . or .. not supported' ;;
esac
case $orig_exe in
# theoretically this could be optimized but it's negligible cost
*/*) orig_dir=$(cd -L "${orig_exe%/*}" && pwd -L) ;;
*) orig_dir=$PWD ;;
esac
# clean up path. theoretically we could allow e.g. PATH=/dir://dir but which
# would we match for cd /dir; ./exe
tmp_path=$(printf '%s\n' ":$PATH:" | sed -e 's|/*:|:|g' -e 's|//|/|g')
case $tmp_path in
*:$orig_dir:$orig_dir:*|*:$orig_dir:*:$orig_dir:*)
die 'duplicate entry in PATH: %s' "$orig_dir"
esac
new_path=${tmp_path#*":$orig_dir:"}
new_path=${new_path%:}
exe=$(PATH="$new_path" command -v "$exe_name") || true
[ -n "$exe" ] || die 'PATH lookup failed using %s' "$new_path"
$action "$exe" "$@"
|