diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-02 13:15:14 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-02 13:15:14 +0200 |
| commit | c5a0d1ca39a0ae61e03b0f38a30579b811b4b858 (patch) | |
| tree | 3f2728f97c266867e5ffc54f292d5e0161cacfb3 /rc.book-reader | |
| download | book-reader-c5a0d1ca39a0ae61e03b0f38a30579b811b4b858.tar.gz book-reader-c5a0d1ca39a0ae61e03b0f38a30579b811b4b858.zip | |
Add book-reader: two-page image book viewer
Browser viewer for books stored as folders of page images: two-page
spreads with a GPU-composited 3D page turn, keyboard/wheel/click
navigation, fit-height and fit-width (scroll then flip) modes, a library
of every image folder under the configured root, and per-book reading
progress in localStorage.
rc.book-reader serves it with python3 http.server on 127.0.0.1 from a
runtime dir of symlinks, so the library is never written to. It can be
copied to /etc/rc.d: started as root it re-executes itself as RUNAS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'rc.book-reader')
| -rwxr-xr-x | rc.book-reader | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/rc.book-reader b/rc.book-reader new file mode 100755 index 0000000..5ba30a3 --- /dev/null +++ b/rc.book-reader @@ -0,0 +1,61 @@ +#!/bin/bash +# rc.book-reader: start/stop the local server for book-reader. +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> +# SPDX-License-Identifier: GPL-2.0-only +# +# Config (shell syntax): ${XDG_CONFIG_HOME:-~/.config}/book-reader.conf +# LIBRARY=/path/to/collection # required; every folder with images inside is a book +# PORT=8642 # keep it fixed: reading progress is stored per origin +# BIND=127.0.0.1 +# READER=/path/to/book-reader/reader.html # needed when this script is copied out of the repo +# +# Boot (Slackware): copy to /etc/rc.d, set RUNAS below, call "start" from +# rc.local and "stop" from rc.local_shutdown. Run as root, the script +# re-executes itself as RUNAS: the web server never runs as root. + +RUNAS= # user to run as when started by root + +if [ "$(id -u)" = 0 ]; then + if [ -z "$RUNAS" ] || [ "$RUNAS" = root ]; then echo "set RUNAS in $0 to a non-root user" >&2; exit 1; fi + exec su - "$RUNAS" -s /bin/bash -c "$(printf '%q %q' "$(readlink -f "$0")" "$1")" +fi + +LIBRARY= PORT=8642 BIND=127.0.0.1 READER=$(dirname "$(readlink -f "$0")")/reader.html +CONF=${BOOK_READER_CONF:-${XDG_CONFIG_HOME:-$HOME/.config}/book-reader.conf} +[ -r "$CONF" ] && . "$CONF" + +# fixed path: boot (no XDG_RUNTIME_DIR) and desktop sessions must share the pidfile +RUN=/tmp/book-reader-$UID +PIDFILE=$RUN/pid +URL="http://$BIND:$PORT/reader.html" + +running() { [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; } + +start() { + if running; then echo "book-reader already running: $URL"; return 0; fi + if [ ! -d "$LIBRARY" ]; then echo "LIBRARY not set or missing (edit $CONF)" >&2; return 1; fi + if [ ! -r "$READER" ]; then echo "reader.html not found at $READER (set READER in $CONF)" >&2; return 1; fi + # Served root holds only symlinks: the viewer and the library, so neither dir gets touched. + mkdir -p -m 700 "$RUN" "$RUN/root" + find "$RUN/root" -mindepth 1 -maxdepth 1 -type l -delete + ln -s "$(readlink -f "$READER")" "$RUN/root/reader.html" + ln -s "$(readlink -f "$LIBRARY")" "$RUN/root/$(basename "$LIBRARY")" + setsid python3 -m http.server -b "$BIND" -d "$RUN/root" "$PORT" >"$RUN/log" 2>&1 & + echo $! >"$PIDFILE" + sleep 0.5 + if ! running; then echo "book-reader failed to start:" >&2; tail -n 5 "$RUN/log" >&2; rm -f "$PIDFILE"; return 1; fi + echo "book-reader started: $URL" +} + +stop() { + if running; then kill "$(cat "$PIDFILE")"; echo "book-reader stopped"; else echo "book-reader not running"; fi + rm -f "$PIDFILE" +} + +case "$1" in + start) start ;; + stop) stop ;; + restart) stop; start ;; + status) if running; then echo "book-reader running: $URL"; else echo "book-reader stopped"; exit 3; fi ;; + *) echo "usage: $0 start|stop|restart|status" >&2; exit 1 ;; +esac |
