#!/bin/sh -e

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

dbx="s6-rc-db -c /usr/lib/s6-rc/compiled-work"
. /usr/lib/s6-policy-common/lib/svctl-common.sh

# Source bundles (anchors, role bundles) go into the start set as a REFERENCE
# (1.3.0): top/contents.d/<bundle>, not its current members. Members that
# join the bundle later are then in the start set after the next compile,
# without another enable -- the building block for roles. Everything else
# (units, policy bundles) is handled as before, resolved to atomics.
# A source bundle need not be in compiled-work yet (a role bundle written
# right before the enable), so it is taken out of the unknown-service check.
refs=""
rest=""
for _a in "$@" ; do
  if svctl_is_source_bundle "$_a" ; then
    refs="$refs $_a"
  else
    rest="$rest $_a"
  fi
done
set -- $rest

# Unknown services are an ERROR, not a no-op.
#
# Without this check the script ran through: the command substitutions below
# sit in an "if" and in a "for", where "set -e" does not apply -- s6-rc-db
# printed its "not a valid identifier" to stderr, the loop ran zero times, and
# the script ended with exit 0. Puppet would have taken an enable/disable that
# hit nothing for a success (finding 2026-09-22).
if [ $# -gt 0 ] && ! $dbx atomics "$@" >/dev/null 2>&1 ; then
  echo "svctl-disable: unknown service: $*" 1>&2
  exit 3
fi

policy=$(readlink /usr/lib/s6-rc/policy/current)
if test x"$policy" = x"exclusive" ; then
  isexclusive=true
elif test x"$policy" = x"shared" ; then
  isexclusive=false
else
  echo "svctl-disable: fatal: /usr/lib/s6-rc/policy/current should be a relative symlink to either shared or exclusive" 1>&2
  exit 100
fi

needcompile=false
for b in $refs ; do
  for d in $(svctl_start_set_dirs) ; do
    rm -f "$d/$b"
  done
  needcompile=true
done
[ $# -gt 0 ] || set -- ""
for i in $([ -n "$1" ] && $dbx atomics "$@") ; do
  if test -d "/usr/lib/s6-rc/sources/$i" ; then
    if $isexclusive ; then
      rm -f "/usr/lib/s6-rc/policy/exclusive/top/contents.d/$i"
    else
      for j in 2 3 4 5 ; do
        rm -f "/usr/lib/s6-rc/policy/shared/runlevel_$j/contents.d/$i"
      done
    fi
    needcompile=true
  else
    echo "svctl-disable: warning: service $i not found in /usr/lib/s6-rc/sources"
  fi
done

# 1.3.0: a unit can also be in the start set through a bundle reference
# (anchor or role bundle in top). Removing its own entry does not change that;
# say so instead of pretending.
for i in $([ -n "$1" ] && $dbx atomics "$@" 2>/dev/null) ; do
  for d in $(svctl_start_set_dirs) ; do
    for r in $(ls -A "$d" 2>/dev/null) ; do
      svctl_is_source_bundle "$r" || continue
      if $dbx atomics "$r" 2>/dev/null | grep -qFx "$i" ; then
        echo "svctl-disable: WARNING: $i stays in the start set through bundle $r ($d/$r)" 1>&2
      fi
    done
    break
  done
done

# E6: say out loud what disable did NOT do.
#
# disable removes a unit from the start set. It does not lower the running
# wish, and that is right -- the separation of "start set" and "running state"
# IS the rule "packages yes, services off". But it must not be silent.
#
# Measured on infra-1 on 24.09.2026: "svctl isenabled" rc 1 AND "svctl
# iswanted" rc 0 at the same time -- disabled and still wanted. s6 kept
# restarting svc-ctrl 54-57 times a minute while every display said
# "disabled". Whoever calls disable and expects a quiet machine afterwards must
# learn here that a step is missing.
_stillactive=""
for i in $([ -n "$1" ] && $dbx atomics "$@" 2>/dev/null) $(for _r in $refs ; do $dbx atomics "$_r" 2>/dev/null ; done) ; do
  if s6-rc -a list 2>/dev/null | grep -qFx "$i" ; then
    _stillactive="$_stillactive $i"
  fi
done
if test -n "$_stillactive" ; then
  echo "svctl-disable: WARNING: removed from the start set, but s6-rc still lists as active:" 1>&2
  for i in $_stillactive ; do
    echo "svctl-disable: WARNING   $i" 1>&2
  done
  echo "svctl-disable: WARNING These services keep running and are restarted after a" 1>&2
  echo "svctl-disable: WARNING crash. disable deliberately does NOT lower the running" 1>&2
  echo "svctl-disable: WARNING wish -- to stop them:  svctl stop$_stillactive" 1>&2
fi

if $needcompile ; then
  exec /usr/lib/s6-policy-common/bin/svctl-compile
fi
