#!/bin/sh
# Minimal foreground supervisor for init systems without native Restart=.

set -u

restart=on-failure
delay=5
workdir=/
logfile=""

usage() {
    echo "usage: $0 [--restart always|on-failure|never] [--delay SEC] [--chdir DIR] [--log FILE] -- command [args...]" >&2
    exit 64
}

while [ "$#" -gt 0 ]; do
    case "$1" in
        --restart)
            [ "$#" -ge 2 ] || usage
            restart=$2
            shift 2
            ;;
        --delay)
            [ "$#" -ge 2 ] || usage
            delay=$2
            shift 2
            ;;
        --chdir)
            [ "$#" -ge 2 ] || usage
            workdir=$2
            shift 2
            ;;
        --log)
            [ "$#" -ge 2 ] || usage
            logfile=$2
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *) usage ;;
    esac
done

[ "$#" -gt 0 ] || usage
case "$restart" in always|on-failure|never) ;; *) usage ;; esac
case "$delay" in ""|*[!0-9]*) usage ;; esac
[ -d "$workdir" ] || mkdir -p "$workdir" 2>/dev/null || exit 73
if [ -n "$logfile" ]; then
    logdir=$(dirname "$logfile")
    [ -d "$logdir" ] || mkdir -p "$logdir" 2>/dev/null || exit 73
fi

stopping=0
child=""

forward_term() {
    stopping=1
    if [ -n "$child" ]; then
        target=$child
        kill -TERM "$target" 2>/dev/null || true
        count=0
        while kill -0 "$target" 2>/dev/null && [ "$count" -lt 30 ]; do
            sleep 0.1
            count=$((count + 1))
        done
        kill -KILL "$target" 2>/dev/null || true
    fi
}

forward_hup() {
    if [ -n "$child" ]; then
        kill -HUP "$child" 2>/dev/null || true
    fi
}

trap forward_term INT TERM
trap forward_hup HUP

while [ "$stopping" -eq 0 ]; do
    (
        cd "$workdir" || exit 73
        if [ -n "$logfile" ]; then
            exec "$@" >>"$logfile" 2>&1
        fi
        exec "$@"
    ) &
    child=$!

    wait "$child"
    status=$?
    child=""

    [ "$stopping" -eq 0 ] || exit 0

    case "$restart" in
        never) exit "$status" ;;
        on-failure)
            [ "$status" -ne 0 ] || exit 0
            ;;
        always) ;;
    esac

    [ "$delay" -eq 0 ] || {
        sleep "$delay" &
        child=$!
        wait "$child" 2>/dev/null || true
        child=""
    }
done

exit 0
