#!/bin/sh
# synopkgland: the SDK steps run in synopkgland_sdk; the App's dsm-scripts/start-stop-status runs from scripts/app/start-stop-status.
synopkgland_sdk() (
stop_background_worker() {
  /usr/syno/bin/synosystemctl stop pkguser-SynoPkgGopeed-background.service && return 0
  # DSM's native uninstall stops the unit, then releases the package user's
  # systemd manager before preuninst, so a repeated stop fails. That is only
  # "already stopped" when no process runs the worker executable.
  [ -d /proc/self ] || return 1
  worker="$(readlink -f "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}/background/worker")" || return 1
  for exe in /proc/[0-9]*/exe; do
    case "$(readlink "$exe" 2>/dev/null)" in
      "$worker"|"$worker (deleted)") echo "background worker still running" >&2; return 1 ;;
    esac
  done
  echo "background worker already stopped" >&2
}
recover_user_manager() {
  uid="$(id -u)" || return 1
  [ "$uid" != 0 ] || return 0
  i=0
  while [ "$(/usr/bin/loginctl show-user "$uid" -p State 2>/dev/null)" = State=closing ] && [ "$i" -lt 100 ]; do
    sleep 0.1; i=$((i + 1))
  done
  [ -S "/run/user/$uid/systemd/private" ] && return 0
  for exe in /proc/[0-9]*/exe; do
    pid="${exe%/exe}"; pid="${pid##*/}"
    [ -O "/proc/$pid" ] && [ "$(readlink "$exe" 2>/dev/null)" = /usr/lib/systemd/systemd ] || continue
    case " $(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)" in *" --user "*) ;; *) continue ;; esac
    echo "package user manager $pid has no socket in /run/user/$uid; stopping it so DSM starts a fresh one" >&2
    kill -TERM "$pid" || return 1
    i=0
    # DSM's bash logs a failed kill to syslog even with 2>/dev/null, so the
    # exit is looked up in /proc.
    while [ -d "/proc/$pid" ]; do
      [ "$i" -lt 100 ] || { echo "package user manager $pid did not exit" >&2; return 1; }
      sleep 0.1; i=$((i + 1))
    done
  done
}
start_background_worker() {
  /usr/syno/bin/synosystemctl start pkguser-SynoPkgGopeed-background.service && return 0
  rc=$?; socket=missing
  [ -S "/run/user/$(id -u)/systemd/private" ] && socket=present
  echo "background worker pkguser-SynoPkgGopeed-background.service failed to start (exit $rc; package user manager socket $socket)" >&2
  return "$rc"
}
case "$1" in
  prestart) recover_user_manager ;;
  prestop) exit 0 ;;
  start)
    "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}/executor/lifecycle" start --package SynoPkgGopeed || exit $?
    if ! "/var/packages/SynoPkgGopeed/target/daemon/control" start "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}" "${SYNOPKG_PKGVAR:-/var/packages/SynoPkgGopeed/var}"; then
      "/var/packages/SynoPkgGopeed/target/daemon/control" stop "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}" "${SYNOPKG_PKGVAR:-/var/packages/SynoPkgGopeed/var}"
      "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}/executor/lifecycle" stop --package SynoPkgGopeed
      exit 1
    fi
    if ! start_background_worker; then
      /usr/syno/bin/synosystemctl stop pkguser-SynoPkgGopeed-background.service
      "/var/packages/SynoPkgGopeed/target/daemon/control" stop "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}" "${SYNOPKG_PKGVAR:-/var/packages/SynoPkgGopeed/var}"
      "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}/executor/lifecycle" stop --package SynoPkgGopeed
      exit 1
    fi
    exit 0 ;;
  status)
    "/var/packages/SynoPkgGopeed/target/daemon/control" status "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}" "${SYNOPKG_PKGVAR:-/var/packages/SynoPkgGopeed/var}" || exit $?
    worker_state="$(/usr/syno/bin/synosystemctl get-active-status pkguser-SynoPkgGopeed-background.service)" || exit 3
    [ "$worker_state" = active ] && exit 0
    exit 3 ;;
  stop)
result=0
stop_background_worker || result=1
"/var/packages/SynoPkgGopeed/target/daemon/control" stop "${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}" "${SYNOPKG_PKGVAR:-/var/packages/SynoPkgGopeed/var}" || result=1
"${SYNOPKG_PKGDEST:-/var/packages/SynoPkgGopeed/target}/executor/lifecycle" stop --package SynoPkgGopeed || result=1
exit "$result"
    ;;
  restart)
    "$0" stop || exit $?
    exec "$0" start ;;
  *) exit 1 ;;
esac
)
synopkgland_app="$(dirname "$0")/app/start-stop-status"
case "$1" in
  start)
    synopkgland_sdk "$@" || exit $?
    "$synopkgland_app" "$@" && exit 0
    synopkgland_result=$?
    synopkgland_sdk stop
    exit "$synopkgland_result" ;;
  stop|prestop)
    synopkgland_result=0
    "$synopkgland_app" "$@" || synopkgland_result=$?
    synopkgland_sdk "$@" || exit $?
    exit "$synopkgland_result" ;;
  restart)
    "$0" stop || exit $?
    exec "$0" start ;;
  *)
    synopkgland_sdk "$@" || exit $?
    exec "$synopkgland_app" "$@" ;;
esac
