#!/usr/bin/env bash

set -ueo pipefail

# Callers can test for support via "with-tty true".

usage() { echo 'Usage: with-tty command [arg ...]'; }
misuse() { usage 1>&2; exit 2; }

case "$OSTYPE" in
    netbsd) exit 2 ;; # https://gnats.netbsd.org/56254
esac

# script(1), originating in 3.0BSD, is not specified by POSIX and has
# varying forms.

#   FreeBSD 15: script [-aeFfkqrw] [-t time] [file [command ...]]
#   FreeBSD 14: script [-aeFfkqr] [-t time] [file [command ...]]
#   FreeBSD 13: script [-aefkqr] [-F pipe] [-t time] [file [command ...]]
#   FreeBSD 12: script [-adfkpqr] [-F pipe] [-t time] [file [command ...]]
#   FreeBSD 11: script [-adfkpqr] [-F pipe] [-t time] [file [command ...]]
#   FreeBSD 10: script [-adfkpqr] [-t time] [file [command ...]]
#   FreeBSD 8: script [-akq] [-t time] [file [command ...]]
#   FreeBSD 3.0: script [-a] [-k] [-q] [-t time] [file] [command ...]
#   FreeBSD 1.0: script [-a] [file]

#   Linux ?: script [options] [file] [-- command [argument...]]
#     but also "-c, --command command", and -eq

#   macos ?: script [-aeFkqr] [-t time] [file [command ...]]

#   NetBSD 10: script [-adefpqr] [-c command] [file]
#   NetBSD 6-9: script [-adfpqr] [-c command] [file]
#   NetBSD 5: script [-adpr] [file]

# Try variants; insist on exit with child status/ (-e behavior).

if script -qec true /dev/null; then
    script -qec "$(printf ' %q' "$@")" /dev/null
elif script -q -c true /dev/null; then
    if script -q -c false /dev/null; then # -e behavior?
        printf '%q ignores child exit status\n' "$(command -v script)" 1>&2
        exit 2
    fi
    script -q -c "$(printf ' %q' "$@")" /dev/null
elif script -q /dev/null true; then
    if script -q /dev/null false; then # -e behavior?
        printf '%q ignores child exit status\n' "$(command -v script)" 1>&2
        exit 2
    fi
    script -q /dev/null "$@"
else
    rc=0
    cmd="$(command -v script)" || rc=$?
    if test "$rc" -eq 0; then
        printf 'Unsupported script command: %q\n' "$cmd" 1>&2
    else
        echo 'No script command' 1>&2
    fi
    exit 2
fi

case "$OSTYPE" in
    netbsd)
        # On NetBSD, the top-level script(1) process exits when read()
        # reports EOF on stdin; this happens when running tests with
        # /dev/null as stdin.  As a workaround, wait after script, so
        # that the command will have finished.
        sleep 5
        ;;
esac
