#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" INSTALL_DIR="${INSTALL_DIR:-$ROOT_DIR/.local/dcmtk-bin}" REQUIRED_BINS=(storescp movescu storescu findscu dcmdump dcmodify getscu echoscu dcmj2pnm) SOURCE_DIR="" ARCHIVE_URL="" TMP_DIR="" usage() { cat <<'EOF' Usage: scripts/setup-dcmtk.sh [--source-dir DIR | --archive-url URL] [--install-dir DIR] Behavior: - Copies required DCMTK binaries into a local ignored directory. - If --source-dir is omitted, binaries are resolved from PATH. - If --archive-url is given, the script downloads and extracts an archive, then searches for the required binaries inside it. Examples: scripts/setup-dcmtk.sh --source-dir /opt/dcmtk/bin scripts/setup-dcmtk.sh --archive-url https://github.com///releases/download//dcmtk-bin.tar.gz scripts/setup-dcmtk.sh --install-dir /data/dcmtk-bin EOF } download() { local url="$1" local out="$2" if command -v curl >/dev/null 2>&1; then curl -fL "$url" -o "$out" elif command -v wget >/dev/null 2>&1; then wget -O "$out" "$url" else echo "need curl or wget to download $url" >&2 exit 1 fi } extract_archive() { local archive="$1" local dest="$2" case "$archive" in *.tar.gz|*.tgz) tar -xzf "$archive" -C "$dest" ;; *.tar.xz) tar -xJf "$archive" -C "$dest" ;; *.tar) tar -xf "$archive" -C "$dest" ;; *.zip) command -v unzip >/dev/null 2>&1 || { echo "unzip is required for $archive" >&2; exit 1; } unzip -q "$archive" -d "$dest" ;; *) echo "unsupported archive format: $archive" >&2 exit 1 ;; esac } while [[ $# -gt 0 ]]; do case "$1" in --source-dir) SOURCE_DIR="${2:?missing value for --source-dir}" shift 2 ;; --archive-url) ARCHIVE_URL="${2:?missing value for --archive-url}" shift 2 ;; --install-dir) INSTALL_DIR="${2:?missing value for --install-dir}" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "Unknown argument: $1" >&2 usage >&2 exit 1 ;; esac done if [[ -n "$SOURCE_DIR" && -n "$ARCHIVE_URL" ]]; then echo "use only one of --source-dir or --archive-url" >&2 exit 1 fi cleanup() { [[ -n "$TMP_DIR" && -d "$TMP_DIR" ]] && rm -rf "$TMP_DIR" } trap cleanup EXIT if [[ -n "$ARCHIVE_URL" ]]; then TMP_DIR="$(mktemp -d)" archive_name="$(basename "${ARCHIVE_URL%%\?*}")" [[ -n "$archive_name" && "$archive_name" != "/" ]] || archive_name="archive.tar.gz" archive="$TMP_DIR/$archive_name" download "$ARCHIVE_URL" "$archive" mkdir -p "$TMP_DIR/extracted" extract_archive "$archive" "$TMP_DIR/extracted" SOURCE_DIR="$TMP_DIR/extracted" fi mkdir -p "$INSTALL_DIR" resolve_bin() { local name="$1" if [[ -n "$SOURCE_DIR" ]]; then local candidate candidate="$(find "$SOURCE_DIR" -type f -name "$name" -perm -u+x | head -n 1 || true)" [[ -n "$candidate" ]] || candidate="$(find "$SOURCE_DIR" -type f -name "$name" | head -n 1 || true)" [[ -n "$candidate" ]] || { echo "missing binary in source: $name" >&2; return 1; } printf '%s\n' "$candidate" return 0 fi command -v "$name" >/dev/null 2>&1 || { echo "binary not found in PATH: $name" >&2; return 1; } command -v "$name" } for bin in "${REQUIRED_BINS[@]}"; do src="$(resolve_bin "$bin")" install -m 0755 "$src" "$INSTALL_DIR/$bin" echo "installed $bin -> $INSTALL_DIR/$bin" done cat <