From eca967a494e5144e662d174261d06c5ffbb1916d Mon Sep 17 00:00:00 2001 From: randogoth Date: Sat, 18 Oct 2025 20:34:07 +0300 Subject: [PATCH] cleanup --- Dockerfile | 1 - scripts/dos-shell | 203 ++++++++++++++++++++++++------------- scripts/prepare-svardos.sh | 96 +++++------------- 3 files changed, 162 insertions(+), 138 deletions(-) diff --git a/Dockerfile b/Dockerfile index a819c0e..276b22a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,6 @@ RUN apt-get update && \ unzip \ file \ && add-apt-repository -y ppa:dosemu2/ppa && \ - apt-get update && \ apt-get install -y --no-install-recommends \ dosemu2 \ && rm -rf /var/lib/apt/lists/* diff --git a/scripts/dos-shell b/scripts/dos-shell index a0d37f4..d1f51f2 100755 --- a/scripts/dos-shell +++ b/scripts/dos-shell @@ -1,57 +1,128 @@ #!/bin/bash # /usr/local/bin/dos-shell -# 1) reset C: drive contents to only the allowed files -# 2) launch dosemu with /cdrive mounted as C: +# Prepare the SvarDOS environment and launch dosemu. set -euo pipefail ALLOWED_LIST="/etc/dos_allowed" -ALLOWED_REPO="/opt/allowed_repo" # repository of allowed DOS files stored in container -C_DRIVE="/cdrive" +ALLOWED_REPO="/opt/allowed_repo" ENV_DIR="/etc/dos_env" AUTOEXEC_TEMPLATE="${ENV_DIR}/AUTOEXEC.BAT" CONFIG_TEMPLATE="${ENV_DIR}/CONFIG.SYS" -SVARDOS_BASE="/opt/svardos/base" -ALLOW_MODE="${DOS_ALLOW_MODE:-all}" # default to exposing everything from the repo +SVARDOS_ROOT="${SVARDOS_ROOT:-/opt/svardos}" +SVARDOS_BASE="${SVARDOS_BASE:-${SVARDOS_ROOT}/base}" +ALLOW_MODE="${DOS_ALLOW_MODE:-all}" +DEFAULT_DOS_USER="dosuser" +INSTALL_SENTINEL=".svardos_installed" +if [ "$(id -u)" -eq 0 ]; then + DOS_USER="${DEFAULT_DOS_USER}" + DOS_HOME="$(getent passwd "${DOS_USER}" | cut -d: -f6)" +else + DOS_USER="$(id -un)" + DOS_HOME="${HOME}" +fi + +if [ -z "${DOS_HOME}" ]; then + echo "Unable to determine home directory for ${DOS_USER}" >&2 + exit 1 +fi + +DOSEMU_DIR="${DOS_HOME}/.dosemu" +C_DRIVE="${DOSEMU_DIR}/drive_c" +DOSEMURC_PATH="${DOS_HOME}/.dosemurc" +INSTALL_MARKER="${DOSEMU_DIR}/${INSTALL_SENTINEL}" +DOSEMU_ARGS=(-quiet -t -K "${C_DRIVE}") +allowed_entries=() + +mkdir -p "${DOSEMU_DIR}" "${C_DRIVE}" if [ "$(id -u)" -eq 0 ] && [ ! -d "${ENV_DIR}" ]; then mkdir -p "${ENV_DIR}" fi -# clear C: drive to ensure only allowed programs are present -rm -rf "${C_DRIVE:?}/"* -mkdir -p "${C_DRIVE}" +set_install_marker() { + touch "${INSTALL_MARKER}" + if [ "$(id -u)" -eq 0 ]; then + chown "${DOS_USER}:${DOS_USER}" "${INSTALL_MARKER}" + fi +} + +has_svardos_installation() { + if [ -f "${C_DRIVE}/KERNEL.SYS" ] || [ -f "${C_DRIVE}/kernel.sys" ]; then + return 0 + fi + if [ -f "${C_DRIVE}/BIN/PKG.EXE" ] || [ -f "${C_DRIVE}/bin/pkg.exe" ]; then + return 0 + fi + if [ -d "${C_DRIVE}/SVARDOS" ] || [ -d "${C_DRIVE}/svardos" ]; then + return 0 + fi + return 1 +} + +needs_install() { + if [ "${DOS_FORCE_INSTALL:-0}" = "1" ]; then + return 0 + fi + if [ -f "${INSTALL_MARKER}" ]; then + return 1 + fi + if has_svardos_installation; then + set_install_marker + return 1 + fi + return 0 +} + +stage_initial_install() { + if [ ! -d "${SVARDOS_BASE}" ] || [ -z "$(ls -A "${SVARDOS_BASE}")" ]; then + echo "SvarDOS base directory ${SVARDOS_BASE} is empty. Aborting." >&2 + exit 1 + fi + + rm -rf "${C_DRIVE:?}/"* -# Seed the C: drive with the SvarDOS base image -if [ -e "${SVARDOS_BASE}/COMMAND.COM" ] || [ -e "${SVARDOS_BASE}/command.com" ]; then cp -a "${SVARDOS_BASE}/." "${C_DRIVE}/" -else - echo "SvarDOS base not found in ${SVARDOS_BASE}. Aborting." >&2 - exit 1 -fi + set_install_marker + echo "SvarDOS base staged to ${C_DRIVE}" +} -# Sync additional DOS files into the C: drive -allowed_entries=() -case "${ALLOW_MODE}" in - all) - if [ -d "${ALLOWED_REPO}" ] && [ "$(ls -A "${ALLOWED_REPO}")" ]; then +generate_dosemurc() { + local boot_target="$1" + { + printf "%s\n" "\$_hdimage = \"${C_DRIVE}\"" + printf "%s\n" "\$_boot = \"${boot_target}\"" + printf "%s\n" "\$_emusys = \"drdos\"" + printf "%s\n" "\$_fdpp = (off)" + } > "${DOSEMURC_PATH}" + if [ -f "${ENV_DIR}/dosemurc" ]; then + cat "${ENV_DIR}/dosemurc" >> "${DOSEMURC_PATH}" + fi + if [ "$(id -u)" -eq 0 ]; then + chown "${DOS_USER}:${DOS_USER}" "${DOSEMURC_PATH}" + fi +} + +sync_allowed_content() { + allowed_entries=() + local mode="${ALLOW_MODE}" + if [ "${mode}" = "all" ]; then + if [ -d "${ALLOWED_REPO}" ] && [ "$(ls -A "${ALLOWED_REPO}" 2>/dev/null)" ]; then cp -a "${ALLOWED_REPO}/." "${C_DRIVE}/" + allowed_entries+=("ALL") fi - ;; - list|allowlist) - ;; - *) - echo "Unknown DOS_ALLOW_MODE '${ALLOW_MODE}', falling back to allowlist mode." >&2 - ALLOW_MODE="list" - ;; -esac + return + fi + + if [ "${mode}" != "list" ] && [ "${mode}" != "allowlist" ]; then + echo "Unknown DOS_ALLOW_MODE '${mode}', defaulting to allowlist mode." >&2 + mode="list" + ALLOW_MODE="${mode}" + fi -if [ "${ALLOW_MODE}" != "all" ]; then if [ -f "${ALLOWED_LIST}" ]; then while IFS= read -r line || [ -n "$line" ]; do - # trim whitespace line="$(printf '%s' "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - # skip blank/comment lines case "$line" in ''|\#*) continue ;; esac @@ -69,47 +140,41 @@ if [ "${ALLOW_MODE}" != "all" ]; then echo "Warning: allowed file not found: $src" >&2 fi done +} + +apply_templates() { + if [ -f "${AUTOEXEC_TEMPLATE}" ]; then + cp "${AUTOEXEC_TEMPLATE}" "${C_DRIVE}/AUTOEXEC.BAT" + fi + if [ -f "${CONFIG_TEMPLATE}" ]; then + cp "${CONFIG_TEMPLATE}" "${C_DRIVE}/CONFIG.SYS" + fi +} + +if needs_install; then + stage_initial_install fi -# Optional: create an AUTOEXEC.BAT and CONFIG.SYS or other DOS boot files -autoexec_path="${C_DRIVE}/AUTOEXEC.BAT" -config_path="${C_DRIVE}/CONFIG.SYS" +generate_dosemurc "c" -if [ -f "${AUTOEXEC_TEMPLATE}" ]; then - cp "${AUTOEXEC_TEMPLATE}" "${autoexec_path}" -else - cat > "${autoexec_path}" <<'EOF' -@echo off -prompt [DOS]$P$G -echo Welcome to the containerized DOS environment. -EOF -fi +sync_allowed_content +apply_templates -if [ "${ALLOW_MODE}" = "all" ]; then - printf 'echo All repository programs are currently enabled.\r\n' >> "${autoexec_path}" -elif [ ${#allowed_entries[@]} -gt 0 ]; then - { - printf 'echo Allowed programs:\r\n' - for entry in "${allowed_entries[@]}"; do - dos_entry="${entry//\//\\}" - printf 'echo %s\r\n' "${dos_entry}" - done - } >> "${autoexec_path}" -else - { - printf 'echo No extra programs are currently enabled.\r\n' - } >> "${autoexec_path}" -fi - -if [ -f "${CONFIG_TEMPLATE}" ]; then - cp "${CONFIG_TEMPLATE}" "${config_path}" -fi - -# Drop privileges to dosuser if we were run as root (ssh will run as the user) -# but in case sshd runs ForceCommand as root, we switch. if [ "$(id -u)" -eq 0 ]; then - exec runuser -u dosuser -- dosemu -quiet -K "${C_DRIVE}" -else - # running as the user already - exec dosemu -quiet -K "${C_DRIVE}" + chown -R "${DOS_USER}:${DOS_USER}" "${DOSEMU_DIR}" +fi + +if [ "${ALLOW_MODE}" = "all" ] && [ "${#allowed_entries[@]}" -gt 0 ]; then + echo "All files in ${ALLOWED_REPO} are available on drive C:." +elif [ "${#allowed_entries[@]}" -gt 0 ]; then + echo "Allowlisted files copied to C: from ${ALLOWED_REPO}:" + for entry in "${allowed_entries[@]}"; do + echo " ${entry}" + done +fi + +if [ "$(id -u)" -eq 0 ]; then + exec runuser -u "${DOS_USER}" -- dosemu "${DOSEMU_ARGS[@]}" +else + exec dosemu "${DOSEMU_ARGS[@]}" fi diff --git a/scripts/prepare-svardos.sh b/scripts/prepare-svardos.sh index 1b94b38..9521687 100644 --- a/scripts/prepare-svardos.sh +++ b/scripts/prepare-svardos.sh @@ -1,79 +1,39 @@ #!/bin/bash set -euo pipefail -SVARDOS_BASE_DIR="/opt/svardos/base" -SVARDOS_CACHE="/opt/svardos/cache" -SVARDOS_IMG="${SVARDOS_CACHE}/svardos.img" -DEFAULT_REL="download/20250427/svardos-20250427-floppy-1.44M.zip" -DEFAULT_BASE="http://svardos.org" +SVARDOS_ROOT="${SVARDOS_ROOT:-/opt/svardos}" +SVARDOS_BASE_DIR="${SVARDOS_BASE_DIR:-${SVARDOS_ROOT}/base}" +DEFAULT_URL="http://svardos.org/download/20250427/svardos-20250427-dosemu.zip" +ARCHIVE_URL="${SVARDOS_IMG_URL:-$DEFAULT_URL}" -if [ -z "${SVARDOS_IMG_URL:-}" ]; then - homepage="$( - curl -fsSL "${DEFAULT_BASE}/" 2>/dev/null || true - )" - discovered_rel="" - if [ -n "$homepage" ]; then - for pattern in 'download/[0-9]+/svardos-[0-9]+-floppy-1\.44M\.zip' 'download/[0-9]+/svardos-[0-9]+-usb\.zip'; do - candidate="$(printf '%s' "$homepage" | grep -Eo "$pattern" | head -n1)" - if [ -n "$candidate" ]; then - discovered_rel="$candidate" - break - fi - done - fi - if [ -n "$discovered_rel" ]; then - SVARDOS_IMG_URL="${DEFAULT_BASE}/${discovered_rel}" - else - SVARDOS_IMG_URL="${DEFAULT_BASE}/${DEFAULT_REL}" - fi -fi - -if [ -e "${SVARDOS_BASE_DIR}/COMMAND.COM" ] || [ -e "${SVARDOS_BASE_DIR}/command.com" ]; then +# Skip work if the base tree already exists (unless SVARDOS_REFRESH is set) +if [ -z "${SVARDOS_REFRESH:-}" ] && [ -e "${SVARDOS_BASE_DIR}/COMMAND.COM" ]; then exit 0 fi -mkdir -p "${SVARDOS_BASE_DIR}" "${SVARDOS_CACHE}" - -tmp_archive="${SVARDOS_CACHE}/svardos_download" -rm -f "${tmp_archive}" "${SVARDOS_IMG}" - -echo "Fetching SvarDOS base from ${SVARDOS_IMG_URL}" -curl -fsSL "${SVARDOS_IMG_URL}" -o "${tmp_archive}" - -mime_type="$(file -b --mime-type "${tmp_archive}")" -case "${mime_type}" in - application/zip) - unzip -o "${tmp_archive}" -d "${SVARDOS_CACHE}" >/dev/null - ;; - application/x-bzip2|application/x-gzip|application/x-xz) - tar -xf "${tmp_archive}" -C "${SVARDOS_CACHE}" - ;; - application/octet-stream) - # assume this is already a raw image - cp "${tmp_archive}" "${SVARDOS_IMG}" - ;; - *) - echo "Unsupported SvarDOS payload type: ${mime_type}" >&2 - exit 1 - ;; -esac - -if [ ! -f "${SVARDOS_IMG}" ]; then - # try to locate the image file - candidate="$(find "${SVARDOS_CACHE}" -maxdepth 1 -type f \( -iname '*svardos*.img' -o -iname '*.ima' -o -iname '*.img' \) | head -n1)" - if [ -z "${candidate}" ]; then - echo "Could not locate a SvarDOS disk image after extraction." >&2 - exit 1 - fi - mv "${candidate}" "${SVARDOS_IMG}" -fi - -rm -rf "${SVARDOS_BASE_DIR}"/* mkdir -p "${SVARDOS_BASE_DIR}" -# Copy contents of FAT image into the base directory -mcopy -s -i "${SVARDOS_IMG}" ::* "${SVARDOS_BASE_DIR}/" +tmpdir="$(mktemp -d)" +cleanup() { + rm -rf "${tmpdir}" +} +trap cleanup EXIT + +archive_path="${tmpdir}/svardos.zip" +unpack_dir="${tmpdir}/unpacked" + +echo "Fetching SvarDOS base from ${ARCHIVE_URL}" +curl -fsSL "${ARCHIVE_URL}" -o "${archive_path}" + +unzip -q "${archive_path}" -d "${unpack_dir}" + +# Some archives might unpack into a single top-level directory; flatten it if so. +if [ "$(find "${unpack_dir}" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && \ + [ "$(find "${unpack_dir}" -mindepth 1 -maxdepth 1 | wc -l)" -eq 1 ]; then + unpack_dir="$(find "${unpack_dir}" -mindepth 1 -maxdepth 1 -type d)" +fi + +rm -rf "${SVARDOS_BASE_DIR:?}/"* +cp -a "${unpack_dir}/." "${SVARDOS_BASE_DIR}/" -rm -f "${SVARDOS_IMG}" "${tmp_archive}" -rm -rf "${SVARDOS_CACHE}" echo "SvarDOS base copied to ${SVARDOS_BASE_DIR}"