#!/bin/sh set -eu # Brutal Router for Unix Tools # https://brut.sh # Copyright (c) Sam Stephenson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # “Software”), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Get our bearings OLDENV="$(export -p)" SELF="$(realpath "$0")" NAME="${0##*/}" PROGRAM_NAME="${SELF##*/}" ROOT="${SELF%/*/*}" # Set up the environment LIB="$ROOT/lib/$NAME" LIBEXEC="$ROOT/libexec" SHARE="$ROOT/share/$PROGRAM_NAME" VENDOR="$SHARE/vendor" PATH="$LIB:$LIBEXEC:$VENDOR:$PATH" export SELF USAGE="" unset VERSION # --- # Define shared helpers error() { printf "%s: " "$(invocation "${1##*/}")" shift printf "%s\n" "$@" return 1 } >&2 usage() { [ $# -gt 0 ] || set -- "$NAME" "${USAGE:-}" "commands: $(flatten commands)" printf "usage: %s " "$(invocation "${1##*/}")" shift printf "%s\n" "$@" return 1 } >&2 version() { printf "%s %s\n" "$PROGRAM_NAME" "$VERSION" } # --- awka() { awk "BEGIN { ARGC = 1; a = ARGV[1] } $2" "$1" } commands() { executables \ | awka ${#NAME} 'BEGIN { FS = "/" } { print substr($NF, a+2) }' | sort } executables() { for ns in $(namespaces "$NAME"); do set -- "$@" \! -name "$ns-*" done 2>/dev/null searchpath -name "$NAME-*" "$@" \ | awk -F / '!a[$NF]++' } flatten() { "$@" | { tr "\n" " "; printf "\n"; } } invocation() { { printf "%s\n" "$PROGRAM_NAME"; namespaces "$PROGRAM_NAME"; } | sort -r \ | awka "${1:-$NAME}" \ 'index(a, $0 "-") == 1 { a = $0 " " substr(a, length($0) + 2) } END { print a }' } namespaces() { searchpath -type l -name "${1:-$NAME}-*" \ -exec sh -c '[ "$0" = "$(realpath "$1")" ] 2>/dev/null' "$SELF" {} \; \ | awk -F / '{ print $NF }' | sort -u } resolve() { case "${1:-}" in *-* ) executables ;; ?* ) searchpath -name "$NAME-*" esac \ | awka "$NAME-${1:-}" \ 'BEGIN { FS = "/" } $NF == a { print; s = 1; exit } END { exit !s }' } searchpath() { { IFS=: dirs= set -- \) -o -prune "$@" for dir in $PATH; do [ -d "$dir" ] || continue set -- -o -path "$dir" "$@" dirs="$dirs:$dir" done set -- ${dirs#:} \( \! -name "*" "$@" unset IFS } 2>/dev/null find -H "$@" 2>/dev/null \ \( -perm -001 -o -perm -010 -o -perm -100 \) \ \( -type f -o -type l \) \ \! -name "?*--?*" \ -print || true } # --- # Load _init.sh, if it exists if [ -r "$LIB"/_init.sh ]; then . "$LIB"/_init.sh fi # Rewrite `--version` to `--- version` if [ $# -eq 1 ] && [ -n "${VERSION:-}" ] && [ "$1" = "--version" ]; then set -- --- version fi # When invoked as `--- ...`, run that exact command and exit if [ "${1:-}" = "---" ]; then [ $# -gt 1 ] && shift || usage "$@" exit fi # Scan the argument list to find the command name COMMAND= args= index=0 for arg; do index=$((index+1)) case "$arg" in -* ) ;; ?*--?* | "" ) [ -n "$COMMAND" ] || usage ;; * ) if [ -z "$COMMAND" ]; then COMMAND="$arg" continue fi esac args="$args"' "${'"$index"'}"' done # Match the command name to an executable in the current namespace; # if one exists, exec it if executable="$(resolve "$COMMAND")"; then eval "set --$args" exec "$executable" "$@" fi # No matching executable; load _unhandled.sh, if it exists if [ -r "$LIB"/_unhandled.sh ]; then . "$LIB"/_unhandled.sh fi # No matching command or no command specified if [ -n "$COMMAND" ]; then error "$0" "$COMMAND: command not found" || exit 127 fi usage