# common useful functions

w3m_safe() {
  url="$1"

  output=$(/opt/homebrew/bin/w3m "$url" -M -cols 400 -graph -dump 2>&1)

  if echo "$output" | grep -q "Can't load"; then
    return 2
  else
    echo "$output"
    return 0
  fi
}


# Returns:
#   0 = server reachable & remote command ran
#   1 = network/host-not-up-yet
#   2 = SSH auth failure (key needs passphrase / wrong key / agent locked) -> caller should abort
#   3 = host not found
is_server_up() {
    local host err st err_lc
    host=$1

    # return 3 if the host does not exist
    host "$host" 2>&1 > /dev/null || return 3

    # Capture only stderr; do NOT use -q (it suppresses diagnostics we need to classify).
    # Force English messages for stable matching.
    err=$(LC_ALL=C /usr/bin/ssh \
        -o BatchMode=yes \
        -o PreferredAuthentications=publickey \
        -o PubkeyAuthentication=yes \
        -o PasswordAuthentication=no \
        -o KbdInteractiveAuthentication=no \
        -o NumberOfPasswordPrompts=0 \
        -o ConnectTimeout=10 \
        -o ServerAliveInterval=20 \
        -o ServerAliveCountMax=3 \
        -o ConnectionAttempts=1 \
        -o StrictHostKeyChecking=no \
        -o UserKnownHostsFile=/dev/null \
        -o LogLevel=ERROR \
        -n "$host" 'uname -n || hostname' 2>&1 >/dev/null)
    st=$?

    # Success
    [ $st -eq 0 ] && return 0

    # ssh uses 255 for any error; distinguish by stderr text
    err_lc=$(printf '%s' "$err" | tr '[:upper:]' '[:lower:]')

    case $err_lc in
        # Common auth/passphrase/agent problems
        *"permission denied"*|\
        *"no supported authentication methods available"*|\
        *"publickey authentication failed"*|\
        *"too many authentication failures"*|\
        *"sign_and_send_pubkey: signing failed"*|\
        *"agent refused operation"*|\
        *"agent admitted failure"*|\
        *"bad permissions"*|\
        *"enter passphrase"*)
            printf 'FATAL: SSH authentication failed for "%s": %s\n' "$host" "$err" >&2
            return 2
            ;;
    esac

    # Everything else looks like "not up yet" (timeout, DNS, connection refused/reset, kex read, etc.)
    return 1
}

wait_for_server_to_boot_up() {
    local server rc
    server=$1
    while :; do
        is_server_up "$server"
        rc=$?
        case $rc in
            0)
                printf '"%s" is up and running.\n' "$server"
                return 0
                ;;
            2)
                printf 'Aborting: SSH authentication failed for "%s" (key needs passphrase / wrong key / agent locked).\n' "$server" >&2
                return 2
                ;;
            3)
                printf 'Aborting: Host not found.\n' "$server" >&2
                return 3
                ;;
            *)
                printf 'Server "%s" is not up\n' "$server"
                sleep 10
                ;;
        esac
    done
}

# vim: set ts=4 sw=4 tw=0 noet ft=sh:
