#!/usr/bin/env bash
# Give fire_gimbal_control the one privilege the thermal camera needs.
#
# The InfraTec SDK talks to the TarisIR over a raw AF_PACKET socket, which
# takes CAP_NET_RAW. Rather than running the whole program - motors, MQTT
# remote control and all - as root, the binary gets that one capability and
# keeps running as the tower's user. A rebuild replaces the binary and with it
# the capability, so deploy.sh and install-tower run this after every build.
#
#   scripts/fgc-setcap                    set it (asks for the sudo password)
#   scripts/fgc-setcap --if-thermal       ... only if a [Camera.*] has driver = taris;
#                                         never fails, says what is missing
#   scripts/fgc-setcap --check            exit 0 if the binary has it
#   scripts/fgc-setcap --install-sudoers  allow exactly this setcap without a
#                                         password, so deploy.sh can run it
#
# A binary with file capabilities runs in the loader's secure mode: LD_* is
# ignored and no core dumps are written. So the SDK (/usr/lib/infratec, in the
# ld cache) and Vimba X must be found without LD_LIBRARY_PATH - see
# docs/tower-installation.md, "Thermal camera", for the check.
set -euo pipefail

REPO=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
BIN="$REPO/build/fire_gimbal_control"
CAPS="cap_net_raw+ep"
SETCAP=/usr/sbin/setcap   # fixed: the sudoers rule names this exact path
[[ -x $SETCAP ]] || SETCAP=$(command -v setcap 2>/dev/null || echo /usr/sbin/setcap)
SUDOERS=/etc/sudoers.d/fire-gimbal-control-setcap
HW=/etc/fire_gimbal_control/hardware.ini

thermal_configured() {
    local f cfg
    cfg=$("$REPO/scripts/tower-config" where 2>/dev/null || true)
    for f in "$cfg" "$REPO/config.ini" "$HW"; do
        [[ -r $f ]] && grep -Eqi '^[[:space:]]*driver[[:space:]]*=[[:space:]]*taris' "$f" && return 0
    done
    return 1
}

has_cap() { command -v getcap > /dev/null && getcap "$BIN" 2>/dev/null | grep -q cap_net_raw; }

set_cap() {
    [[ -x $BIN ]] || { echo "fgc-setcap: $BIN not built yet" >&2; return 1; }
    if sudo -n "$SETCAP" "$CAPS" "$BIN" 2>/dev/null; then :
    elif [[ -t 0 ]]; then sudo "$SETCAP" "$CAPS" "$BIN"
    else return 1
    fi
    has_cap
}

case "${1:-}" in
    --check)
        has_cap
        ;;
    --install-sudoers)
        rule="$(id -un) ALL=(root) NOPASSWD: $SETCAP $CAPS $BIN"
        tmp=$(mktemp)
        trap 'rm -f "$tmp"' EXIT
        printf '# fire_gimbal_control: the thermal camera needs cap_net_raw after every build\n%s\n' \
            "$rule" > "$tmp"
        /usr/sbin/visudo -cf "$tmp" > /dev/null || { echo "fgc-setcap: rule rejected by visudo" >&2; exit 1; }
        sudo install -m 0440 -o root -g root "$tmp" "$SUDOERS"
        echo "wrote $SUDOERS: $rule"
        ;;
    --if-thermal)
        thermal_configured || exit 0
        if set_cap; then
            echo "fgc-setcap: $BIN may open raw sockets (thermal camera)"
        else
            echo "!! fgc-setcap: could not give $BIN $CAPS - the thermal camera stays offline." >&2
            echo "!!   Once on the tower: scripts/fgc-setcap --install-sudoers   (or run scripts/fgc-setcap)" >&2
        fi
        exit 0
        ;;
    "")
        set_cap && echo "fgc-setcap: $BIN may open raw sockets"
        ;;
    *)
        sed -n '2,20p' "$0" >&2
        exit 2
        ;;
esac
