diff --git a/setup-dev.sh b/setup-dev.sh deleted file mode 100644 index dbbfcc7..0000000 --- a/setup-dev.sh +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/env bash -# INTERCEPT Setup Script (best-effort installs, hard-fail verification) - -# ---- Force bash even if launched with sh ---- -if [ -z "${BASH_VERSION:-}" ]; then - echo "[x] This script must be run with bash (not sh)." - echo " Run: bash $0" - exec bash "$0" "$@" -fi - -set -Eeuo pipefail - -# Ensure admin paths are searchable (many tools live here) -export PATH="/usr/local/sbin:/usr/sbin:/sbin:/opt/homebrew/sbin:/opt/homebrew/bin:$PATH" - -# ---------------------------- -# Pretty output -# ---------------------------- -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -info() { echo -e "${BLUE}[*]${NC} $*"; } -ok() { echo -e "${GREEN}[✓]${NC} $*"; } -warn() { echo -e "${YELLOW}[!]${NC} $*"; } -fail() { echo -e "${RED}[x]${NC} $*"; } - -on_error() { - local line="$1" - local cmd="${2:-unknown}" - fail "Setup failed at line ${line}: ${cmd}" - exit 1 -} -trap 'on_error $LINENO "$BASH_COMMAND"' ERR - -# ---------------------------- -# Banner -# ---------------------------- -echo -e "${BLUE}" -echo " ___ _ _ _____ _____ ____ ____ _____ ____ _____ " -echo " |_ _| \\ | |_ _| ____| _ \\ / ___| ____| _ \\_ _|" -echo " | || \\| | | | | _| | |_) | | | _| | |_) || | " -echo " | || |\\ | | | | |___| _ <| |___| |___| __/ | | " -echo " |___|_| \\_| |_| |_____|_| \\_\\\\____|_____|_| |_| " -echo -e "${NC}" -echo "INTERCEPT - Setup Script" -echo "============================================" -echo - -# ---------------------------- -# Helpers -# ---------------------------- -cmd_exists() { - local c="$1" - command -v "$c" >/dev/null 2>&1 && return 0 - [[ -x "/usr/sbin/$c" || -x "/sbin/$c" || -x "/usr/local/sbin/$c" || -x "/opt/homebrew/sbin/$c" ]] && return 0 - return 1 -} - -have_any() { - local c - for c in "$@"; do - cmd_exists "$c" && return 0 - done - return 1 -} - -need_sudo() { - if [[ "$(id -u)" -eq 0 ]]; then - SUDO="" - ok "Running as root" - else - if cmd_exists sudo; then - SUDO="sudo" - else - fail "sudo is not installed and you're not root." - echo "Either run as root or install sudo first." - exit 1 - fi - fi -} - -detect_os() { - if [[ "${OSTYPE:-}" == "darwin"* ]]; then - OS="macos" - elif [[ -f /etc/debian_version ]]; then - OS="debian" - else - OS="unknown" - fi - info "Detected OS: ${OS}" - [[ "$OS" != "unknown" ]] || { fail "Unsupported OS (macOS + Debian/Ubuntu only)."; exit 1; } -} - -# ---------------------------- -# Required tool checks (with alternates) -# ---------------------------- -missing_required=() - -check_required() { - local label="$1"; shift - local desc="$1"; shift - - if have_any "$@"; then - ok "${label} - ${desc}" - else - warn "${label} - ${desc} (missing, required)" - missing_required+=("$label") - fi -} - -check_tools() { - info "Checking required tools..." - missing_required=() - - echo - info "Core SDR:" - check_required "rtl_fm" "RTL-SDR FM demodulator" rtl_fm - check_required "rtl_test" "RTL-SDR device detection" rtl_test - check_required "multimon-ng" "Pager decoder" multimon-ng - check_required "rtl_433" "433MHz sensor decoder" rtl_433 rtl433 - check_required "dump1090" "ADS-B decoder" dump1090 - - echo - info "GPS:" - check_required "gpsd" "GPS daemon" gpsd - - echo - info "Audio:" - check_required "ffmpeg" "Audio encoder/decoder" ffmpeg - - echo - info "WiFi:" - check_required "airmon-ng" "Monitor mode helper" airmon-ng - check_required "airodump-ng" "WiFi scanner" airodump-ng - check_required "aireplay-ng" "Injection/deauth" aireplay-ng - check_required "hcxdumptool" "PMKID capture" hcxdumptool - check_required "hcxpcapngtool" "PMKID/pcapng conversion" hcxpcapngtool - - echo - info "Bluetooth:" - check_required "bluetoothctl" "Bluetooth controller CLI" bluetoothctl - check_required "hcitool" "Bluetooth scan utility" hcitool - check_required "hciconfig" "Bluetooth adapter config" hciconfig - - echo - info "SoapySDR:" - check_required "SoapySDRUtil" "SoapySDR CLI utility" SoapySDRUtil - echo -} - -# ---------------------------- -# Python venv + deps -# ---------------------------- -check_python_version() { - if ! cmd_exists python3; then - fail "python3 not found." - [[ "$OS" == "macos" ]] && echo "Install with: brew install python" - [[ "$OS" == "debian" ]] && echo "Install with: sudo apt-get install python3" - exit 1 - fi - - local ver - ver="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" - info "Python version: ${ver}" - - python3 - <<'PY' -import sys -raise SystemExit(0 if sys.version_info >= (3,9) else 1) -PY - ok "Python version OK (>= 3.9)" -} - -install_python_deps() { - info "Setting up Python virtual environment..." - check_python_version - - if [[ ! -f requirements.txt ]]; then - warn "requirements.txt not found; skipping Python dependency install." - return 0 - fi - - if [[ ! -d venv ]]; then - python3 -m venv venv - ok "Created venv/" - else - ok "Using existing venv/" - fi - - # shellcheck disable=SC1091 - source venv/bin/activate - - python -m pip install --upgrade pip setuptools wheel >/dev/null - ok "Upgraded pip tooling" - - info "Installing Python requirements..." - python -m pip install -r requirements.txt - ok "Python dependencies installed" - echo -} - -# ---------------------------- -# macOS install (Homebrew) -# ---------------------------- -ensure_brew() { - cmd_exists brew && return 0 - warn "Homebrew not found. Installing Homebrew..." - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - - if [[ -x /opt/homebrew/bin/brew ]]; then - eval "$(/opt/homebrew/bin/brew shellenv)" - elif [[ -x /usr/local/bin/brew ]]; then - eval "$(/usr/local/bin/brew shellenv)" - fi - - cmd_exists brew || { fail "Homebrew install failed. Install manually then re-run."; exit 1; } -} - -brew_install() { - local pkg="$1" - if brew list --formula "$pkg" >/dev/null 2>&1; then - ok "brew: ${pkg} already installed" - return 0 - fi - info "brew: installing ${pkg}..." - brew install "$pkg" - ok "brew: installed ${pkg}" -} - -install_macos_packages() { - ensure_brew - info "Installing packages via Homebrew..." - - brew_install librtlsdr - brew_install multimon-ng - brew_install ffmpeg - brew_install rtl_433 - - # ADS-B (may not exist) - warn "Attempting dump1090 install via Homebrew (may be unavailable)..." - (brew_install dump1090-mutability) || true - - brew_install aircrack-ng - brew_install hcxtools - brew_install soapysdr - brew_install gpsd - - warn "macOS note: hcitool/hciconfig are Linux (BlueZ) utilities and often unavailable on macOS." - echo -} - -# ---------------------------- -# Debian/Ubuntu install (APT) -# ---------------------------- -apt_install() { $SUDO apt-get install -y --no-install-recommends "$@" >/dev/null; } - -apt_try_install_any() { - local p - for p in "$@"; do - if $SUDO apt-get install -y --no-install-recommends "$p" >/dev/null 2>&1; then - ok "apt: installed ${p}" - return 0 - fi - done - return 1 -} - -install_dump1090_from_source_debian() { - info "dump1090 not available via APT. Building from source (required)..." - - apt_install build-essential git pkg-config \ - librtlsdr-dev libusb-1.0-0-dev \ - libncurses-dev tcl-dev python3-dev - - local orig_dir tmp_dir - orig_dir="$(pwd)" - tmp_dir="$(mktemp -d)" - - cleanup() { cd "$orig_dir" >/dev/null 2>&1 || true; rm -rf "$tmp_dir"; } - trap cleanup EXIT - - info "Cloning FlightAware dump1090..." - git clone --depth 1 https://github.com/flightaware/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \ - || { fail "Failed to clone FlightAware dump1090"; exit 1; } - - cd "$tmp_dir/dump1090" - info "Compiling FlightAware dump1090..." - if make BLADERF=no RTLSDR=yes >/dev/null 2>&1; then - $SUDO install -m 0755 dump1090 /usr/local/bin/dump1090 - ok "dump1090 installed successfully (FlightAware)." - return 0 - fi - - warn "FlightAware build failed. Falling back to antirez/dump1090..." - rm -rf "$tmp_dir/dump1090" - git clone --depth 1 https://github.com/antirez/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \ - || { fail "Failed to clone antirez dump1090"; exit 1; } - - cd "$tmp_dir/dump1090" - info "Compiling antirez dump1090..." - make >/dev/null 2>&1 || { fail "Failed to build dump1090 from source (required)."; exit 1; } - - $SUDO install -m 0755 dump1090 /usr/local/bin/dump1090 - ok "dump1090 installed successfully (antirez)." -} - -setup_udev_rules_debian() { - [[ -d /etc/udev/rules.d ]] || { warn "udev not found; skipping RTL-SDR udev rules."; return 0; } - - local rules_file="/etc/udev/rules.d/20-rtlsdr.rules" - [[ -f "$rules_file" ]] && { ok "RTL-SDR udev rules already present: $rules_file"; return 0; } - - info "Installing RTL-SDR udev rules..." - $SUDO tee "$rules_file" >/dev/null <<'EOF' -SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE="0666" -EOF - $SUDO udevadm control --reload-rules || true - $SUDO udevadm trigger || true - ok "udev rules installed. Unplug/replug your RTL-SDR if connected." - echo -} - -install_debian_packages() { - need_sudo - info "Updating APT package lists..." - $SUDO apt-get update -y >/dev/null - - info "Installing required packages via APT..." - apt_install rtl-sdr - apt_install multimon-ng - apt_install ffmpeg - - apt_try_install_any rtl-433 rtl433 || true - - apt_install aircrack-ng || true - apt_install hcxdumptool || true - apt_install hcxtools || true - apt_install bluez bluetooth || true - apt_install soapysdr-tools || true - apt_install gpsd gpsd-clients || true - - # dump1090: apt first; source fallback; hard fail inside if it can't build - if ! cmd_exists dump1090; then - apt_try_install_any dump1090-fa dump1090-mutability dump1090 || true - fi - cmd_exists dump1090 || install_dump1090_from_source_debian - - setup_udev_rules_debian -} - -# ---------------------------- -# Final summary / hard fail -# ---------------------------- -final_summary_and_hard_fail() { - check_tools - - echo "============================================" - if [[ "${#missing_required[@]}" -eq 0 ]]; then - ok "All REQUIRED tools are installed." - else - fail "Missing REQUIRED tools:" - for t in "${missing_required[@]}"; do echo " - $t"; done - echo - fail "Exiting because required tools are missing." - echo - warn "If you are on macOS: hcitool/hciconfig are Linux (BlueZ) tools and may not be installable." - warn "If you truly require them everywhere, you must restrict supported platforms or provide alternatives." - exit 1 - fi - - echo - echo "To start INTERCEPT:" - echo " source venv/bin/activate" - echo " sudo python intercept.py" - echo - echo "Then open http://localhost:5050 in your browser" - echo -} - -# ---------------------------- -# MAIN -# ---------------------------- -main() { - detect_os - - if [[ "$OS" == "macos" ]]; then - install_macos_packages - else - install_debian_packages - fi - - install_python_deps - final_summary_and_hard_fail -} - -main "$@" - diff --git a/setup.sh b/setup.sh old mode 100755 new mode 100644 index 6eab522..dbbfcc7 --- a/setup.sh +++ b/setup.sh @@ -1,26 +1,43 @@ -#!/bin/bash -# -# INTERCEPT Setup Script -# Installs dependencies for macOS and Debian/Ubuntu -# +#!/usr/bin/env bash +# INTERCEPT Setup Script (best-effort installs, hard-fail verification) -# Don't exit on errors - we handle them explicitly -set +e +# ---- Force bash even if launched with sh ---- +if [ -z "${BASH_VERSION:-}" ]; then + echo "[x] This script must be run with bash (not sh)." + echo " Run: bash $0" + exec bash "$0" "$@" +fi -# Pause briefly after each action so output is readable -PAUSE_TIME=1 +set -Eeuo pipefail -pause() { - sleep $PAUSE_TIME -} +# Ensure admin paths are searchable (many tools live here) +export PATH="/usr/local/sbin:/usr/sbin:/sbin:/opt/homebrew/sbin:/opt/homebrew/bin:$PATH" -# Colors for output +# ---------------------------- +# Pretty output +# ---------------------------- RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color +NC='\033[0m' +info() { echo -e "${BLUE}[*]${NC} $*"; } +ok() { echo -e "${GREEN}[✓]${NC} $*"; } +warn() { echo -e "${YELLOW}[!]${NC} $*"; } +fail() { echo -e "${RED}[x]${NC} $*"; } + +on_error() { + local line="$1" + local cmd="${2:-unknown}" + fail "Setup failed at line ${line}: ${cmd}" + exit 1 +} +trap 'on_error $LINENO "$BASH_COMMAND"' ERR + +# ---------------------------- +# Banner +# ---------------------------- echo -e "${BLUE}" echo " ___ _ _ _____ _____ ____ ____ _____ ____ _____ " echo " |_ _| \\ | |_ _| ____| _ \\ / ___| ____| _ \\_ _|" @@ -28,619 +45,356 @@ echo " | || \\| | | | | _| | |_) | | | _| | |_) || | " echo " | || |\\ | | | | |___| _ <| |___| |___| __/ | | " echo " |___|_| \\_| |_| |_____|_| \\_\\\\____|_____|_| |_| " echo -e "${NC}" -echo "Signal Intelligence Platform - Setup Script" +echo "INTERCEPT - Setup Script" echo "============================================" -echo "" +echo + +# ---------------------------- +# Helpers +# ---------------------------- +cmd_exists() { + local c="$1" + command -v "$c" >/dev/null 2>&1 && return 0 + [[ -x "/usr/sbin/$c" || -x "/sbin/$c" || -x "/usr/local/sbin/$c" || -x "/opt/homebrew/sbin/$c" ]] && return 0 + return 1 +} + +have_any() { + local c + for c in "$@"; do + cmd_exists "$c" && return 0 + done + return 1 +} + +need_sudo() { + if [[ "$(id -u)" -eq 0 ]]; then + SUDO="" + ok "Running as root" + else + if cmd_exists sudo; then + SUDO="sudo" + else + fail "sudo is not installed and you're not root." + echo "Either run as root or install sudo first." + exit 1 + fi + fi +} -# Detect OS detect_os() { - if [[ "$OSTYPE" == "darwin"* ]]; then - OS="macos" - PKG_MANAGER="brew" - elif [[ -f /etc/debian_version ]]; then - OS="debian" - PKG_MANAGER="apt" - else - OS="unknown" - PKG_MANAGER="unknown" - fi - echo -e "${BLUE}Detected OS:${NC} $OS" + if [[ "${OSTYPE:-}" == "darwin"* ]]; then + OS="macos" + elif [[ -f /etc/debian_version ]]; then + OS="debian" + else + OS="unknown" + fi + info "Detected OS: ${OS}" + [[ "$OS" != "unknown" ]] || { fail "Unsupported OS (macOS + Debian/Ubuntu only)."; exit 1; } } -# Check if a command exists (also check /usr/sbin for Debian) -check_cmd() { - command -v "$1" &> /dev/null || [ -x "/usr/sbin/$1" ] || [ -x "/sbin/$1" ] -} +# ---------------------------- +# Required tool checks (with alternates) +# ---------------------------- +missing_required=() -# Check if a package is installable (Debian) -pkg_available() { - local candidate - candidate=$(apt-cache policy "$1" 2>/dev/null | grep "Candidate:" | awk '{print $2}') - [ -n "$candidate" ] && [ "$candidate" != "(none)" ] -} +check_required() { + local label="$1"; shift + local desc="$1"; shift -# Setup sudo command -setup_sudo() { - if [ "$(id -u)" -eq 0 ]; then - SUDO="" - echo -e "${BLUE}Running as root${NC}" - elif check_cmd sudo; then - SUDO="sudo" - else - echo -e "${RED}Error: Not running as root and sudo is not installed${NC}" - exit 1 - fi -} - -# ============================================ -# PYTHON DEPENDENCIES -# ============================================ -install_python_deps() { - echo "" - echo -e "${BLUE}[3/3] Installing Python dependencies...${NC}" - - if ! check_cmd python3; then - echo -e "${RED}Error: Python 3 is not installed${NC}" - if [[ "$OS" == "macos" ]]; then - echo "Install with: brew install python@3.11" - else - echo "Install with: sudo apt install python3" - fi - exit 1 - fi - - # Check Python version - PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') - PYTHON_MAJOR=$(python3 -c 'import sys; print(sys.version_info.major)') - PYTHON_MINOR=$(python3 -c 'import sys; print(sys.version_info.minor)') - echo "Python version: $PYTHON_VERSION" - - if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 9 ]); then - echo -e "${RED}Error: Python 3.9 or later is required (you have $PYTHON_VERSION)${NC}" - if [[ "$OS" == "macos" ]]; then - echo "Upgrade with: brew install python@3.11" - else - echo "Upgrade with: sudo apt install python3.11" - fi - exit 1 - fi - - # Install dependencies - if [ -n "$VIRTUAL_ENV" ]; then - echo "Using virtual environment: $VIRTUAL_ENV" - pip install -r requirements.txt || echo -e "${YELLOW}Warning: Some Python packages may have failed${NC}" - elif [ -f "venv/bin/activate" ]; then - echo "Found existing venv, activating..." - source venv/bin/activate - pip install -r requirements.txt || echo -e "${YELLOW}Warning: Some Python packages may have failed${NC}" - else - # Try pip install, fall back to venv if needed (PEP 668) - if python3 -m pip install -r requirements.txt 2>/dev/null; then - echo -e "${GREEN}Python dependencies installed${NC}" - return - fi - - echo -e "${YELLOW}Creating virtual environment...${NC}" - if [ -d "venv" ] && [ ! -f "venv/bin/activate" ]; then - rm -rf venv - fi - - # Install python3-venv if needed - if [[ "$OS" == "debian" ]]; then - $SUDO apt-get install -y python3-venv 2>/dev/null || true - fi - - if ! python3 -m venv venv; then - echo -e "${RED}Error: Failed to create virtual environment${NC}" - echo -e "${YELLOW}Continuing with system tool installation...${NC}" - return - fi - - source venv/bin/activate - pip install -r requirements.txt || echo -e "${YELLOW}Warning: Some Python packages may have failed${NC}" - - echo "" - echo -e "${YELLOW}NOTE: Virtual environment created.${NC}" - echo "Activate with: source venv/bin/activate" - fi - - echo -e "${GREEN}Python dependencies installed${NC}" -} - -# ============================================ -# TOOL CHECKING -# ============================================ -check_tool() { - local cmd=$1 - local desc=$2 - local category=$3 - if check_cmd "$cmd"; then - echo -e " ${GREEN}✓${NC} $cmd - $desc" - return 0 - else - echo -e " ${RED}✗${NC} $cmd - $desc ${YELLOW}(not found)${NC}" - MISSING_TOOLS+=("$cmd") - case "$category" in - core) MISSING_CORE=true ;; - audio) MISSING_AUDIO=true ;; - wifi) MISSING_WIFI=true ;; - bluetooth) MISSING_BLUETOOTH=true ;; - esac - return 1 - fi + if have_any "$@"; then + ok "${label} - ${desc}" + else + warn "${label} - ${desc} (missing, required)" + missing_required+=("$label") + fi } check_tools() { - echo "" - echo -e "${BLUE}[1/3] Checking external tools...${NC}" - echo "" + info "Checking required tools..." + missing_required=() - MISSING_TOOLS=() - MISSING_CORE=false - MISSING_AUDIO=false - MISSING_WIFI=false - MISSING_BLUETOOTH=false + echo + info "Core SDR:" + check_required "rtl_fm" "RTL-SDR FM demodulator" rtl_fm + check_required "rtl_test" "RTL-SDR device detection" rtl_test + check_required "multimon-ng" "Pager decoder" multimon-ng + check_required "rtl_433" "433MHz sensor decoder" rtl_433 rtl433 + check_required "dump1090" "ADS-B decoder" dump1090 - echo "Core SDR Tools:" - check_tool "rtl_fm" "RTL-SDR FM demodulator" "core" - check_tool "rtl_test" "RTL-SDR device detection" "core" - check_tool "multimon-ng" "Pager decoder" "core" - check_tool "rtl_433" "433MHz sensor decoder" "core" - check_tool "dump1090" "ADS-B decoder" "core" + echo + info "GPS:" + check_required "gpsd" "GPS daemon" gpsd - echo "" - echo "Audio Tools:" - check_tool "ffmpeg" "Audio encoder for streaming" "audio" + echo + info "Audio:" + check_required "ffmpeg" "Audio encoder/decoder" ffmpeg - echo "" - echo "WiFi Tools:" - check_tool "airmon-ng" "WiFi monitor mode" "wifi" - check_tool "airodump-ng" "WiFi scanner" "wifi" - # aireplay-ng is optional (for deauth) - if check_cmd aireplay-ng; then - echo -e " ${GREEN}✓${NC} aireplay-ng - Deauthentication (optional)" - fi - # PMKID tools are optional - if check_cmd hcxdumptool; then - echo -e " ${GREEN}✓${NC} hcxdumptool - PMKID capture (optional)" - else - echo -e " ${YELLOW}-${NC} hcxdumptool - PMKID capture (optional)" - fi - if check_cmd hcxpcapngtool; then - echo -e " ${GREEN}✓${NC} hcxpcapngtool - Hash extraction (optional)" - else - echo -e " ${YELLOW}-${NC} hcxpcapngtool - Hash extraction (optional)" - fi + echo + info "WiFi:" + check_required "airmon-ng" "Monitor mode helper" airmon-ng + check_required "airodump-ng" "WiFi scanner" airodump-ng + check_required "aireplay-ng" "Injection/deauth" aireplay-ng + check_required "hcxdumptool" "PMKID capture" hcxdumptool + check_required "hcxpcapngtool" "PMKID/pcapng conversion" hcxpcapngtool - echo "" - echo "Bluetooth Tools:" - check_tool "hcitool" "Bluetooth scanner" "bluetooth" - check_tool "bluetoothctl" "Bluetooth controller" "bluetooth" - check_tool "hciconfig" "Bluetooth adapter config" "bluetooth" + echo + info "Bluetooth:" + check_required "bluetoothctl" "Bluetooth controller CLI" bluetoothctl + check_required "hcitool" "Bluetooth scan utility" hcitool + check_required "hciconfig" "Bluetooth adapter config" hciconfig - echo "" - echo "Optional (LimeSDR/HackRF):" - if check_cmd SoapySDRUtil; then - echo -e " ${GREEN}✓${NC} SoapySDRUtil - SoapySDR support" - else - echo -e " ${YELLOW}-${NC} SoapySDRUtil - Not installed (optional)" - fi - - if [ ${#MISSING_TOOLS[@]} -gt 0 ]; then - echo "" - echo -e "${YELLOW}Some tools are missing.${NC}" - else - echo "" - echo -e "${GREEN}All tools installed!${NC}" - fi + echo + info "SoapySDR:" + check_required "SoapySDRUtil" "SoapySDR CLI utility" SoapySDRUtil + echo } -# ============================================ -# macOS INSTALLATION -# ============================================ -install_macos_tools() { - echo "" - echo -e "${BLUE}[2/3] Installing tools (macOS)...${NC}" - echo "" +# ---------------------------- +# Python venv + deps +# ---------------------------- +check_python_version() { + if ! cmd_exists python3; then + fail "python3 not found." + [[ "$OS" == "macos" ]] && echo "Install with: brew install python" + [[ "$OS" == "debian" ]] && echo "Install with: sudo apt-get install python3" + exit 1 + fi - if [ ${#MISSING_TOOLS[@]} -eq 0 ]; then - echo -e "${GREEN}All tools are already installed!${NC}" - return - fi + local ver + ver="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" + info "Python version: ${ver}" - # Check for Homebrew - if ! check_cmd brew; then - echo -e "${YELLOW}Homebrew is not installed. Installing...${NC}" - echo "" - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - - # Add brew to PATH for this session - if [[ -f /opt/homebrew/bin/brew ]]; then - eval "$(/opt/homebrew/bin/brew shellenv)" - elif [[ -f /usr/local/bin/brew ]]; then - eval "$(/usr/local/bin/brew shellenv)" - fi - - if ! check_cmd brew; then - echo -e "${RED}Failed to install Homebrew. Install manually:${NC}" - show_macos_manual - return - fi - fi - - echo -e "${YELLOW}Installing missing tools automatically...${NC}" - echo "" - - # Core SDR tools - if $MISSING_CORE; then - echo "" - echo -e "${BLUE}Installing Core SDR tools...${NC}" - - echo " Installing librtlsdr..." - brew install librtlsdr || echo -e "${YELLOW} Warning: librtlsdr installation failed${NC}" - - echo " Installing multimon-ng..." - brew install multimon-ng || echo -e "${YELLOW} Warning: multimon-ng installation failed${NC}" - - echo " Installing rtl_433..." - brew install rtl_433 || echo -e "${YELLOW} Warning: rtl_433 installation failed${NC}" - - # dump1090 - if ! check_cmd dump1090; then - echo " Installing dump1090..." - brew install dump1090-mutability || \ - echo -e "${YELLOW} Note: dump1090 may need manual installation${NC}" - fi - fi - - # Audio tools - if $MISSING_AUDIO; then - echo "" - echo -e "${BLUE}Installing Audio tools...${NC}" - echo " Installing ffmpeg..." - brew install ffmpeg || echo -e "${YELLOW} Warning: ffmpeg installation failed${NC}" - fi - - # WiFi tools - if $MISSING_WIFI; then - echo "" - echo -e "${BLUE}Installing WiFi tools...${NC}" - echo " Installing aircrack-ng..." - brew install aircrack-ng || echo -e "${YELLOW} Warning: aircrack-ng installation failed${NC}" - echo " Installing hcxtools (PMKID capture)..." - brew install hcxtools || echo -e "${YELLOW} Warning: hcxtools installation failed${NC}" - fi - - echo "" - echo -e "${GREEN}Tool installation complete!${NC}" + python3 - <<'PY' +import sys +raise SystemExit(0 if sys.version_info >= (3,9) else 1) +PY + ok "Python version OK (>= 3.9)" } -show_macos_manual() { - echo "" - echo -e "${BLUE}Manual installation (macOS):${NC}" - echo "" - echo "# Required tools" - echo "brew install librtlsdr multimon-ng rtl_433 ffmpeg" - echo "" - echo "# ADS-B tracking" - echo "brew install dump1090-mutability" - echo "" - echo "# WiFi scanning (optional)" - echo "brew install aircrack-ng hcxtools" +install_python_deps() { + info "Setting up Python virtual environment..." + check_python_version + + if [[ ! -f requirements.txt ]]; then + warn "requirements.txt not found; skipping Python dependency install." + return 0 + fi + + if [[ ! -d venv ]]; then + python3 -m venv venv + ok "Created venv/" + else + ok "Using existing venv/" + fi + + # shellcheck disable=SC1091 + source venv/bin/activate + + python -m pip install --upgrade pip setuptools wheel >/dev/null + ok "Upgraded pip tooling" + + info "Installing Python requirements..." + python -m pip install -r requirements.txt + ok "Python dependencies installed" + echo } -# ============================================ -# BUILD DUMP1090 FROM SOURCE -# ============================================ -install_dump1090_from_source() { - echo " Installing build dependencies..." - $SUDO apt-get install -y build-essential git librtlsdr-dev libusb-1.0-0-dev \ - pkg-config libncurses-dev debhelper tcl-dev python3-dev || true +# ---------------------------- +# macOS install (Homebrew) +# ---------------------------- +ensure_brew() { + cmd_exists brew && return 0 + warn "Homebrew not found. Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - # Save current directory - local orig_dir=$(pwd) - local tmp_dir=$(mktemp -d) + if [[ -x /opt/homebrew/bin/brew ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + elif [[ -x /usr/local/bin/brew ]]; then + eval "$(/usr/local/bin/brew shellenv)" + fi - echo " Cloning dump1090 repository..." - if ! git clone --depth 1 https://github.com/flightaware/dump1090.git "$tmp_dir/dump1090" 2>&1; then - echo -e "${RED} Failed to clone dump1090 repository${NC}" - rm -rf "$tmp_dir" - return 1 - fi - - cd "$tmp_dir/dump1090" - - echo " Compiling dump1090 (this may take a minute)..." - # Try to build - use BLADERF=no to skip BladeRF dependency - if make BLADERF=no RTLSDR=yes 2>&1; then - echo " Installing dump1090 to /usr/local/bin..." - $SUDO cp dump1090 /usr/local/bin/ - $SUDO chmod +x /usr/local/bin/dump1090 - echo -e "${GREEN} dump1090 installed successfully!${NC}" - else - echo -e "${RED} Failed to compile dump1090${NC}" - echo " Trying simpler antirez version..." - - # Try the simpler antirez version as fallback - cd "$tmp_dir" - rm -rf dump1090 - if git clone --depth 1 https://github.com/antirez/dump1090.git 2>&1; then - cd dump1090 - if make 2>&1; then - $SUDO cp dump1090 /usr/local/bin/ - $SUDO chmod +x /usr/local/bin/dump1090 - echo -e "${GREEN} dump1090 (antirez) installed successfully!${NC}" - else - echo -e "${RED} Failed to compile dump1090${NC}" - fi - fi - fi - - # Cleanup - cd "$orig_dir" - rm -rf "$tmp_dir" + cmd_exists brew || { fail "Homebrew install failed. Install manually then re-run."; exit 1; } } -# ============================================ -# DEBIAN INSTALLATION -# ============================================ -install_debian_tools() { - echo "" - echo -e "${BLUE}[2/3] Installing tools (Debian/Ubuntu)...${NC}" - echo "" - - echo "Updating package lists..." - $SUDO apt-get update -qq - - # Always try to install all tools - apt will skip already installed ones - echo "" - echo -e "${BLUE}Installing Core SDR tools...${NC}" - - # Install rtl-sdr - echo " Installing rtl-sdr..." - if $SUDO apt-get install -y rtl-sdr; then - echo -e "${GREEN} rtl-sdr installed${NC}" - else - echo -e "${YELLOW} Warning: rtl-sdr installation failed${NC}" - fi - pause - - # Install multimon-ng - echo " Installing multimon-ng..." - if $SUDO apt-get install -y multimon-ng; then - echo -e "${GREEN} multimon-ng installed${NC}" - else - echo -e "${YELLOW} Warning: multimon-ng installation failed${NC}" - fi - pause - - # rtl-433 (package name varies by distribution) - echo " Installing rtl-433..." - if $SUDO apt-get install -y rtl-433 2>/dev/null; then - echo -e "${GREEN} rtl-433 installed${NC}" - elif $SUDO apt-get install -y rtl433 2>/dev/null; then - echo -e "${GREEN} rtl433 installed${NC}" - else - echo -e "${YELLOW} Note: rtl-433 not in repositories${NC}" - echo " Install manually from: https://github.com/merbanan/rtl_433" - fi - pause - - # dump1090 (package varies by distribution) - echo " Installing dump1090..." - if check_cmd dump1090; then - echo -e "${GREEN} dump1090 already installed${NC}" - elif $SUDO apt-get install -y dump1090-fa 2>/dev/null; then - echo -e "${GREEN} dump1090-fa installed${NC}" - elif $SUDO apt-get install -y dump1090-mutability 2>/dev/null; then - echo -e "${GREEN} dump1090-mutability installed${NC}" - elif $SUDO apt-get install -y dump1090 2>/dev/null; then - echo -e "${GREEN} dump1090 installed${NC}" - else - # Build from source as fallback - echo -e "${YELLOW} dump1090 not in repositories, building from source...${NC}" - install_dump1090_from_source - fi - pause - - # Audio tools - echo "" - echo -e "${BLUE}Installing Audio tools...${NC}" - echo " Installing ffmpeg..." - if $SUDO apt-get install -y ffmpeg; then - echo -e "${GREEN} ffmpeg installed${NC}" - else - echo -e "${YELLOW} Warning: ffmpeg installation failed${NC}" - fi - pause - - # WiFi tools - echo "" - echo -e "${BLUE}Installing WiFi tools...${NC}" - echo " Installing aircrack-ng..." - if $SUDO apt-get install -y aircrack-ng; then - echo -e "${GREEN} aircrack-ng installed${NC}" - else - echo -e "${YELLOW} Warning: aircrack-ng installation failed${NC}" - fi - pause - - # PMKID capture tools - echo " Installing hcxdumptool (PMKID capture)..." - if $SUDO apt-get install -y hcxdumptool; then - echo -e "${GREEN} hcxdumptool installed${NC}" - else - echo -e "${YELLOW} Warning: hcxdumptool installation failed${NC}" - fi - pause - - echo " Installing hcxtools (hash extraction)..." - if $SUDO apt-get install -y hcxtools; then - echo -e "${GREEN} hcxtools installed${NC}" - else - echo -e "${YELLOW} Warning: hcxtools installation failed${NC}" - fi - pause - - # Bluetooth tools - echo "" - echo -e "${BLUE}Installing Bluetooth tools...${NC}" - echo " Installing bluez..." - if $SUDO apt-get install -y bluez bluetooth; then - echo -e "${GREEN} bluez installed${NC}" - else - echo -e "${YELLOW} Warning: bluez installation failed${NC}" - fi - pause - - echo "" - echo -e "${GREEN}Tool installation complete!${NC}" - pause - - # Setup udev rules - setup_udev_rules - - # Verify installation - echo "" - echo -e "${BLUE}Verifying installation...${NC}" - verify_tools +brew_install() { + local pkg="$1" + if brew list --formula "$pkg" >/dev/null 2>&1; then + ok "brew: ${pkg} already installed" + return 0 + fi + info "brew: installing ${pkg}..." + brew install "$pkg" + ok "brew: installed ${pkg}" } -show_debian_manual() { - echo "" - echo -e "${BLUE}Manual installation (Debian/Ubuntu):${NC}" - echo "" - echo "# Required tools" - echo "sudo apt install rtl-sdr multimon-ng rtl-433 ffmpeg" - echo "" - echo "# ADS-B tracking" - echo "sudo apt install dump1090-mutability # or dump1090-fa" - echo "" - echo "# WiFi scanning (optional)" - echo "sudo apt install aircrack-ng hcxdumptool hcxtools" - echo "" - echo "# Bluetooth scanning (optional)" - echo "sudo apt install bluez bluetooth" +install_macos_packages() { + ensure_brew + info "Installing packages via Homebrew..." + + brew_install librtlsdr + brew_install multimon-ng + brew_install ffmpeg + brew_install rtl_433 + + # ADS-B (may not exist) + warn "Attempting dump1090 install via Homebrew (may be unavailable)..." + (brew_install dump1090-mutability) || true + + brew_install aircrack-ng + brew_install hcxtools + brew_install soapysdr + brew_install gpsd + + warn "macOS note: hcitool/hciconfig are Linux (BlueZ) utilities and often unavailable on macOS." + echo } -verify_tools() { - local all_ok=true +# ---------------------------- +# Debian/Ubuntu install (APT) +# ---------------------------- +apt_install() { $SUDO apt-get install -y --no-install-recommends "$@" >/dev/null; } - echo "" - if check_cmd rtl_fm; then - echo -e " ${GREEN}✓${NC} rtl_fm" - else - echo -e " ${RED}✗${NC} rtl_fm - NOT INSTALLED" - all_ok=false - fi - - if check_cmd multimon-ng; then - echo -e " ${GREEN}✓${NC} multimon-ng" - else - echo -e " ${RED}✗${NC} multimon-ng - NOT INSTALLED" - all_ok=false - fi - - if check_cmd rtl_433; then - echo -e " ${GREEN}✓${NC} rtl_433" - else - echo -e " ${YELLOW}-${NC} rtl_433 - not installed (optional)" - fi - - if check_cmd dump1090; then - echo -e " ${GREEN}✓${NC} dump1090" - else - echo -e " ${YELLOW}-${NC} dump1090 - not installed (optional)" - fi - - if check_cmd ffmpeg; then - echo -e " ${GREEN}✓${NC} ffmpeg" - else - echo -e " ${RED}✗${NC} ffmpeg - NOT INSTALLED" - all_ok=false - fi - - if check_cmd airmon-ng; then - echo -e " ${GREEN}✓${NC} aircrack-ng" - else - echo -e " ${YELLOW}-${NC} aircrack-ng - not installed (optional)" - fi - - if ! $all_ok; then - echo "" - echo -e "${YELLOW}Some required tools failed to install. You may need to install them manually.${NC}" +apt_try_install_any() { + local p + for p in "$@"; do + if $SUDO apt-get install -y --no-install-recommends "$p" >/dev/null 2>&1; then + ok "apt: installed ${p}" + return 0 fi + done + return 1 } -setup_udev_rules() { - if [ -f /etc/udev/rules.d/20-rtlsdr.rules ]; then - echo -e "${GREEN}udev rules already configured${NC}" - return - fi +install_dump1090_from_source_debian() { + info "dump1090 not available via APT. Building from source (required)..." - echo "" - echo -e "${BLUE}Setting up RTL-SDR udev rules...${NC}" - $SUDO bash -c 'cat > /etc/udev/rules.d/20-rtlsdr.rules << EOF + apt_install build-essential git pkg-config \ + librtlsdr-dev libusb-1.0-0-dev \ + libncurses-dev tcl-dev python3-dev + + local orig_dir tmp_dir + orig_dir="$(pwd)" + tmp_dir="$(mktemp -d)" + + cleanup() { cd "$orig_dir" >/dev/null 2>&1 || true; rm -rf "$tmp_dir"; } + trap cleanup EXIT + + info "Cloning FlightAware dump1090..." + git clone --depth 1 https://github.com/flightaware/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \ + || { fail "Failed to clone FlightAware dump1090"; exit 1; } + + cd "$tmp_dir/dump1090" + info "Compiling FlightAware dump1090..." + if make BLADERF=no RTLSDR=yes >/dev/null 2>&1; then + $SUDO install -m 0755 dump1090 /usr/local/bin/dump1090 + ok "dump1090 installed successfully (FlightAware)." + return 0 + fi + + warn "FlightAware build failed. Falling back to antirez/dump1090..." + rm -rf "$tmp_dir/dump1090" + git clone --depth 1 https://github.com/antirez/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \ + || { fail "Failed to clone antirez dump1090"; exit 1; } + + cd "$tmp_dir/dump1090" + info "Compiling antirez dump1090..." + make >/dev/null 2>&1 || { fail "Failed to build dump1090 from source (required)."; exit 1; } + + $SUDO install -m 0755 dump1090 /usr/local/bin/dump1090 + ok "dump1090 installed successfully (antirez)." +} + +setup_udev_rules_debian() { + [[ -d /etc/udev/rules.d ]] || { warn "udev not found; skipping RTL-SDR udev rules."; return 0; } + + local rules_file="/etc/udev/rules.d/20-rtlsdr.rules" + [[ -f "$rules_file" ]] && { ok "RTL-SDR udev rules already present: $rules_file"; return 0; } + + info "Installing RTL-SDR udev rules..." + $SUDO tee "$rules_file" >/dev/null <<'EOF' SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE="0666" SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE="0666" -EOF' - $SUDO udevadm control --reload-rules - $SUDO udevadm trigger - echo -e "${GREEN}udev rules installed!${NC}" - echo "Please unplug and replug your RTL-SDR if connected." +EOF + $SUDO udevadm control --reload-rules || true + $SUDO udevadm trigger || true + ok "udev rules installed. Unplug/replug your RTL-SDR if connected." + echo } -# ============================================ +install_debian_packages() { + need_sudo + info "Updating APT package lists..." + $SUDO apt-get update -y >/dev/null + + info "Installing required packages via APT..." + apt_install rtl-sdr + apt_install multimon-ng + apt_install ffmpeg + + apt_try_install_any rtl-433 rtl433 || true + + apt_install aircrack-ng || true + apt_install hcxdumptool || true + apt_install hcxtools || true + apt_install bluez bluetooth || true + apt_install soapysdr-tools || true + apt_install gpsd gpsd-clients || true + + # dump1090: apt first; source fallback; hard fail inside if it can't build + if ! cmd_exists dump1090; then + apt_try_install_any dump1090-fa dump1090-mutability dump1090 || true + fi + cmd_exists dump1090 || install_dump1090_from_source_debian + + setup_udev_rules_debian +} + +# ---------------------------- +# Final summary / hard fail +# ---------------------------- +final_summary_and_hard_fail() { + check_tools + + echo "============================================" + if [[ "${#missing_required[@]}" -eq 0 ]]; then + ok "All REQUIRED tools are installed." + else + fail "Missing REQUIRED tools:" + for t in "${missing_required[@]}"; do echo " - $t"; done + echo + fail "Exiting because required tools are missing." + echo + warn "If you are on macOS: hcitool/hciconfig are Linux (BlueZ) tools and may not be installable." + warn "If you truly require them everywhere, you must restrict supported platforms or provide alternatives." + exit 1 + fi + + echo + echo "To start INTERCEPT:" + echo " source venv/bin/activate" + echo " sudo python intercept.py" + echo + echo "Then open http://localhost:5050 in your browser" + echo +} + +# ---------------------------- # MAIN -# ============================================ +# ---------------------------- main() { - detect_os + detect_os - if [[ "$OS" == "unknown" ]]; then - echo -e "${RED}Unsupported OS. This script supports macOS and Debian/Ubuntu.${NC}" - exit 1 - fi + if [[ "$OS" == "macos" ]]; then + install_macos_packages + else + install_debian_packages + fi - if [[ "$OS" == "debian" ]]; then - setup_sudo - fi - - # Check and install system tools FIRST - check_tools - - if [[ "$OS" == "macos" ]]; then - install_macos_tools - else - install_debian_tools - fi - - # Install Python dependencies AFTER system tools - install_python_deps - - echo "" - echo "============================================" - echo -e "${GREEN}Setup complete!${NC}" - echo "" - echo "To start INTERCEPT:" - - if [ -d "venv" ]; then - echo " source venv/bin/activate" - if [[ "$OS" == "debian" ]]; then - echo " sudo venv/bin/python intercept.py" - else - echo " sudo python3 intercept.py" - fi - else - if [[ "$OS" == "debian" ]]; then - echo " sudo python3 intercept.py" - else - echo " sudo python3 intercept.py" - fi - fi - - echo "" - echo "Then open http://localhost:5050 in your browser" - echo "" + install_python_deps + final_summary_and_hard_fail } main "$@" +