Naposledy aktivní 1 month ago

Revize c4dced7fa49c598bf86df77b975df82473b041a7

brut.sh Raw
1#!/bin/sh
2# Brutal Router for Unix Tools - https://brut.sh
3set -eu
4
5
6# Find ourselves
7OLDENV="$(export -p)"
8SELF="$(realpath "$0")"
9NAME="${0##*/}"
10PROGRAM_NAME="${SELF##*/}"
11ROOT="${SELF%/*/*}"
12
13
14# Set up the environment
15LIB="$ROOT/lib/$NAME"
16LIBEXEC="$ROOT/libexec"
17SHARE="$ROOT/share/$NAME"
18VENDOR="$SHARE/vendor"
19
20PATH="$LIB:$LIBEXEC:$VENDOR:$PATH"
21export SELF
22
23USAGE="<COMMAND>"
24unset VERSION
25
26
27# ---
28# Define shared helpers
29
30error() {
31 NAME="${1##*/}"
32 shift
33
34 printf "%s: " "$(invocation)"
35 printf "%s\n" "$@"
36 return 1
37} >&2
38
39usage() {
40 if [ $# -eq 0 ]; then
41 set -- "$NAME" "${USAGE:-}" "commands: $(flatten commands)"
42 fi
43
44 NAME="${1##*/}"
45 shift
46
47 printf "usage: %s " "$(invocation)"
48 printf "%s\n" "$@"
49 return 1
50} >&2
51
52version() {
53 printf "%s %s\n" "$PROGRAM_NAME" "$VERSION"
54}
55
56# ---
57
58commands() {
59 executables | sed -e "s/^.*\/$NAME-//" | sort
60}
61
62executables() {
63 for ns in $(namespaces "$NAME-"); do
64 set -- "$@" \! -name "$ns-*"
65 done
66
67 searchpath -name "$NAME-*" "$@" | awk -F / '!a[$NF]++'
68}
69
70flatten() {
71 "$@" | xargs -r printf "%s "
72}
73
74invocation() {
75 { printf "%s\n" "$PROGRAM_NAME"; namespaces; } \
76 | awk -v i=-1 -v name="$NAME" \
77 'index(name, $0 "-") == 1 { o = o " " substr($0, i+2); i = length($0) }
78 END { print substr(o " " substr(name, i+2), 2) }'
79}
80
81namespaces() {
82 searchpath -type l -name "${1:-$PROGRAM_NAME-}*" \
83 -exec sh -c '[ "$0" = "$(realpath "$1")" ] 2>/dev/null' "$SELF" {} \; \
84 | sed -e "s/^.*\///" | sort -u
85}
86
87resolve() {
88 case "${1:-}" in
89 *-* ) executables -name "$NAME-$1" ;;
90 ?* ) searchpath -name "$NAME-$1" | head -n 1
91 esac | grep .
92}
93
94searchpath() {
95 { IFS=:
96 set -- \) -o -prune "$@"
97 for dir in $PATH; do
98 set -- -o -path "$dir" "$@"
99 done
100 set -- $PATH \( \! -name '*' "$@"
101 unset IFS
102 } 2>/dev/null
103
104 find -H "$@" 2>/dev/null \
105 \( -perm -001 -o -perm -010 -o -perm -100 \) \
106 \( -type f -o -type l \) \
107 \! -name "?*--?*" \
108 -print || true
109}
110
111unenv() {
112 exec env -i sh -euc 'eval "$1"; shift; exec "$@"' "$0" "$OLDENV" "$@"
113}
114
115# ---
116
117
118# Load _init.sh, if it exists
119if [ -r "$LIB"/_init.sh ]; then
120 . "$LIB"/_init.sh
121fi
122
123
124# Rewrite `--version` to `--- version`
125if [ $# -eq 1 ] && [ -n "${VERSION:-}" ] && [ "$1" = "--version" ]; then
126 set -- --- version
127fi
128
129
130# When invoked as `--- <COMMAND> ...`, run that command and exit
131if [ "${1:-}" = "---" ]; then
132 [ $# -gt 1 ] || usage
133 shift
134 "$@"
135 exit
136fi
137
138
139# Scan the argument list to find the command name
140COMMAND=
141args=
142index=0
143
144for arg; do
145 index=$((index+1))
146
147 case "$arg" in
148 -* ) ;;
149 ?*--?* ) [ -n "$COMMAND" ] || usage ;;
150 * )
151 if [ -z "$COMMAND" ]; then
152 COMMAND="$arg"
153 continue
154 fi
155 esac
156
157 args="$args"' "${'"$index"'}"'
158done
159
160
161# Match the command name to an executable in the current namespace;
162# if one exists, exec it
163if executable="$(resolve "$COMMAND")"; then
164 eval "set --$args"
165 exec "$executable" "$@"
166fi
167
168
169# No matching executable; load _unhandled.sh, if it exists
170if [ -r "$LIB"/_unhandled.sh ]; then
171 . "$LIB"/_unhandled.sh
172fi
173
174
175# No matching command or no command specified
176if [ -n "$COMMAND" ]; then
177 error "$0" "$COMMAND: command not found" || exit 127
178fi
179
180usage
181