#!/bin/sh
#
### BEGIN INIT INFO
# Provides:          avreg
# Required-Start:    $local_fs $network $remote_fs $syslog $time
# Required-Stop:     $local_fs $network $remote_fs $syslog
# Should-Start:      udev module-init-tools $named mysql postgresql
# Should-Stop:       $named mysql postgresql
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start and stop the avregd server
# Description:       The avregd is a main daemon of AVReg surveillance system.
### END INIT INFO

set -e
${DEBIAN_SCRIPT_DEBUG:+ set -v -x}

RET=0
PATH='/sbin:/bin:/usr/sbin:/usr/bin'
AVREGD='avregd'
AVREGD_BIN="/usr/sbin/$AVREGD"
PIDDIR='/run/avreg'
CONF='/etc/avreg/avreg.conf'
PROFILESDIR='/etc/avreg/profiles'
DESC="AVReg surveillance system server"
DOC='/usr/share/doc/avregd/README.gz'

SUPERD='avreg-supervisor'
SUPERD_BIN="/usr/sbin/$SUPERD"
SUPERD_PID="$PIDDIR/$SUPERD.pid"

AVREGD_DISABLED=No

SELF=${0##*/}

: "${NICE:=0}"

test -x $SUPERD_BIN || exit 0
test -x $AVREGD_BIN || exit 0


if [ ! "`id -u`" = 0 ]; then
   echo "WARNING: You are not the superuser root. You are assured that correctly do?" 1>&2
fi

STAT=$(which stat 2>/dev/null)
LOGGER=$(which logger 2>/dev/null)
if [ $? -eq 0 -a -n "$LOGGER" ]; then
   ERR_LOGGER="logger -p daemon.err -t /etc/init.d/$SELF -i"
else
   ERR_LOGGER='true'
fi

CMD="${1:-help}"
OPT=
PROFILES=
ABSENT_PROFILES=

if [ -r /etc/default/avreg ]; then
   . /etc/default/avreg
fi
. /lib/lsb/init-functions

case "x$AVREGD_DISABLED" in
   x[tT][rR][uU][eE]|x[yY][Ee][Ss]|x1)
      exit 0
      ;;
esac

if [ -d "$PROFILESDIR" -a -r "$PROFILESDIR" ]; then
   if [ -n "$2" ]; then
      shift
      OPT="$*"
   fi

   EXISTS_PROFILES=$(cd $PROFILESDIR 2>/dev/null && find -type f -regex '\./[A-Za-z0-9][A-Za-z0-9_\.:\-]+' -exec basename {} \; | sort)

   if [ -z "$OPT" ]; then
      PROFILES="$EXISTS_PROFILES"
   else
      for elem in $OPT; do
         if [ -r "${PROFILESDIR}/${elem}" ]; then
            if [ -z "$PROFILES" ]; then
               PROFILES="${elem}"
            else
               PROFILES="$PROFILES ${elem}"
            fi
         else
            if [ -z "$ABSENT_PROFILES" ]; then
               ABSENT_PROFILES="${elem}"
            else
               ABSENT_PROFILES="$ABSENT_PROFILES ${elem}"
            fi
         fi
      done
   fi
fi

# Safeguard (relative paths, core dumps..)
cd /
umask 077

if [ -n "$ABSENT_PROFILES" ]; then
   msg="ERROR: profiles config file(s)  [ $ABSENT_PROFILES ] not found in dir \`${PROFILESDIR}/'"
   log_failure_msg "$SELF: $msg"
   echo "$msg" | $ERR_LOGGER
   exit 6
fi

proc_get_live_pid() {
   local proc_title pid_file pid
   proc_title="$1"
   pid_file="$2"
   pid=

   if [ -r "$pid_file" ]; then
      pid=$(cat $pid_file 2>/dev/null)
   else
      pid=$(ps -C $AVREGD -o pid=,stat=,cmd= | \
         grep -v $0 | \
         sed -n 's/^\s*\([0-9]\+\)\s\+[SR][^ ]*\s*[0-9A-Za-z./_-]*'"$proc_title"'.*/\1/p' | \
         head -n 1)
   fi
   if [ $? -eq 0 -a -n "$pid" ]; then
      echo "$pid"
      return 0
   else
      # echo "$proc_title not running (R or S states)" >&2
      return 1
   fi
}

# start-stop-daemon uses the same algorithm as "pidofproc" above.
unset killproc || true
killproc () {
   local pidfile sig status base i name_param sig_term
   pidfile=
   name_param=
   sig_term=
   sig=

   OPTIND=1
   while getopts p: opt ; do
      case "$opt" in
         p)  pidfile="$OPTARG";;
      esac
   done
   shift $(($OPTIND - 1))

   base=${1##*/}
   if [ ! "$pidfile" ]; then
      pidfile="/run/$base.pid"
      name_param="--name $base"
   fi

   if [ -n "${2:-}" ]; then
      sig=$(echo ${2:-} | sed -e 's/^-\(.*\)/\1/')
      sig=$(echo $sig | sed -e 's/^SIG\(.*\)/\1/')
   fi

   if [ -z "$sig" -o "$sig" = 15 -o "$sig" = TERM ]; then
      sig_term='yes'
      /sbin/start-stop-daemon --stop --pidfile "$pidfile" --retry 5 --quiet --oknodo "$name_param"
   else
      /sbin/start-stop-daemon --stop --pidfile "$pidfile" --signal "$sig" --quiet "$name_param"
   fi

   # LSB 3.01
   status=$?
   case "$status" in
      0) [ $status -eq 0 -a "$sig_term" = yes ] && rm -f "$pidfile"
         return 0 ;;
      1) return 7 ;; # program is not running
      *) return $status
   esac
   return 0
}


_start() {
   local proc_title profile pid_file ret pid
   proc_title="$1"
   profile=${2:-}
   pid_file="${PIDDIR}/${proc_title}.pid"
   ret=0
   pid=$(proc_get_live_pid "$proc_title" "$pid_file" 2>/dev/null)
   if [ $? -eq 0 -a -n "$pid" ]; then
      echo -n "$proc_title[$pid] already running; "
      return 0
   fi

   if [ -z "$profile" ]; then
      start_daemon -n $NICE -p "$pid_file" -- $AVREGD_BIN ${AVREGD_ARGS:-} || ret=$?
   else
      start_daemon -n $NICE -p "$pid_file" -- $AVREGD_BIN --profile=$profile ${AVREGD_ARGS:-} || ret=$?
   fi

#   if [ $ret -eq 0  ]; then
#      sleep 1
#      pid=$(proc_get_live_pid "$proc_title" "$pid_file" 2>/dev/null)
#      ret=$?
#   fi

   if [ $ret -eq 0 ]; then #-a -n "$pid" ]; then
      echo -n "$proc_title[$pid] started; "
   else
      echo -n "$proc_title failed; "
   fi
   return $ret
}

_stop() {
   local proc_title pid_file ret
   proc_title="$1"
   pid_file="${PIDDIR}/${proc_title}.pid"
   ret=0
   killproc -p "$pid_file" $AVREGD || ret=$?
   if [ $ret -eq 0 ]; then
      echo -n "$proc_title stopped; "
   else
      echo -n "$proc_title failed; "
   fi
   return $ret
}

_reload() {
   local proc_title pid_file ret
   proc_title="$1"
   pid_file="${PIDDIR}/${proc_title}.pid"
   ret=0
   killproc -p "$pid_file" $AVREGD HUP || ret=$?
   if [ $ret -eq 0 ]; then
      echo -n "$proc_title ok; "
   else
      echo -n "$proc_title failed; "
   fi
   return $ret
}

_snapshot() {
   local proc_title pid_file ret
   proc_title="$1"
   pid_file="${PIDDIR}/${proc_title}.pid"
   ret=0
   killproc -p "$pid_file" $AVREGD USR1 || ret=$?
   if [ $ret -eq 0 ]; then
      echo -n "$proc_title ok; "
   else
      echo -n "$proc_title failed; "
   fi
   return $ret
}

_status() {
   local proc_title pid_file ret start_time
   proc_title="$1"
   pid_file="${PIDDIR}/${proc_title}.pid"
   pid=
   start_time=

   pid=$(proc_get_live_pid "$proc_title" "$pid_file" 2>/dev/null)

   if [ -n "$pid" ] && ps -p "$pid" >/dev/null 2>&1; then
      start_time=$(ps -p $pid -o start_time= 2>&1)
      echo -n "$proc_title[$pid] started at $start_time; "
      return 0
   fi

   if [ -e "$pid_file" ]; then
      echo -n "$proc_title stopped, but $pid_file exists; "
      return 1
   else
      echo -n "$proc_title stopped; "
      return 3
   fi
}

_proc() {
   local cmd profiles profile ret
   cmd="$1"
   profiles="$2"
   profile=
   ret=0
   if [ -z "$profiles" ]; then
      "$cmd" "$AVREGD"
      ret=$?
   else
      for profile in $profiles; do
         "$cmd" "${AVREGD}-${profile}" "$profile" || ret="$(($ret + $?))"
      done
   fi
   return $ret
}

case "$CMD" in
   'start')

      ## Do some sanity checks before even trying to start avregd.
      # check for config file
      if [ ! -r $CONF ]; then
         msg="ERROR: \`$CONF' cannot be read. See $DOC"
         log_failure_msg "$SELF: $msg"
         echo "$msg" | $ERR_LOGGER
         exit 6
      fi

      # check rights
      if [ -n "$STAT" ]; then
         if [ ! "$($STAT --format='%u %g %a' $CONF)" = '0 0 644' ]; then
            msg="WARNING: \`$CONF' must by have rights 0644 root:root. See $DOC"
            log_warning_msg "$SELF: $msg"
            echo "$msg" | $ERR_LOGGER
            chmod 0644 $CONF
            chown root:root $CONF
         fi
      fi

      storage_dir="$(update-avreg.conf print 'global' --param='storage-dir' -s)"
      user="$(update-avreg.conf print 'global' --param='user' -s)"
      group="$(update-avreg.conf print 'global' --param='group' -s)"
      [ -z "$storage_dir" ] && storage_dir='/var/spool/avreg'
      [ -z "$user" ]        && user='avreg'
      [ -z "$group" ]       && group='avreg'

      # if $storage_dir is mountpoint to XFS (couldn't set uid:gid in fstab)
      if [ -n "$storage_dir" ] && mountpoint -q "$storage_dir" ; then
         chmod ${SPOOL_CHMOD:-'0775' }        "$storage_dir"
         chown ${SPOOL_CHOWN:-"$user:$group"} "$storage_dir"
      fi

      # if /var/{run,lock,log}/avreg not exists - maybe mounted to tmpfs
      for dir in '/run' '/run/lock' '/var/log'; do
         if [ ! -e "$dir/avreg" ]; then
            mkdir -m 0775 "$dir/avreg"
            chown "root:$group" "$dir/avreg"
         fi
      done

      # start supervisor
      start_daemon -p "$SUPERD_PID" -- $SUPERD_BIN ${SUPERD_ARGS:-}

      log_daemon_msg "Starting $DESC" ' '
      _proc '_start' "$PROFILES" || RET=$?
      log_end_msg $RET
      if [ $RET -eq 0 ]; then
         log_success_msg "Please take a look at the syslog."
      else
         log_failure_msg "Please take a look at the syslog!"
      fi
      ;;

   'stop')
      log_daemon_msg "Stopping $DESC" ' '
      _proc '_stop' "$PROFILES" || RET=$?
      log_end_msg $RET
      if [ $RET -eq 0 ]; then
         killproc -p "$SUPERD_PID" $SUPERD || true
      else
         log_failure_msg " Please stop \`$AVREGD' manually and read $DOC!"
      fi
      ;;

   'restart')
      set +e
      /etc/init.d/$SELF stop $PROFILES
      set -e
      /etc/init.d/$SELF start $PROFILES
      ;;

   'reload'|'force-reload')
      log_daemon_msg "Reloading $DESC" ' '
      _proc '_reload' "$PROFILES" || RET=$?
      log_end_msg $RET
      ;;

   'snap'*)
      log_daemon_msg "Make snapshot jpegs $DESC" ' '
      _proc '_snapshot' "$PROFILES" || RET=$?
      log_end_msg $RET
      ;;

   'status')
      echo -n "Status of $DESC: "
      _proc '_status' "$PROFILES" || RET=$?
      echo
      ;;

   *)  cat >&2 << __EOF__
Usage: /etc/init.d/$SELF command [profile1 profile2 ... ]
where:
command in {start|stop|restart|reload|force-reload|status}
profiles - optional parameters, see additional conf files in \`${PROFILESDIR}' dir
__EOF__
      exit 3
      ;;
esac

exit $RET
