c7cc56f04e7cec733e0217d37b05bebb16427c38 / aldermon/aldermon-install.sh · 22367 bytes · raw
#!/bin/sh
# aldermon-install.sh - one-stop installer / uninstaller for aldermon.
#
# Flow: RECON (checks, nothing changed) -> printed plan -> confirm ->
# ONE root escalation (doas/sudo) -> per-component install with status
# lines -> verify.
#
# Install components (each checked first; skipped when already right, except
# watts + the optional VID answer):
# [1/4] binary+helper install if missing or older than the built
# version; identical/newer left alone (--clean forces).
# The helper FILE is inert without its capability.
# [2/4] /etc config installed only if missing (system-conf edits are
# never clobbered unless --clean).
# [3/4] watts powercap udev rule + RUN chmod helper (energy_uj
# is 0400 root-only and powercap has no devnode).
# Always done - the TUI power panel needs it.
# [4/4] VID (optional) asked at the root stage (y/n): msr udev rule
# (nodes 0440 adm) + cap_sys_rawio+ep on aldermon-msr
# only. open /dev/cpu/N/msr takes TWO gates: DAC
# file-mode first (setcap alone gets EACCES - the cap
# is not CAP_DAC_OVERRIDE), then msr_open()'s
# capable(CAP_SYS_RAWIO) (chmod alone gets EPERM).
# Declining leaves VID showing "no msr access";
# vCore/temps/freqs stay fully unprivileged either
# way.
# Install also removes pre-rename leftovers (60-adlermon-powercap.rules,
# sbin/adlermon-powercap-chmod) and superseded installer scripts.
#
# Uninstall removes what install created (binaries, capability, udev rules,
# RUN helper) and restores the device nodes' stock permissions, so recon
# reports everything missing again. The /etc config is KEPT (your edits)
# unless --purge.
#
# usage: aldermon-install.sh [MODE|OPTION]
# (default) recon -> plan -> confirm -> install
# --clean, -c force-reinstall every component (resets /etc config to stock)
# --vid plan VID as ON; no prompt
# --no-vid plan VID as SKIP; no prompt
# --setup privileged parts only (rules, setcap) for staged/package
# installs; still plan+confirm
# --uninstall remove binaries, capability, rules, RUN helper; restore node
# perms (keeps config)
# --purge uninstall AND delete the /etc config
# --del-adm on uninstall, also remove the original user from group adm
# (default: ask at the root stage)
# --keep-adm on uninstall, leave the adm group alone; don't ask
# Install adds the original user to group adm if missing; activate it with a
# re-login or `newgrp adm` (current shell only).
# --check status report; changes nothing
# --yes, -y accept the plan without prompting
# --help, -h this text
#
# env: PREFIX (default /usr/local), SYSCONF (/etc), DATADIR (/usr/share)
set -eu
SRCDIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
PREFIX=${PREFIX:-/usr/local}
SYSCONF=${SYSCONF:-/etc}
DATADIR=${DATADIR:-/usr/share}
BIN=$PREFIX/bin/aldermon
MSRBIN=$PREFIX/bin/aldermon-msr
CONF=$SYSCONF/aldermon/aldermon.conf
STOCK_CONF=$SRCDIR/aldermon.conf
HELPER=$PREFIX/sbin/aldermon-powercap-chmod
RULE=$SYSCONF/udev/rules.d/60-aldermon-powercap.rules
MSRRULE=$SYSCONF/udev/rules.d/60-aldermon-msr.rules
REL=$SRCDIR/target/release
_seen_section=0
section() { if [ "$_seen_section" = 1 ]; then printf '\n'; fi; printf '== %s ==\n' "$1"; _seen_section=1; }
item() { printf ' %s\n' "$*"; }
sub() { printf ' %s\n' "$*"; }
say() { printf '%s\n' "$*"; }
die() { printf 'aldermon-install: error: %s\n' "$*" >&2; exit 1; }
usage() { sed -n '/^# usage:/,/^# env:/p' "$0" | sed 's/^# //;s/^#$//'; }
ver_older() { # a b -> true if a is a strictly older dotted version
[ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
installed_ver() { # echoes "" | version | 0.0.0 (pre-version build)
[ -x "$BIN" ] || return 0
_v=$("$BIN" --version 2>/dev/null | sed -n 's/^aldermon //p') || true
echo "${_v:-0.0.0}"
}
src_ver() { # version the tree builds (from binary if built, else Cargo.toml)
if [ -x "$REL/aldermon" ]; then
"$REL/aldermon" --version | sed -n 's/^aldermon //p'
else
sed -n 's/^version = "\([^"]*\)"/\1/p' "$SRCDIR/Cargo.toml" 2>/dev/null || echo ""
fi
}
helper_state() { # "missing" | "installed, no capability" | "installed + capable"
if [ ! -x "$MSRBIN" ]; then echo missing
elif getcap "$MSRBIN" 2>/dev/null | grep -q cap_sys_rawio; then echo "installed + capable"
else echo "installed, no capability"; fi
}
# echoes the [1/4] gate action for FORCE INST SRC
bin_action() {
if [ "$1" = clean ]; then echo "install (forced)"
elif [ -z "$2" ]; then echo "install (missing)"
elif ver_older "$2" "$3"; then echo "upgrade $2 -> $3"
elif [ "$2" = "$3" ]; then echo "skip (up to date)"
else echo "keep (installed $2 newer than source $3)"
fi
}
write_if_changed() { # FILE MODE, content on stdin
_f=$1 _m=$2 _t="$_f.tmp-aldermon-install"
install -d "$(dirname "$_f")"
cat >"$_t"
if [ -f "$_f" ] && cmp -s "$_t" "$_f"; then
sub "kept (unchanged): $_f"
rm -f "$_t"
else
install -D -m "$_m" "$_t" "$_f"
sub "installed: $_f"
rm -f "$_t"
fi
}
write_powercap() { # watts: RUN-chmod helper + rule, applied now
install -d "$(dirname "$HELPER")"
cat <<EOF | write_if_changed "$HELPER" 755
#!/bin/sh
for d in /sys/class/powercap/intel-rapl*; do
[ -e "\$d/energy_uj" ] && chgrp adm "\$d/energy_uj" && chmod 0440 "\$d/energy_uj"
done
exit 0
EOF
printf '%s\n' 'SUBSYSTEM=="powercap", ACTION=="add", RUN+="'$HELPER'"' |
write_if_changed "$RULE" 644
"$HELPER" || sub "warning: powercap chmod failed (watts may stay unreadable)"
udevadm control --reload-rules
udevadm trigger --subsystem-match=powercap
sub "udev reloaded + powercap triggered"
clean_legacy
}
write_msr_rule() { # VID gate 1: msr IS a devnode -> plain MODE/GROUP
printf '%s\n' 'KERNEL=="msr[0-9]*", SUBSYSTEM=="msr", MODE="0440", GROUP="adm"' |
write_if_changed "$MSRRULE" 644
udevadm control --reload-rules # required: write_powercap reloaded BEFORE this file existed
udevadm trigger --subsystem-match=msr
sub "udev msr nodes triggered (0440 adm)"
}
# adm group membership: watts (energy_uj 0440 adm) and VID msr nodes both
# need it. Adds USER if missing so a fresh install works after one re-login.
ensure_adm() { # USER
_user=${1:-}
[ -n "$_user" ] && [ "$_user" != root ] || return 0
if ! getent group adm >/dev/null 2>&1; then
sub "warning: no group adm on this system; grant node access to $_user's group instead"
elif id -nG "$_user" 2>/dev/null | tr ' ' '\n' | grep -qx adm; then
sub "user $_user: already in group adm"
elif usermod -aG adm "$_user"; then
sub "added $_user to group adm - re-login (or 'newgrp adm') to activate"
else
sub "warning: could not add $_user to adm; do it manually: doas usermod -aG adm $_user"
fi
}
# Pre-rename (adlermon) and superseded installer leftovers - the old rule
# still RUNs its old chmod helper, so remove the pair once ours is in.
clean_legacy() {
for _l in "$SYSCONF/udev/rules.d/60-adlermon-powercap.rules" \
"$PREFIX/sbin/adlermon-powercap-chmod" \
"$DATADIR/aldermon/powercap-pl-rules.sh" \
"$DATADIR/aldermon/aldermon-setup.sh"; do
if [ -e "$_l" ]; then
rm -f "$_l"
sub "removed legacy leftover: $_l"
fi
done
}
setcap_helper() { # FORCE - VID gate 2: capability on the minimal helper only
[ -x "$MSRBIN" ] || die "$MSRBIN not found - install the binary first (or use 'aldermon --vid' under root)"
if [ "$1" != clean ] && getcap "$MSRBIN" 2>/dev/null | grep -q 'cap_sys_rawio'; then
sub "kept (already capable): $MSRBIN"
else
setcap cap_sys_rawio+ep "$MSRBIN"
sub "setcap cap_sys_rawio+ep: $MSRBIN"
fi
}
vid_choice() { # root side: ask Y/n unless pre-answered
case "$VIDMODE" in
on) return 0 ;;
off) sub "skipped (declined): VID stays unreadable - the TUI shows 'VID n/a (no msr access)'. Re-run with --vid to add it."; return 1 ;;
esac
printf 'enable VID extras (msr rule + helper setcap)? [Y/n] '
read -r _ans || _ans=y
case "$_ans" in
[nN]*) sub "skipped (declined): VID stays unreadable - the TUI shows 'VID n/a (no msr access)'. Re-run with --vid to add it."; return 1 ;;
*) return 0 ;;
esac
}
verify() { # ORIGUSER VIDENABLED
_u=${1:-$(id -un)} _vid=${2:-yes}
section verify
if [ -x "$BIN" ]; then item "binary: $("$BIN" --version 2>/dev/null || echo 'installed, pre-version')"; fi
_c=$(getcap "$MSRBIN" 2>/dev/null || true)
if [ "$_vid" = yes ]; then
item "helper caps: ${_c:-NONE (VID stays unreadable - run --setup)}"
else
item "VID: not wanted this run - TUI shows 'VID n/a (no msr access)'"
if [ -f "$MSRRULE" ]; then
item "note: an msr rule from a previous install is still present (left alone; VID still off until the helper is setcap'd)"
fi
fi
if [ -e /dev/cpu/0/msr ]; then
item "msr nodes: $(ls -l /dev/cpu/0/msr | awk '{print $1, $3, $4}')"
else
item "warning: /dev/cpu/0/msr absent - msr module not loaded"
fi
_e=$(ls /sys/class/powercap/intel-rapl:0/energy_uj 2>/dev/null || true)
if [ -n "$_e" ]; then item "energy_uj: $(ls -l "$_e" | awk '{print $1, $3, $4}')"; fi
if [ -f "$CONF" ]; then item "config: $CONF present"; else item "config: $CONF MISSING"; fi
if id -nG "$_u" 2>/dev/null | tr ' ' '\n' | grep -qx adm; then
item "user $_u: in group adm (existing shells need re-login or 'newgrp adm')"
else
item "user $_u: NOT in group adm"
fi
}
recon() { # install/setup: status + planned actions, BEFORE any root action
_src=$(src_ver) _inst=$(installed_ver)
section recon
item "installed: ${_inst:-none} | source: ${_src:-unknown}"
item "helper: $(helper_state)"
item "rules: powercap $([ -f "$RULE" ] && echo present || echo missing), msr $([ -f "$MSRRULE" ] && echo present || echo missing)"
item "config: $CONF $([ -f "$CONF" ] && echo present || echo missing)"
_e=$(ls -l /sys/class/powercap/intel-rapl:0/energy_uj 2>/dev/null | awk '{print $1, $3, $4}')
item "watts source: energy_uj ${_e:-unreadable}"
item "planned actions:"
if [ "$MODE" != setup ]; then
_act=$(bin_action "$FORCE" "$_inst" "$_src")
if [ "$MODE" = install ] && [ ! -x "$REL/aldermon" ]; then _act="$_act (after release build)"; fi
sub "[1/4] binary+helper: $_act"
if [ "$FORCE" = clean ]; then sub "[2/4] config: reset $CONF to stock"
elif [ -f "$CONF" ]; then sub "[2/4] config: keep existing $CONF"
else sub "[2/4] config: install stock $CONF"; fi
fi
sub "[3/4] watts: ensure powercap rule + $HELPER (group adm; needs root)"
_u=$(id -un)
if id -nG "$_u" 2>/dev/null | tr ' ' '\n' | grep -qx adm; then
sub "groups: $_u already in adm"
else
sub "groups: add $_u to adm (needs root; re-login or 'newgrp adm' after)"
fi
case "$VIDMODE" in
off) sub "[4/4] VID: SKIP (--no-vid)" ;;
on) sub "[4/4] VID: msr rule + setcap helper (needs root)" ;;
*) sub "[4/4] VID: OPTIONAL - asked after the root prompt; msr rule 0440 adm + cap_sys_rawio+ep on aldermon-msr only. Decline keeps 'VID n/a'; vCore/temps/freqs need no privileges either way." ;;
esac
}
recon_uninstall() {
section recon
item "binary: $([ -x "$BIN" ] && echo "$BIN ($("$BIN" --version 2>/dev/null || echo 'pre-version'))" || echo "not installed")"
item "helper: $(helper_state)"
item "rules: powercap $([ -f "$RULE" ] && echo present || echo missing), msr $([ -f "$MSRRULE" ] && echo present || echo missing)"
item "config: $CONF $([ -f "$CONF" ] && echo present || echo missing)"
item "planned actions:"
if [ "$PURGE" = yes ]; then
sub "remove binaries, capability, both udev rules, RUN helper, installer copy"
sub "restore /dev/cpu/*/msr to 0600 root:root and energy_uj to 0400 root:root"
sub "remove config $CONF (--purge)"
else
sub "remove binaries, capability, both udev rules, RUN helper, installer copy"
sub "restore /dev/cpu/*/msr to 0600 root:root and energy_uj to 0400 root:root"
sub "keep config $CONF (add --purge to remove)"
fi
case "$ADMREMOVE" in
yes) sub "remove $(id -un) from group adm" ;;
no) sub "leave group adm alone" ;;
*) sub "ask at the root stage whether to remove $(id -un) from group adm" ;;
esac
}
confirm_or_go() { # plan acceptance before escalating
[ "$ASSUME" = yes ] && return 0
printf 'proceed? [Y/n] '
read -r _r || die "no tty for confirmation - use --yes"
case "$_r" in
[nN]*) say "aborted, nothing changed"; exit 0 ;;
esac
}
root_install() { # FORCE VIDMODE PURGE ORIGUSER PREFIX SYSCONF DATADIR
FORCE=$1; VIDMODE=$2; _orig=$4; PREFIX=$5; SYSCONF=$6; DATADIR=$7
BIN=$PREFIX/bin/aldermon; MSRBIN=$PREFIX/bin/aldermon-msr
CONF=$SYSCONF/aldermon/aldermon.conf; STOCK_CONF=$SRCDIR/aldermon.conf
HELPER=$PREFIX/sbin/aldermon-powercap-chmod
RULE=$SYSCONF/udev/rules.d/60-aldermon-powercap.rules
MSRRULE=$SYSCONF/udev/rules.d/60-aldermon-msr.rules
[ -x "$REL/aldermon" ] || die "no release build in $SRCDIR - run the script unprivileged (it builds) or cargo build --release first"
SRCVER=$(src_ver)
INSTVER=$(installed_ver)
section install
item "[1/4] binary (installed: ${INSTVER:-none}, source: $SRCVER)"
_act=$(bin_action "$FORCE" "$INSTVER" "$SRCVER")
case $_act in
install* | upgrade*)
install -Dm755 "$REL/aldermon" "$BIN"
install -Dm755 "$REL/aldermon-msr" "$MSRBIN"
sub "installed: $BIN + $MSRBIN" ;;
skip*)
if [ ! -x "$MSRBIN" ]; then
install -Dm755 "$REL/aldermon-msr" "$MSRBIN"
sub "skipped binary (up to date); installed missing helper"
else
sub "skipped: up to date (use --clean to force)"
fi ;;
keep*) sub "$_act" ;;
esac
item "[2/4] config"
if [ "$FORCE" = clean ] || [ ! -e "$CONF" ]; then
[ -f "$STOCK_CONF" ] || die "stock config $STOCK_CONF not found (installed copy? use --setup)"
install -Dm644 "$STOCK_CONF" "$CONF"
sub "installed stock: $CONF"
else
sub "kept existing: $CONF (--clean resets to stock)"
fi
item "[3/4] watts (powercap)"
write_powercap
item "[4/4] VID (optional)"
_vid=no
if vid_choice; then
_vid=yes
write_msr_rule
setcap_helper "$FORCE"
fi
item "group membership"
ensure_adm "$_orig"
verify "$_orig" "$_vid"
}
root_setup() { # FORCE VIDMODE PURGE ORIGUSER PREFIX SYSCONF DATADIR
FORCE=$1; VIDMODE=$2; _orig=$4; PREFIX=$5; SYSCONF=$6; DATADIR=$7
BIN=$PREFIX/bin/aldermon; MSRBIN=$PREFIX/bin/aldermon-msr
CONF=$SYSCONF/aldermon/aldermon.conf
HELPER=$PREFIX/sbin/aldermon-powercap-chmod
RULE=$SYSCONF/udev/rules.d/60-aldermon-powercap.rules
MSRRULE=$SYSCONF/udev/rules.d/60-aldermon-msr.rules
section install
item "setup: watts (powercap)"
write_powercap
item "setup: VID (optional)"
_vid=no
if vid_choice; then
_vid=yes
write_msr_rule
setcap_helper "$FORCE"
fi
item "group membership"
ensure_adm "$_orig"
verify "$_orig" "$_vid"
}
root_uninstall() { # FORCE VIDMODE PURGE ORIGUSER PREFIX SYSCONF DATADIR ADMREMOVE
PURGE=$3; _orig=$4; PREFIX=$5; SYSCONF=$6; DATADIR=$7; ADMREMOVE=$8
BIN=$PREFIX/bin/aldermon; MSRBIN=$PREFIX/bin/aldermon-msr
CONF=$SYSCONF/aldermon/aldermon.conf
HELPER=$PREFIX/sbin/aldermon-powercap-chmod
RULE=$SYSCONF/udev/rules.d/60-aldermon-powercap.rules
MSRRULE=$SYSCONF/udev/rules.d/60-aldermon-msr.rules
section uninstall
if [ -x "$MSRBIN" ]; then
setcap -r "$MSRBIN" 2>/dev/null && item "dropped capability: $MSRBIN" || item "capability already absent"
fi
for _f in "$BIN" "$MSRBIN" "$HELPER" "$RULE" "$MSRRULE" "$DATADIR/aldermon/aldermon-install.sh"; do
if [ -e "$_f" ]; then rm -f "$_f"; item "removed: $_f"; fi
done
clean_legacy
# Restore stock device perms so recon reports them unset again.
if [ -e /dev/cpu/0/msr ]; then
chgrp root /dev/cpu/*/msr 2>/dev/null || true
chmod 0600 /dev/cpu/*/msr 2>/dev/null || true
item "restored /dev/cpu/*/msr -> 0600 root:root"
fi
_e=$(ls /sys/class/powercap/intel-rapl:0/energy_uj 2>/dev/null || true)
if [ -n "$_e" ]; then
chgrp root "$_e" 2>/dev/null || true
chmod 0400 "$_e" 2>/dev/null || true
item "restored energy_uj -> 0400 root:root"
fi
udevadm control --reload-rules
item "udev rules reloaded"
if [ "$PURGE" = yes ]; then
if [ -e "$CONF" ]; then rm -f "$CONF"; item "removed config: $CONF"; fi
else
item "kept config: $CONF (--purge removes it)"
fi
rmdir -p --ignore-fail-on-non-empty "$DATADIR/aldermon" 2>/dev/null || true
verify_uninstall "$_orig" "$ADMREMOVE"
}
verify_uninstall() { # ORIGUSER ADMREMOVE
_u=${1:-$(id -un)} _adm=${2:-no}
section verify
item "binary: $([ -e "$BIN" ] && echo STILL PRESENT || echo gone)"
item "helper: $([ -e "$MSRBIN" ] && echo STILL PRESENT || echo gone)"
item "powercap rule: $([ -e "$RULE" ] && echo STILL PRESENT || echo gone)"
item "msr rule: $([ -e "$MSRRULE" ] && echo STILL PRESENT || echo gone)"
if [ -e /dev/cpu/0/msr ]; then
item "msr node: $(ls -l /dev/cpu/0/msr | awk '{print $1, $3, $4}') (stock 0600 root root)"
fi
_e=$(ls /sys/class/powercap/intel-rapl:0/energy_uj 2>/dev/null || true)
if [ -n "$_e" ]; then item "energy_uj: $(ls -l "$_e" | awk '{print $1, $3, $4}')"; fi
item "config: $CONF $([ -e "$CONF" ] && echo present || echo gone)"
if id -nG "$_u" 2>/dev/null | tr ' ' '\n' | grep -qx adm; then
_do_adm=no
case "$_adm" in
yes) _do_adm=yes ;;
no) item "user $_u: still in group adm (use --del-adm to remove; adm also grants log access)" ;;
*)
printf 'remove %s from group adm? [y/N] ' "$_u"
read -r _r || _r=n
case "$_r" in [yY]*) _do_adm=yes ;; esac
;;
esac
if [ "$_do_adm" = yes ]; then
if gpasswd -d "$_u" adm >/dev/null 2>&1; then
item "removed $_u from group adm (re-login for it to take effect)"
else
item "could not remove $_u from adm; do it manually: doas gpasswd -d $_u adm"
fi
elif [ "$_adm" = ask ]; then
item "kept $_u in group adm (adm also grants log access)"
fi
fi
}
escalate() { # INTERNALMODE
_mode=$1 _u=$(id -un)
if [ "$(id -u)" -eq 0 ]; then
"$0" "$_mode" "$FORCE" "$VIDMODE" "$PURGE" "$_u" "$PREFIX" "$SYSCONF" "$DATADIR" "$ADMREMOVE"
else
PRIV=$(command -v doas 2>/dev/null || command -v sudo 2>/dev/null || true)
[ -n "$PRIV" ] || die "no doas or sudo found - run the privileged steps as root"
say "requesting root via $PRIV"
exec "$PRIV" "$0" "$_mode" "$FORCE" "$VIDMODE" "$PURGE" "$_u" "$PREFIX" "$SYSCONF" "$DATADIR" "$ADMREMOVE"
fi
}
check_status() {
section status
if [ -x "$BIN" ]; then
item "binary: $("$BIN" --version 2>/dev/null || echo 'installed, pre-version (<= 2026-09)')"
if [ -x "$REL/aldermon" ]; then
_s=$("$REL/aldermon" --version | sed -n 's/^aldermon //p')
_i=$("$BIN" --version 2>/dev/null | sed -n 's/^aldermon //p')
[ -n "$_i" ] || _i=0.0.0
if ver_older "$_i" "$_s"; then item "update available: source builds $_s"
else item "source build: $_s $([ "$_i" = "$_s" ] && echo '(match)' || echo '(source is older)')"; fi
fi
else
item "binary: NOT INSTALLED ($BIN)"
fi
item "helper: $(helper_state)"
item "powercap rule: $([ -f "$RULE" ] && echo present || echo MISSING)"
item "msr rule: $([ -f "$MSRRULE" ] && echo present || echo MISSING)"
if [ -e /dev/cpu/0/msr ]; then
item "msr node: $(ls -l /dev/cpu/0/msr | awk '{print $1, $3, $4}') (needs 0440 adm + helper cap)"
fi
item "config: $CONF $([ -f "$CONF" ] && echo present || echo MISSING)"
if id -nG "$(id -un)" | tr ' ' '\n' | grep -qx adm; then
item "user $(id -un): in adm"
else
item "user $(id -un): NOT in adm"
fi
}
MODE=install
FORCE=plain
VIDMODE=ask
PURGE=no
ADMREMOVE=ask
ASSUME=no
while [ $# -gt 0 ]; do
case $1 in
-h | --help) usage; exit 0 ;;
--check) MODE=check ;;
--setup) MODE=setup ;;
--uninstall) MODE=uninstall ;;
--purge) MODE=uninstall; PURGE=yes ;;
--clean | -c) FORCE=clean ;;
--yes | -y) ASSUME=yes ;;
--no-vid) VIDMODE=off ;;
--vid) VIDMODE=on ;;
--del-adm) ADMREMOVE=yes ;;
--keep-adm) ADMREMOVE=no ;;
_root) shift; root_install "$@"; exit 0 ;;
_setup) shift; root_setup "$@"; exit 0 ;;
_unroot) shift; root_uninstall "$@"; exit 0 ;;
*) die "unknown argument: $1 (see --help)" ;;
esac
shift
done
case $MODE in
check) check_status ;;
uninstall)
recon_uninstall
confirm_or_go
escalate _unroot
;;
setup)
recon
confirm_or_go
escalate _setup
;;
install)
[ -f "$SRCDIR/Cargo.toml" ] || die "$SRCDIR is not a source tree - run from the checkout, or use --setup/--check"
recon
confirm_or_go
if [ ! -x "$REL/aldermon" ]; then
command -v cargo >/dev/null || die "cargo not found and no release build present"
say "building release binaries (as $(id -un))"
(cd "$SRCDIR" && cargo build --release)
fi
escalate _root
;;
esac