First Addon migrated: menus/addon_cups.sh (install, reconfigure for network access, complete uninstall/purge). Different risk profile from everything migrated so far - it genuinely mutates real system state (apt install/remove --purge, /etc/cups, ufw) at fixed paths CUPS itself doesn't let us relocate, unlike the systemd/cron/bin paths this project already controls via $SYSTEMD_DIR etc. Only the polkit rule's directory is parameterized ($POLKIT_DIR, lib/config.sh, since that one is ours to place); everything else gets full command-level `sudo` stubbing in every test - there is no scratch equivalent for a real apt-managed subsystem's own file layout. Also added $BUILD_USER (the admin account actually running the tool, as opposed to $KIOSK_USER) since CUPS needs to grant it lpadmin group membership. Restructured install.sh's top-level menu into Core Settings / Addons / Advanced (matching the legacy tool) instead of one flat list, now that Addons exists as its own category - cheap to do with one item in it, much more annoying to retrofit once the flat list has fifteen. Two bugs caught and fixed before they shipped: - A "wait for CUPS to start" retry loop used a bare `cmd1 && cmd2 && break` as its body while "simplifying" the legacy script's `if cmd1 && cmd2; then break; fi`. Being inside a loop doesn't protect a bare &&/|| list from set -e - only if/while/until conditions and the protected side of &&/|| do that - so the first command failing on an early iteration (near-certain right after a fresh install, before CUPS has actually started) would have crashed the entire session. Restored the `if` form; noted the lesson in the file's own header comment since it's a general trap, not CUPS-specific. - Resolved real uncertainty, rather than assuming: how far does run_menu's `handler || true` guard (v2.1.0) actually protect? Wrote a minimal isolated test (a bare `false` three function calls deep, called via `outer || true` at the top) and confirmed bash's errexit exemption for the left side of `||` covers the *entire* evaluation, arbitrarily deep through function calls - not just the immediately invoked function. So the session-crash risk this project has been chasing since v2.1.0 is already covered end-to-end by that one fix. Per-statement guards (`|| true`, explicit `if`) still earn their keep for a different reason: without them a deep failure bubbles silently past the menu actually responsible for it to wherever the nearest `|| true` happens to sit, which can be several menu levels above where the user actually was - not a crash, but a confusing jump. Verified: - Full regression: re-ran every existing scratch-config/stub test suite after the lib/config.sh change (new $BUILD_USER/$POLKIT_DIR) and after the install.sh restructuring - all still clean. - New scratch/stub test for addon_cups.sh: full state-machine coverage (not installed -> decline -> install -> running -> reconfigure -> stopped -> start -> uninstall decline -> uninstall confirm -> not installed again) with every `sudo` call intercepted and only `rm` targeting the scratch $POLKIT_DIR ever actually executed; confirmed the polkit rule's content and that declining install makes zero sudo calls. Added both apt-failure paths (update fails, install fails) and confirmed the tool reports clearly and returns to the menu instead of dying, exercising the exact bug class just fixed. - End-to-end: ran the real install.sh as a genuine non-root, non- "kiosk" user through the full new three-level structure - Core Settings -> Sites -> back -> back, Addons -> CUPS -> declined install (using this container's real, unstubbed dpkg check, correctly reporting "not installed" and making no apt/systemctl calls) -> back -> back, Advanced -> Diagnostics -> System status -> back -> back -> Exit. Zero invalid-choice errors, clean exit code 0 throughout.
145 lines
4.6 KiB
Bash
Executable File
145 lines
4.6 KiB
Bash
Executable File
#!/bin/bash
|
|
################################################################################
|
|
# install.sh - Modular management entry point for Ubuntu Based Kiosk.
|
|
#
|
|
# This is NOT yet the full system installer - that is still the big
|
|
# single-file script (ubuntu-based-kiosk.sh) documented in Readme.md, and
|
|
# first-time provisioning of a new kiosk still goes through it. That file
|
|
# still also contains its own (unmigrated, unmodified) copies of every
|
|
# menu below - both copies coexist deliberately until enough of Core
|
|
# Settings/Addons/Advanced has moved over to retire the old ones in one
|
|
# pass. This entry point is the modular replacement, one menus/*.sh file
|
|
# at a time, so a change to (say) the Sites menu can't accidentally break
|
|
# WiFi setup or the uninstaller three thousand lines away.
|
|
#
|
|
# Migrated so far, grouped the same way the legacy menu groups them:
|
|
# Core Settings: Sites & Page Timing, Display & Interaction, Timezone,
|
|
# Hidden Site PIN, Password Protection & Lockout, WiFi,
|
|
# Power/Display/Quiet Hours.
|
|
# Addons: CUPS Printing (menus/addon_cups.sh).
|
|
# Advanced: Diagnostics (menus/diagnostics.sh - system status/logs/
|
|
# audio/network).
|
|
#
|
|
# Usage (once the kiosk has already been installed):
|
|
# git clone <repo>
|
|
# cd ubuntu-based-kiosk
|
|
# ./install.sh
|
|
################################################################################
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# shellcheck source=lib/menu.sh
|
|
source "$SCRIPT_DIR/lib/menu.sh"
|
|
# shellcheck source=lib/config.sh
|
|
source "$SCRIPT_DIR/lib/config.sh"
|
|
# shellcheck source=menus/sites.sh
|
|
source "$SCRIPT_DIR/menus/sites.sh"
|
|
# shellcheck source=menus/display.sh
|
|
source "$SCRIPT_DIR/menus/display.sh"
|
|
# shellcheck source=menus/timezone.sh
|
|
source "$SCRIPT_DIR/menus/timezone.sh"
|
|
# shellcheck source=menus/hidden_pin.sh
|
|
source "$SCRIPT_DIR/menus/hidden_pin.sh"
|
|
# shellcheck source=menus/lockout.sh
|
|
source "$SCRIPT_DIR/menus/lockout.sh"
|
|
# shellcheck source=menus/wifi.sh
|
|
source "$SCRIPT_DIR/menus/wifi.sh"
|
|
# shellcheck source=menus/power_schedule.sh
|
|
source "$SCRIPT_DIR/menus/power_schedule.sh"
|
|
# shellcheck source=menus/diagnostics.sh
|
|
source "$SCRIPT_DIR/menus/diagnostics.sh"
|
|
# shellcheck source=menus/addon_cups.sh
|
|
source "$SCRIPT_DIR/menus/addon_cups.sh"
|
|
|
|
################################################################################
|
|
# Preflight
|
|
################################################################################
|
|
|
|
if [[ "$(whoami)" == "kiosk" ]]; then
|
|
log_error "Cannot run as user 'kiosk'"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $EUID -eq 0 ]]; then
|
|
log_error "Run as a regular user with sudo privileges, not as root"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v jq &>/dev/null; then
|
|
log_error "jq is required but not installed. Run: sudo apt-get install -y jq"
|
|
exit 1
|
|
fi
|
|
|
|
if ! is_kiosk_installed; then
|
|
echo
|
|
log_error "No installed kiosk found at ${KIOSK_DIR}."
|
|
echo
|
|
echo "This tool manages an already-installed kiosk. To provision a new"
|
|
echo "one for the first time, use the full installer instead - see"
|
|
echo "Readme.md ('Quick Install') for the current download command."
|
|
echo
|
|
exit 1
|
|
fi
|
|
|
|
################################################################################
|
|
# Top-level menu - grouped the same way the legacy menu groups them
|
|
# (Core Settings / Addons / Advanced), so the structure stays familiar
|
|
# and the flat list doesn't grow unwieldy as more menus migrate in.
|
|
################################################################################
|
|
|
|
core_settings_menu_builder() {
|
|
MENU_LABELS=(
|
|
"Sites & Page Timing"
|
|
"Display & Interaction"
|
|
"Timezone"
|
|
"Hidden Site PIN"
|
|
"Password Protection & Lockout"
|
|
"WiFi"
|
|
"Power/Display/Quiet Hours"
|
|
)
|
|
MENU_HANDLERS=(
|
|
sites_menu
|
|
display_menu
|
|
timezone_menu
|
|
hidden_pin_menu
|
|
lockout_menu
|
|
wifi_menu
|
|
power_schedule_menu
|
|
)
|
|
}
|
|
|
|
core_settings_menu() {
|
|
run_menu "CORE SETTINGS" core_settings_menu_builder
|
|
}
|
|
|
|
addons_menu_builder() {
|
|
MENU_LABELS=("CUPS Printing")
|
|
MENU_HANDLERS=(addon_cups_menu)
|
|
}
|
|
|
|
addons_menu() {
|
|
run_menu "ADDONS" addons_menu_builder
|
|
}
|
|
|
|
advanced_menu_builder() {
|
|
MENU_LABELS=("Diagnostics")
|
|
MENU_HANDLERS=(diagnostics_menu)
|
|
}
|
|
|
|
advanced_menu() {
|
|
run_menu "ADVANCED" advanced_menu_builder
|
|
}
|
|
|
|
main_menu_builder() {
|
|
MENU_LABELS=("Core Settings" "Addons" "Advanced")
|
|
MENU_HANDLERS=(core_settings_menu addons_menu advanced_menu)
|
|
}
|
|
|
|
main_menu_status() {
|
|
echo "Managing kiosk at: ${KIOSK_DIR}"
|
|
}
|
|
|
|
run_menu "UBUNTU BASED KIOSK - MANAGEMENT" main_menu_builder main_menu_status "Exit"
|