#!/bin/bash
# Copyright (c) since 2005, GECAD Technologies
# For any feedback, please contact:
# "AXIGEN Developement Team" <team@axigen.com>

# Init script for AXIGEN Filters
# Unified (and tested) *only* for the supported Linux distros.
# See http://www.axigen.com for a full list of supported Linux distros.
# Running on other Linux distros/versions should be possible, but is not
# officially supported.

# chkconfig:    345 80 20
# description:  AXIGEN Filters
# processname: axigenfilters

### BEGIN INIT INFO
# Provides:       axigenfilters
# Required-Start: $network $syslog $time
# Default-Start:  3 4 5
# Default-Stop:   0 1 2 6
# Description:    Starts/Stops AXIGEN Filters
### END INIT INFO

# Default variables
DAEMONS="axidkd axidksd aximilter spamd"

DAEMON_PATH_axidkd="/opt/axigen/bin/axidkd"
DAEMON_PATH_axidksd="/opt/axigen/bin/axidksd"
DAEMON_PATH_aximilter="/opt/axigen/bin/aximilter"
DAEMON_PATH_spamd="/opt/axigen/bin/spamd"

DAEMON_OPTIONS_axidkd=""
DAEMON_OPTIONS_axidksd=""
DAEMON_OPTIONS_aximilter=""
DAEMON_OPTIONS_spamd="-d"

DAEMON_PIDFILE_spamd="/var/opt/axigen/spamassassin/spamd.pid"

DAEMON_NAME_axidkd="AxigenDK Verifier"
DAEMON_NAME_axidksd="AxigenDK Signer"
DAEMON_NAME_aximilter="AxiMilter"
DAEMON_NAME_spamd="SpamAssassin Bundle"

MY_NAME=${0##*/}
[ -f /etc/sysconfig/${MY_NAME} ] && RCCONF=/etc/sysconfig/${MY_NAME}
[ -f /etc/default/${MY_NAME} ] && RCCONF=/etc/default/${MY_NAME}
[ -f /etc/rc.d/rc.${MY_NAME}.conf ] && RCCONF=/etc/rc.d/rc.${MY_NAME}.conf
[ -n "${RCCONF}" ] && source ${RCCONF}

_check_wrapper() {
  wrapper=""
  handlewrapper=""
  if [ -f /etc/init.d/functions ]; then # Redhat-like functions system
    . /etc/init.d/functions
    [ "$(type -t success)" ] && \
    [ "$(type -t failure)" ] && \
      wrapper="functions"
  elif [ -f /etc/rc.status ]; then # SUSE-like rc.status system
    . /etc/rc.status
    [ "$(type -t rc_reset)" ] && \
    [ "$(type -t rc_failed)" ] && \
    [ "$(type -t rc_status)" ] && \
      wrapper="rc.status"
    rc_reset
  elif [ -f /lib/lsb/init-functions ] && [ "$(lsb_release -is 2>/dev/null)" == "Ubuntu" ]; then # Ubuntu
    . /lib/lsb/init-functions
    [ "$(type -t log_success_msg)" ] && \
    [ "$(type -t log_failure_msg)" ] && \
    [ "$(type -t log_begin_msg)" == "function" ] && \
    [ "$(type -t log_end_msg)" == "function" ] && \
      wrapper="ubuntu-lsb"
  elif [ -f /etc/rc.d/functions ] && [ -f /etc/tfm-release ]; then # TFM
    . /etc/rc.d/functions
    [ "$(type -t success)" ] && \
    [ "$(type -t failure)" ] && \
      wrapper="functions-tfm"
  fi
  if [ "$(type -t startproc)" ] && [ "$(type -t killproc)" ] && [ "$(type -t checkproc)" ]; then
    handlewrapper="skc" # {Start,Kill,Check}PROC
  elif [ "$(type -t start-stop-daemon)" ]; then
    handlewrapper="ssd"
  fi
}

_check_wrapper

_print_ok() {
  case "${wrapper}" in
    "ubuntu-lsb")
      log_end_msg 0
      ;;
    "functions")
      success
      echo
      ;;
    "functions-tfm")
      success
      ;;
    "rc.status")
      rc_failed 0
      rc_status -v
      ;;
    *)
      echo "   [ OK ]"
  esac
}

_print_fail() {
  case "${wrapper}" in
    "ubuntu-lsb")
      log_end_msg 1
      ;;
    "functions")
      failure
      echo
      ;;
    "functions-tfm")
      failure
      ;;
    "rc.status")
      rc_failed 1
      rc_status -v
      ;;
    *)
      echo "   [ FAILED ]"
  esac
}

_check_print() {
  local code=
  if [ -z "$1" ]; then
    code=0
  else
    code=$1
  fi
  if [ "$1" == "0" ]; then # sanity check: test value of $1 as string, not as number
    _print_ok
  else
    _print_fail
  fi
}

_echo_wrapper() {
  if [ "$1" == "-n" ]; then
    local ep="-n"
    shift
  fi
  case "${wrapper}" in
  "ubuntu-lsb")
    log_begin_msg "$@"
    ;;
  *)
    echo ${ep} "$@"
  esac
}

_check_run() {
  # return 0 -> daemon in running
  # return 1 -> daemon is not running
  local x=DAEMON_PATH_$1
  DAEMON_PATH="${!x}"
  case "${handlewrapper}" in
  "skc")
    if checkproc "${DAEMON_PATH}"; then
      return 0
    fi
    ;;
  *)
    if pgrep -f ${DAEMON_PATH} >/dev/null 2>&1; then
      return 0
    fi
    ;;
  esac
  return 1
}

_wait_daemon() {
  local ct=0 t=15
  if [ "$1" == "start" ]; then
    while ! _check_run $2; do
      ct=$((${ct}+1));
      [ ${ct} -gt ${t} ] && return 1
      sleep 1
    done
  else
    while _check_run $2; do
      ct=$((${ct}+1));
      [ ${ct} -gt ${t} ] && return 1
      sleep 1
    done
  fi
  return 0
}

_start_daemon() {
  local ret=
  case "${handlewrapper}" in
  "skc")
    startproc ${DAEMON_PATH} ${DAEMON_OPTIONS} 2>/dev/null
    ret=$?
    ;;
  "ssd")
    start-stop-daemon --start --quiet --exec ${DAEMON_PATH} -- ${DAEMON_OPTIONS}
    ret=$?
    ;;
  *)
    ${DAEMON_PATH} ${DAEMON_OPTIONS}
    ret=$?
  esac
  return ${ret}
}

_stop_daemon() {
  local ret=
  case "${handlewrapper}" in
  "skc")
    killproc -t15 "${DAEMON_PATH}"
    ret=$?
    ;;
  "ssd")
    if [ -f "${DAEMON_PIDFILE}" ]; then
      start-stop-daemon --stop --quiet --retry 15 --pidfile "${DAEMON_PIDFILE}" >/dev/null
      ret=$?
    else
      start-stop-daemon --stop --quiet --retry 15 --exec ${DAEMON_PATH} >/dev/null
      ret=$?
    fi
    ;;
  *)
    pkill -f ${DAEMON_PATH} 2>/dev/null
    ret=$?
  esac
  return ${ret}
}

start() {
  local ret= x= daemon=$1
  x=DAEMON_NAME_${daemon}; DAEMON_NAME="${!x}"
  x=DAEMON_PATH_${daemon}; DAEMON_PATH="${!x}"
  x=DAEMON_OPTIONS_${daemon}; DAEMON_OPTIONS="${!x}"
  x=DAEMON_PIDFILE_${daemon}; DAEMON_PIDFILE="${!x}"
  _echo_wrapper -n "  ${DAEMON_NAME} (${daemon}) start..."
  if _check_run ${daemon}; then
    _echo_wrapper
    _echo_wrapper -n "    already running"
    _print_fail
    return $?
  fi
  _start_daemon
  ret=$?
  if [ ${ret} -ne 0 ]; then
    _check_print "${ret}"
    return ${ret}
  fi
  # if daemon stopped after it started successfully
  _wait_daemon start ${daemon}
  ret=$?
  _check_print ${ret}
  return ${ret}
}

stop() {
  local ret= x= daemon=$1
  x=DAEMON_NAME_${daemon}; DAEMON_NAME="${!x}"
  x=DAEMON_PATH_${daemon}; DAEMON_PATH="${!x}"
  x=DAEMON_OPTIONS_${daemon}; DAEMON_OPTIONS="${!x}"
  x=DAEMON_PIDFILE_${daemon}; DAEMON_PIDFILE="${!x}"
  _echo_wrapper -n "  ${DAEMON_NAME} (${daemon}) stop..."
  if ! _check_run ${daemon}; then
    _echo_wrapper
    _echo_wrapper -n "    already stopped"
    _print_fail
    return $?
  fi
  _stop_daemon
  ret=$?
  if [[ ${ret} -ne 0 ]]; then
    _check_print "${ret}"
    return ${ret}
  fi
  _wait_daemon stop ${daemon}
  ret=$?
  _check_print ${ret}
  return ${ret}
}

status() {
  local ret= x= msg= daemon=$1
  x=DAEMON_NAME_${daemon}; DAEMON_NAME="${!x}"
  x=DAEMON_PATH_${daemon}; DAEMON_PATH="${!x}"
  x=DAEMON_OPTIONS_${daemon}; DAEMON_OPTIONS="${!x}"
  x=DAEMON_PIDFILE_${daemon}; DAEMON_PIDFILE="${!x}"
  msg="${DAEMON_NAME} Daemon is"
  _check_run ${daemon}
  ret=$?
  if [ ${ret} -eq 0 ]; then
    _echo_wrapper "${msg} running."
  else
    _echo_wrapper "${msg} stopped."
  fi
  return ${ret}
}

case "$1" in
  start)
    _echo_wrapper "Starting AXIGEN Filters:"
    for d in ${DAEMONS}; do
      start ${d}
    done
    ;;
  stop)
    _echo_wrapper "Stopping AXIGEN Filters:"
    for d in ${DAEMONS}; do
      stop ${d}
    done
    ;;
  restart)
    _echo_wrapper "Restarting AXIGEN Filters:"
    for d in ${DAEMONS}; do
      _check_run ${d} && stop ${d}
    done
    for d in ${DAEMONS}; do
      _check_run ${d} || start ${d}
    done
    ;;
  force-reload)
    for d in ${DAEMONS}; do
      _check_run ${d} && stop ${d}
    done
    for d in ${DAEMONS}; do
      _check_run ${d} || start ${d}
    done
    ;;
  status)
    for d in ${DAEMONS}; do
      status ${d}
    done
    ;;
  quiet-status)
    for d in ${DAEMONS}; do
      _check_run ${d} || exit $?
    done
    ;;
  *)
    echo "Usage: $0 { start | stop | restart | force-reload | status | quiet-status }"
    exit 1
esac

exit $?

