#!/bin/sh
# DaemonTamer: simple and portable local service manager in pure sh
# that allows to quickly daemonize any command and manage it as a service
# Depends on POSIX versions of sh, nohup, cut and grep
# the unreg option also depends on mktemp (not POSIX but present everywhere)
# Run sh dt help to see the parameters
# Created by Luxferre in 2025, released into public domain with no warranties

err() {
  echo $*
  exit 1
}

msgexit() {
  echo $*
  exit 0
}

find_service() {
  sline="$(grep -E "^$1\s+" $CONF)"
  [ -z "$sline" ] && err "No such service found in the config!"
  echo "$sline"
}

CONF="$HOME/.dt.conf"
TMPDIR="$(dirname $(mktemp -u))"
srv_name="$2"
[ "$1" != "help" ] && [ -z "$srv_name" ] && err "Service name is required!"
pidfile="$TMPDIR/$srv_name.pid"
case $1 in
help)
  echo 'DaemonTamer v2'
  echo '--------------'
  echo "Usage: $0 {reg|unreg|start|stop|restart} SERVICE_NAME [REG_PARAMS]"
  echo 'Parameters for the reg subcommand:'
  echo "$0 reg 'COMMAND' [WORKDIR] [STDOUT_LOG_FILE] [STDERR_LOG_FILE] [PRESTART] [POSTSTART] [PRESTOP] [POSTSTOP]"
  echo '(the COMMAND must be specified in single quotes and without nohup)'
  echo
  echo 'Created by Luxferre in 2025, released into public domain with no warranties'
  ;;
reg)
  srv_cmd="$3"
  [ -z "$srv_cmd" ] && err "Service runner command is required!"
  srv_wdir="$4"
  srv_outlog="$5"
  srv_errlog="$6"
  srv_prestart="$7"
  srv_poststart="$8"
  srv_prestop="$9"
  srv_poststop="$10"
  [ -z "$srv_wdir" ] && srv_wdir='-'
  [ -z "$srv_outlog" ] && srv_outlog='/dev/null'
  [ -z "$srv_errlog" ] && srv_errlog='/dev/null'
  [ -z "$srv_prestart" ] && srv_prestart='-'
  [ -z "$srv_poststart" ] && srv_poststart='-'
  [ -z "$srv_prestop" ] && srv_prestop='-'
  [ -z "$srv_poststop" ] && srv_poststop='-'
  printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$srv_name" "$srv_cmd" \
    "$srv_wdir" "$srv_outlog" "$srv_errlog" "$srv_prestart" "$srv_poststart" \
    "$srv_prestop" "$srv_poststop" >> $CONF
  echo "Service $srv_name registered"
  ;;
unreg)
  srvline="$(find_service "$srv_name")"
  TCONF="$(mktemp)"
  grep -v "$srv_name" $CONF > $TCONF && mv $TCONF $CONF
  echo "Service $srv_name unregistered"
  ;;
start)
  [ -f "$pidfile" ] && msgexit "Service $srv is already running";
  srvline="$(find_service "$srv_name")"
  srv_cmd="$(echo "$srvline" | cut -f2)"
  srv_wdir="$(echo "$srvline" | cut -f3)"
  srv_outlog="$(echo "$srvline" | cut -f4)"
  srv_errlog="$(echo "$srvline" | cut -f5)"
  srv_prestart="$(echo "$srvline" | cut -f6)"
  srv_poststart="$(echo "$srvline" | cut -f7)"
  echo "Starting service $srv_name"
  [ "$srv_wdir" != "-" ] && cd "$srv_wdir"
  [ "$srv_prestart" != "-" ] && $SHELL -c "$srv_prestart"
  nohup $srv_cmd >$srv_outlog 2>$srv_errlog & echo $! > $pidfile
  [ "$srv_poststart" != "-" ] && $SHELL -c "$srv_poststart"
  echo "Service $srv_name started"
  ;;
stop)
  [ ! -f "$pidfile" ] && msgexit "Service $srv is not running";
  srvline="$(find_service "$srv_name")"
  srv_prestop="$(echo "$srvline" | cut -f8)"
  srv_poststop="$(echo "$srvline" | cut -f9)"
  echo "Stopping service $srv_name"
  [ "$srv_prestop" != "-" ] && $SHELL -c "$srv_prestop"
  kill $(cat $pidfile)
  rm -f $pidfile
  [ "$srv_poststop" != "-" ] && $SHELL -c "$srv_poststop"
  echo "Service $srv_name stopped"
  ;;
restart)
  srvline="$(find_service "$srv_name")"
  $SHELL $0 stop $srv_name
  $SHELL $0 start $srv_name
  ;;
*)
  echo 'Invalid operation! Pick start, stop, restart, reg, unreg or help'
  ;;
esac

