#!/usr/bin/env bash # BastionGuard user-session watcher # Monitors suspend/resume and lock/unlock events, then restarts BastionGuard user services. set -u RESTART_SCRIPT="${BG_RESTART_SCRIPT:-/usr/share/BastionGuard/data/scripts/BastionGuard-restart-user-services.sh}" DEBOUNCE_SECONDS="${BG_RESTART_DEBOUNCE_SECONDS:-8}" STAMP_FILE="${XDG_RUNTIME_DIR:-/tmp}/BastionGuard-user-session-watch.last" log_msg() { local msg="$1" if command -v systemd-cat >/dev/null 2>&1; then printf '%s\n' "$msg" | systemd-cat -t BastionGuard-user-session-watch -p info else printf '%s\n' "BastionGuard-user-session-watch: $msg" >&2 fi } restart_user_services() { local reason="$1" local now last now="$(date +%s)" last="0" if [ -r "$STAMP_FILE" ]; then last="$(cat "$STAMP_FILE" 2>/dev/null || printf '0')" fi case "$last" in ''|*[!0-9]*) last="0" ;; esac if [ $((now - last)) -lt "$DEBOUNCE_SECONDS" ]; then log_msg "skip restart for '$reason' because debounce is active" return 0 fi printf '%s\n' "$now" > "$STAMP_FILE" 2>/dev/null || true if [ ! -x "$RESTART_SCRIPT" ]; then log_msg "restart script missing or not executable: $RESTART_SCRIPT" return 0 fi log_msg "restarting BastionGuard user services after: $reason" "$RESTART_SCRIPT" --user "$reason" || log_msg "restart script returned a non-zero status for: $reason" } monitor_login1_sleep() { dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'" 2>/dev/null | while IFS= read -r line; do case "$line" in *"boolean false"*) restart_user_services "resume" ;; esac done } monitor_login1_lock() { dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Session'" 2>/dev/null | while IFS= read -r line; do case "$line" in *"member=Lock"*) restart_user_services "session-lock" ;; *"member=Unlock"*) restart_user_services "session-unlock" ;; esac done } monitor_freedesktop_screensaver() { dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" 2>/dev/null | while IFS= read -r line; do case "$line" in *"member=ActiveChanged"*) restart_user_services "screensaver-active-changed" ;; esac done } monitor_gnome_screensaver() { dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" 2>/dev/null | while IFS= read -r line; do case "$line" in *"member=ActiveChanged"*) restart_user_services "gnome-screensaver-active-changed" ;; esac done } cleanup() { trap - INT TERM EXIT jobs -p | xargs -r kill 2>/dev/null || true } trap cleanup INT TERM EXIT if ! command -v dbus-monitor >/dev/null 2>&1; then log_msg "dbus-monitor not found; install package 'dbus' or equivalent" while :; do sleep 3600; done fi log_msg "watcher started" monitor_login1_sleep & monitor_login1_lock & monitor_freedesktop_screensaver & monitor_gnome_screensaver & # Keep the service alive. If a monitor exits, systemd restarts this watcher. wait -n