summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xpathenv55
1 files changed, 55 insertions, 0 deletions
diff --git a/pathenv b/pathenv
new file mode 100755
index 0000000..091deea
--- /dev/null
+++ b/pathenv
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+if [[ $# -eq 0 || $1 = "-h" || $1 = "--help" ]]; then
+ cat >&2 <<EOF
+Usage: $0 [name=/path/to/executable]... -- <command...>
+
+Creates a temporary directory containing symlinks for each of the assignments
+specified on the command line. This directory is prepended to \$PATH when
+exectuing <command...>, with the effect that when the command looks up 'name'
+in \$PATH, it will find /path/to/executable instead of whatever it currently
+refers to in \$PATH.
+EOF
+ if [[ $# -eq 0 ]]; then exit 1; fi
+ exit
+fi
+
+tmpdir=$(mktemp -d)
+trap 'rm -rf "$tmpdir"' EXIT
+
+found_dashes=0
+while [[ $# -gt 0 ]]; do
+ if [[ $1 = "--" ]]; then
+ shift
+ found_dashes=1
+ break
+ fi
+
+ name="${1%%=*}" # remove longest matching suffix
+ path="${1#*=}" # remove shortest matching prefix
+ if [[ ${#name} -eq 0 || ${#path} -eq 0 || ${#name} -ge ${#1} ]]; then
+ # {#name} == {#1} if there was no '=' in the argument to begin with
+ echo >&2 "pathenv: No '=' in argument or no name or path given: '$1'"
+ exit 1
+ elif [[ -n ${name//[^\/]} ]]; then
+ echo >&2 "pathenv: '/' not allowed in name: '$1'"
+ exit 1
+ else
+ ln -s "$(realpath "$path")" "$tmpdir/$name"
+ shift
+ fi
+done
+
+if [[ $found_dashes -eq 0 ]]; then
+ echo >&2 "pathenv: '--' separating assignments and command is mandatory"
+ exit 1
+fi
+
+if [[ $# -eq 0 ]]; then
+ echo >&2 "pathenv: No command given"
+ exit 1
+fi
+
+# don't exec so that we can still cleanup tmpdir afterwards
+PATH="$tmpdir:$PATH" "$@"