#!/bin/sh -e

. /usr/lib/s6-policy-common/lib/svctl-common.sh

if test -z "$1" ; then
  echo "svctl-isup: usage: svctl-isup service" 1>&2
  exit 100
fi

if ! test -L /run/s6-rc/compiled ; then
  echo "svctl-isup: fatal: s6-rc is not running" 1>&2
  exit 2
fi

# Warum hier zweimal gefragt wird:
#
# Bis 1.0.9 antwortete "svctl isup" allein aus "s6-rc -a list". Das ist die
# Liste der Dienste, die s6-rc fuer aktiv HAELT -- also das Ergebnis der letzten
# Transition, nicht der Zustand des Prozesses. Bei einem Longrun, der nach dem
# Start stirbt, bleibt er dort stehen: auf dns-1 meldete "svctl isup pdns"
# "service pdns is running", waehrend "s6-svstat" "down (exitcode 1)" sagte und
# ueberhaupt kein pdns_server-Prozess existierte (Deploy, 23.09.2026).
#
# Fuer ein Pruefwerkzeug ist das schlimmer als ein Fehler: es sagt nicht etwas
# Unvollstaendiges, sondern das Gegenteil. Deshalb zaehlt fuer einen LONGRUN
# zusaetzlich, was der Supervisor sagt. Fuer einen ONESHOT bleibt "s6-rc -a
# list" die einzige Wahrheit -- er hat keinen Prozess, den man befragen koennte.
#
# Die Rueckgabewerte bleiben, damit Aufrufer nicht brechen: 0 laeuft, 3 laeuft
# nicht, 4 unbekannt. Neu ist 5 fuer NICHT MESSBAR -- fail-open: ein Zustand,
# den wir nicht erheben konnten, darf nicht als "laeuft" durchgehen.
# Die menschliche svstat-Zeile eines Longruns: "up (pid 8879) 200 seconds,
# ready 199 seconds" bzw. "down (exitcode 1) 0 seconds, normally up, want up".
# Sie enthaelt die Sekunden, und genau die entscheiden, ob ein Dienst laeuft
# oder gerade zum siebten Mal gestartet wurde.
_isup_line() {
  _d="/run/s6-rc/servicedirs/$1"
  if [ -d "$_d" ]; then
    s6-svstat "$_d" 2>/dev/null || echo 'nicht messbar'
  else
    echo 'oneshot (kein Supervisor, kein Prozess)'
  fi
}

_isup_one() {
  _s="$1"
  if ! svctl_is_active "$_s"; then
    return 3
  fi
  _t=$(s6-rc-db type "$_s" 2>/dev/null || echo unbekannt)
  if [ "$_t" != longrun ]; then
    return 0
  fi
  _dir="/run/s6-rc/servicedirs/$_s"
  if ! [ -d "$_dir" ]; then
    return 0
  fi
  _up=$(s6-svstat -o up "$_dir" 2>/dev/null) || return 5
  case "$_up" in
    true) return 0 ;;
    false) return 3 ;;
    *) return 5 ;;
  esac
}

if ! svctl_load_active; then
  svctl_report_unmeasurable
  exit 5
fi

if s6-rc-db list services | grep -qFx "$1" ; then
  rc=0
  _isup_one "$1" || rc=$?
  case "$rc" in
    0)
      # Mit Zustandszeile, damit "laeuft" pruefbar ist und nicht geglaubt werden
      # muss: Sekunden und ready stehen dabei.
      echo "service $1 is running: $(_isup_line "$1")"
      exit 0
      ;;
    3)
      if svctl_is_active "$1"; then
        # Der Fall, um den es geht: s6-rc fuehrt ihn als aktiv, der Prozess
        # laeuft nicht. Die svstat-Zeile steht dabei, weil sie die Diagnose ist.
        echo "service $1 is NOT running, although s6-rc considers it active: $(_isup_line "$1")"
      else
        echo "service $1 is stopped"
      fi
      exit 3
      ;;
    *)
      echo "service $1 is NOT MEASURABLE: s6-svstat gave no answer for /run/s6-rc/servicedirs/$1" 1>&2
      exit 5
      ;;
  esac
elif s6-rc-db list bundles | grep -qFx "$1" ; then
  # Ein Bundle ist oben, wenn jede direkt enthaltene Einheit oben ist. Die
  # Schleife lief bis 1.0.9 in einer Subshell -- ihr "exit 3" verliess nur die
  # Pipeline, nicht das Skript, und danach meldete es "bundle ... is running".
  rc=0
  for service in $(s6-rc-db contents "$1"); do
    _rc=0
    _isup_one "$service" || _rc=$?
    case "$_rc" in
      0) ;;
      3) echo "service $service in bundle $1 is not running: $(_isup_line "$service")"; rc=3 ;;
      *) echo "service $service in bundle $1 is NOT MEASURABLE" 1>&2; [ "$rc" = 3 ] || rc=5 ;;
    esac
  done
  if [ "$rc" = 0 ]; then
    echo "bundle $1 is running"
  fi
  exit "$rc"
else
  echo "svctl-isup: unknown atomic service: $1" 1>&2
  exit 4
fi
