curtain/Scripts/uninstall.sh
Aric Camarata 8c19e960d2 Detection root-cause fix + audit batch: netstat path, UDP activator, settings coherence, refactor, docs
Detection: netstat lives at /usr/sbin/netstat, not /usr/bin — the hardcoded wrong
path silently killed the ESTABLISHED-TCP activator (root cause of the failed live
test). Fixed and live-verified. Added peered-UDP activator (5900-5902) for
High-Performance sessions, per-signal transition logging, unconditional error
logging for dead probe helpers, and probe v2 with full CGSession dictionary
diffing. 7 new parser tests (32 total).

Fixes from a full audit + adversarial review: idle source setting honored
(default now Remote session activity), cover scope reduced to a coherent
two-mode model with legacy migration (per-display toggle was inverted in
onlyMarked and dead in all), curtain test no longer schedules a teardown over a
live session, specific-display password box placement gets a real picker,
refuse-to-arm enforced, activation notification posts a real banner, menu
password gate bypassed when the event tap is dead, shared single-decoder aerial
player with stale-task guard and async playability check, password buffer zeroed
on successful unlock and Esc, XPC interruption/invalidation handlers, modern
Accessibility settings URL, launchPath modernized, codesign failures now abort
release.sh, monotonic CFBundleVersion, install.sh temp cleanup, dead
armDisarmHotkey setting removed.

Refactor: Curtain.swift and PreferencesWindow.swift split into focused files
(largest now 479 lines). Wiki, README, and contributing docs updated to match.
Build clean at 0 warnings, 32/32 tests pass.
2026-06-09 20:36:30 -04:00

34 lines
1.4 KiB
Bash
Executable file

#!/bin/bash
# Curtain uninstaller. Removes /Applications/Curtain.app. The login item and
# disconnect daemon are unregistered from inside the app (SMAppService) before
# you delete it; this script also defensively cleans up files left by older
# installs (LaunchAgent, /usr/local/bin helper, sudoers rule) — only prompting
# for admin if any of those legacy files actually exist.
set -uo pipefail
AGENT="$HOME/Library/LaunchAgents/io.acamarata.curtain.plist"
LEGACY_HELPER="/usr/local/bin/curtain-endsession"
LEGACY_SUDOERS="/etc/sudoers.d/curtain-endsession"
echo "==> Stopping Curtain…"
pkill -x Curtain 2>/dev/null || true
# Legacy LaunchAgent (newer installs use SMAppService.mainApp instead).
if [ -f "$AGENT" ]; then
echo "==> Removing legacy login agent…"
launchctl unload "$AGENT" 2>/dev/null || true
rm -f "$AGENT"
fi
echo "==> Removing app + settings…"
rm -rf "/Applications/Curtain.app"
rm -rf "$HOME/Library/Application Support/Curtain"
# Legacy root helper + sudoers rule. Only escalate if something is actually
# there, so a clean uninstall never triggers an admin prompt.
if [ -e "$LEGACY_HELPER" ] || [ -e "$LEGACY_SUDOERS" ]; then
echo "==> Removing legacy root helper (needs admin)…"
osascript -e "do shell script \"rm -f '$LEGACY_HELPER' '$LEGACY_SUDOERS'\" with administrator privileges" || true
fi
echo "✅ Curtain uninstalled. You may also remove it from System Settings → Privacy & Security → Accessibility."