- CUPS (Addons -> CUPS Printing, from ./install.sh or the Web UI) now installs from the offline bundle by itself when the kiosk can't reach the Ubuntu archive: lib/config.sh's run_with_offline_fallback switches apt to the bundle (kiosk-offline-apt on) around the install and back afterwards. No-op on manual installs or when online. - Fix cups_is_installed reporting "not installed" for an installed CUPS: `dpkg -l | grep -q` under install.sh's pipefail fails when grep exits early and dpkg takes SIGPIPE. Uses dpkg-query on the one package now. - Sites: an absolute path (/home/kiosk/docs/menu.pdf) is accepted and turned into a percent-encoded file:// URL, identically in the Sites menu (sites_parse_url) and the Web UI (parseUrl, with tests). Electron 42 shows local HTML, PDFs (built-in viewer) and images as-is. - iso/build-iso.sh checks its build tools (plus the --offline ones) and offers to `sudo apt install` what's missing; --install-deps does it without asking. --offline now refuses non-amd64 hosts up front. Tested: offline chroot of the 26.04.1 server filesystem - action_install_cups installed CUPS + printer-driver-all/hplip/gutenprint from the bundle with no network and left apt back on normal sources; webui test suite passes; Electron 42 rendered a file:// PDF and PNG with spaces/# in the path; build-iso.sh stopped with the install command when apt-utils was missing and no TTY, and installed it and built the ISO with --install-deps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cjz8a58eB5P9sUweqd3NHm
175 lines
6.2 KiB
Bash
175 lines
6.2 KiB
Bash
#!/bin/bash
|
|
################################################################################
|
|
# menus/addon_cups.sh - "CUPS Printing" addon (from the legacy Addons menu).
|
|
#
|
|
# First Addon migrated. Genuinely mutates real system state - installs/
|
|
# purges apt packages, writes /etc/cups/cupsd.conf and a polkit rule,
|
|
# touches ufw - at fixed paths CUPS itself doesn't let us relocate the
|
|
# way $SYSTEMD_DIR/$CRON_D_DIR/etc let us relocate our own files. Only
|
|
# the polkit rule's directory is parameterized ($POLKIT_DIR, since that's
|
|
# ours to place); everything else (cupsd.conf, apt, systemctl, ufw) gets
|
|
# full command-level `sudo` stubbing in every test - there is no scratch
|
|
# equivalent for a real apt-managed subsystem's own file layout.
|
|
#
|
|
# Depends on: lib/menu.sh, lib/config.sh being sourced first.
|
|
################################################################################
|
|
|
|
# Also read by iso/offline/build-bundle.sh to bundle these for offline installs.
|
|
CUPS_APT_PACKAGES=(
|
|
cups cups-client cups-filters printer-driver-all
|
|
printer-driver-cups-pdf hplip printer-driver-gutenprint
|
|
foomatic-db-compressed-ppds openprinting-ppds
|
|
)
|
|
|
|
cups_is_installed() {
|
|
# Not `dpkg -l | grep -q`: grep -q exits at the first match, dpkg
|
|
# takes SIGPIPE writing the rest of its long list, and under
|
|
# install.sh's `set -o pipefail` that made this report "not
|
|
# installed" for an installed CUPS.
|
|
[[ "$(dpkg-query -W -f='${db:Status-Abbrev}' cups 2>/dev/null)" == "ii "* ]]
|
|
}
|
|
|
|
cups_is_active() {
|
|
systemctl is-active --quiet cups
|
|
}
|
|
|
|
addon_cups_status() {
|
|
if cups_is_installed && cups_is_active; then
|
|
echo "CUPS: installed and running (http://$(get_ip_address):631)"
|
|
elif cups_is_installed; then
|
|
echo "CUPS: installed but not running"
|
|
else
|
|
echo "CUPS: not installed"
|
|
fi
|
|
}
|
|
|
|
addon_cups_menu_builder() {
|
|
if cups_is_installed && cups_is_active; then
|
|
MENU_LABELS=("Reconfigure for network access" "Complete uninstall (purge)")
|
|
MENU_HANDLERS=(action_reconfigure_cups action_cups_uninstall)
|
|
elif cups_is_installed; then
|
|
MENU_LABELS=("Start CUPS" "Complete uninstall (purge)")
|
|
MENU_HANDLERS=(action_start_cups action_cups_uninstall)
|
|
else
|
|
MENU_LABELS=("Install CUPS printing")
|
|
MENU_HANDLERS=(action_install_cups)
|
|
fi
|
|
}
|
|
|
|
addon_cups_menu() {
|
|
run_menu "CUPS PRINTING SUPPORT" addon_cups_menu_builder addon_cups_status
|
|
}
|
|
|
|
################################################################################
|
|
# Actions
|
|
################################################################################
|
|
|
|
cups_apt_install() {
|
|
if ! sudo apt update; then
|
|
log_error "apt update failed - check network/package sources and try again"
|
|
return 1
|
|
fi
|
|
if ! sudo apt install -y "${CUPS_APT_PACKAGES[@]}"; then
|
|
log_error "CUPS package installation failed"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
action_install_cups() {
|
|
echo
|
|
ask_yes_no "Install CUPS printing?" "n" || { echo "Cancelled"; return; }
|
|
|
|
echo "Installing CUPS from scratch..."
|
|
run_with_offline_fallback cups_apt_install || return 1
|
|
|
|
sudo systemctl enable cups 2>/dev/null || true
|
|
sudo systemctl start cups 2>/dev/null || true
|
|
|
|
echo "Waiting for CUPS to start..."
|
|
for _ in {1..30}; do
|
|
# Must stay in an `if` - a bare `cmd1 && cmd2` statement is
|
|
# subject to set -e itself when cmd1 fails, which is virtually
|
|
# guaranteed on early iterations right after install.
|
|
if cups_is_active && lpstat -r &>/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
# $BUILD_USER already resolves to $SUDO_USER when the tool was run via
|
|
# sudo, so a single usermod covers it - the legacy code ran this twice
|
|
# (once for a hardcoded computed user, once again for $SUDO_USER
|
|
# directly), which was harmless but genuinely redundant.
|
|
sudo usermod -aG lpadmin "$BUILD_USER"
|
|
|
|
action_reconfigure_cups
|
|
|
|
log_success "CUPS installed"
|
|
echo " Web interface: http://$(get_ip_address):631"
|
|
}
|
|
|
|
action_start_cups() {
|
|
sudo systemctl enable cups
|
|
sudo systemctl start cups
|
|
log_success "CUPS started"
|
|
}
|
|
|
|
action_reconfigure_cups() {
|
|
if [[ -f /etc/cups/cupsd.conf ]]; then
|
|
sudo cp /etc/cups/cupsd.conf "/etc/cups/cupsd.conf.backup-$(date +%Y%m%d-%H%M%S)"
|
|
fi
|
|
|
|
if command -v cupsctl &>/dev/null; then
|
|
sudo cupsctl --remote-admin --remote-any --share-printers 2>/dev/null || true
|
|
fi
|
|
|
|
sudo sed -i 's/^Listen localhost:631/Port 631/' /etc/cups/cupsd.conf 2>/dev/null || true
|
|
sudo sed -i 's/^Listen 127.0.0.1:631/Port 631/' /etc/cups/cupsd.conf 2>/dev/null || true
|
|
|
|
sudo mkdir -p "$POLKIT_DIR"
|
|
sudo tee "$POLKIT_DIR/kiosk-printing.pkla" > /dev/null <<EOF
|
|
[Allow kiosk printing]
|
|
Identity=unix-user:${KIOSK_USER}
|
|
Action=org.opensuse.cupspkhelper.mechanism.*
|
|
ResultAny=yes
|
|
ResultInactive=yes
|
|
ResultActive=yes
|
|
EOF
|
|
|
|
sudo ufw allow 631/tcp comment 'CUPS' 2>/dev/null || true
|
|
sudo systemctl restart cups 2>/dev/null || true
|
|
|
|
log_success "CUPS configured for network access"
|
|
}
|
|
|
|
action_cups_uninstall() {
|
|
echo
|
|
ask_yes_no "Completely remove CUPS, including all queues and settings (purge)?" "n" || { echo "Cancelled"; return; }
|
|
cups_do_uninstall
|
|
}
|
|
|
|
# The actual removal, no prompt - shared with Complete Uninstall so that
|
|
# operation doesn't need to re-implement CUPS teardown a second time.
|
|
cups_do_uninstall() {
|
|
echo "Performing complete CUPS uninstall..."
|
|
|
|
sudo systemctl stop cups cups-browsed 2>/dev/null || true
|
|
sudo systemctl disable cups cups-browsed 2>/dev/null || true
|
|
|
|
sudo apt remove --purge -y cups cups-daemon cups-client cups-filters \
|
|
cups-common cups-core-drivers cups-server-common cups-browsed \
|
|
cups-ppdc cups-bsd libcups2 libcupsimage2 2>/dev/null || true
|
|
|
|
sudo apt remove --purge -y printer-driver-all printer-driver-cups-pdf \
|
|
hplip printer-driver-gutenprint foomatic-db-compressed-ppds \
|
|
openprinting-ppds 2>/dev/null || true
|
|
|
|
sudo rm -rf /etc/cups /var/cache/cups /var/spool/cups /var/log/cups /usr/share/cups
|
|
sudo rm -f "$POLKIT_DIR/kiosk-printing.pkla"
|
|
|
|
sudo apt autoremove -y 2>/dev/null || true
|
|
sudo apt clean 2>/dev/null || true
|
|
|
|
log_success "CUPS completely removed"
|
|
}
|