blob: fd8faa5d27b73eb0c26200724ff89ebe6c45257b (
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
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
|
#!/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##*/}
[ -n "$PATH" ] || die 'PATH is empty'
case "$orig_exe" in
*/)
die 'ends with /'
;;
*/*)
orig_dir=${orig_exe%/*}
;;
*)
# either shell has not resolved script-file into a path, or script is
# in cwd and PATH has . or empty entries
if ! [ -d "$orig_exe" ] && [ -x "$orig_exe" ]; then
case ":$PATH:" in
*::*:.:*|*:.:*::*)
die 'exe in cwd and PATH has both . and empty entries'
;;
*::*)
orig_dir=
;;
*:.:*)
orig_dir=.
;;
*)
die 'missing /'
esac
fi
esac
tmp_path=:$PATH:
new_path=${tmp_path#*:$orig_dir:}
[ -n "$new_path" ] \
|| die '%s is last PATH entry' "$orig_dir"
if [ "$new_path" != "$tmp_path" ]; then
new_path_2=${new_path#*:$orig_dir:}
[ "$new_path" = "$new_path_2" ] \
|| die 'duplicate entry in PATH: %s' \
"$orig_exe" "$orig_dir"
else
# try to find equivalent path
found_alt_dir=
new_orig_dir=
equiv_orig_dir=$(cd "${orig_dir:-.}" && pwd -L)
tmp_path_2=$PATH
while :; do
p=${tmp_path_2%%:*}
if [ "$(cd "$p" >/dev/null 2>&1 && pwd -L)" = "$equiv_orig_dir" ]; then
[ -z "$found_alt_dir" ] \
|| die "duplicate equivalent path in PATH: '%s' = '%s'" \
"$new_orig_dir" "$p"
found_alt_dir=1
new_orig_dir=$p
fi
case "$tmp_path_2" in
*:*) tmp_path_2=${tmp_path_2#*:};;
*) break
esac
done
if [ -n "$found_alt_dir" ]; then
new_path=${tmp_path#*:$new_orig_dir:}
[ -n "$new_path" ] \
|| die '%s is last PATH entry' "$new_orig_dir"
else
new_path=$PATH:
fi
fi
exe=$(PATH="${new_path%:}" command -v "$exe_name") || true
[ -n "$exe" ] \
|| die 'PATH lookup failed using %s' \
"${new_path%:}"
$action "$exe" "$@"
|