#!/bin/bash # start-session.sh -- one visitor's session: the saved demo machine, resumed at its prompt, its # serial console on this terminal; gone when the visitor leaves or the time is up (issue #112). # ttyd runs this once per browser connection (issue #114). # # demo/start-session.sh [state-dir] (default: /var/lib/starshipos-demo) # # Nothing a visitor does survives the session: the firmware variables are a copy, the identity # drive's writes are discarded, the image is read-only, and the guest has no network. set -euo pipefail here=$(cd "$(dirname "$0")" && pwd) . "$here/qemu-args.sh" dir=${1:-${DEMO_STATE:-/var/lib/starshipos-demo}} limit=${DEMO_SESSION_LIMIT:-1800} # seconds a session may last [ -f "$dir/state" ] || { echo "The demo is not set up yet: no saved machine in $dir." >&2; exit 1; } tmp=$(mktemp -d "${TMPDIR:-/tmp}/starshipos-session.XXXXXX") trap 'rm -rf "$tmp"' EXIT cp "$dir/vars.fd" "$tmp/vars.fd" demo_qemu_args "$dir" "$tmp/vars.fd" printf '\r\nStarshipOS -- starting a throwaway machine, yours for up to %d minutes. Nothing you do is kept.\r\n' $((limit / 60)) printf 'Try: 3 4 + . : SQUARE DUP * ; 7 SQUARE .\r\n\r\n' # QEMU is a tracked child, not exec'd, so that whatever ends the session ends the machine: ttyd # hangs up (it signals this script only), the service stops, or the time runs out. Its console is # a private socket, joined to this terminal by console.py only once the machine runs: keys typed # while it loads would be lost half-way through a line. qemu-system-x86_64 "${QEMU_ARGS[@]}" \ -chardev "socket,id=con,path=$tmp/con.sock,server=on,wait=off" -serial chardev:con \ -qmp "unix:$tmp/qmp.sock,server=on,wait=off" -monitor none \ -incoming "file:$dir/state" /dev/null ) & timer=$! # The bridge is a tracked child too: bash runs a trap only once its foreground command returns, # so a hang-up would otherwise wait on the bridge. `wait` returns to the trap at once. python3 -I "$here/console.py" "$tmp/qmp.sock" "$tmp/con.sock" 0<&0 & bridge=$! trap 'kill "$bridge" "$qemu" "$timer" 2>/dev/null; rm -rf "$tmp"' EXIT trap 'exit 0' HUP TERM INT wait "$bridge" || true printf '\r\n\r\nThe session has ended. Reload the page for a new one.\r\n'