#!/bin/sh -e

if test -z "$1" ; then
  echo "svctl-enable: usage: svctl-enable 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-enable: 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-enable: fatal: /usr/lib/s6-rc/policy/current should be a relative symlink to either shared or exclusive" 1>&2
  exit 100
fi

tmp=$(mktemp /tmp/svctl-enable.XXXXXX)
cleanup () {
  rm -f "$tmp"
}
trap cleanup EXIT TERM INT HUP QUIT ABRT

ls -1 /usr/lib/s6-rc/masked > "$tmp"
_known_refs=""
for _r in $refs ; do
  $dbx type "$_r" >/dev/null 2>&1 && _known_refs="$_known_refs $_r"
done
if [ -n "$*$_known_refs" ] && list=$($dbx all-dependencies "$@" $_known_refs | grep -Fx -f "$tmp") ; then
  {
    printf "svctl-enable: fatal: at least one of the listed services has a dependency on the following masked service: "
    echo "$list" | head -n 1
  } 1>&2
  exit 1
fi

cleanup
trap - EXIT TERM INT HUP QUIT ABRT

needcompile=false
for b in $refs ; do
  for d in $(svctl_start_set_dirs) ; do
    touch "$d/$b"
  done
  needcompile=true
  if ! ls -A "/usr/lib/s6-rc/sources/$b/contents.d" 2>/dev/null | grep -q . ; then
    echo "svctl-enable: note: bundle $b is empty for now; its members start once they exist (next compile/update)"
  fi
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
      touch "/usr/lib/s6-rc/policy/exclusive/top/contents.d/$i"
    else
      for j in 2 3 4 5 ; do
        touch "/usr/lib/s6-rc/policy/shared/runlevel_$j/contents.d/$i"
      done
    fi
    needcompile=true
  else
    echo "svctl-enable: warning: service $i not found in /usr/lib/s6-rc/sources"
  fi
done

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