#!/bin/bash
#
# Written by Hugo Haas <hugo@debian.org> for ippl.
# Modified by Marc Haber <mh+debian-packages@zugschlus.de>.
# Adapted for dsc-collector by Marc Haber <mh+debian-packages@zugschlus.de>

### BEGIN INIT INFO
# Provides:          dsc-statistics-collector
# Required-Start:    $local_fs $remote_fs $syslog $network $time
# Required-Stop:     $local_fs $remote_fs $syslog $network
# Should-Start:
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: dsc-statistics-collector
# Description:       A DNS Statistics Collector - Collector component
### END INIT INFO

set -e

if ! [ -x "/lib/lsb/init-functions" ]; then
  . /lib/lsb/init-functions
else
  echo "E: /lib/lsb/init-functions not found, lsb-base (>= 3.0-6) needed"
  exit 1
fi

if [ -n "$DSCDEBUG" ]; then
  echo "now debugging $0 $@"
  set -x
fi

LANG=C
export LANG

#read default file
INTERFACE="lo"
LOCAL_ADDRESS="127.0.0.1"
OPTS="-p"
[ -f /etc/default/dsc-statistics-collector ] && . /etc/default/dsc-statistics-collector

PATH="/bin:/usr/bin:/sbin:/usr/sbin"

INSTANCES="${2:-$INSTANCES}"
LIBDIR="/var/lib/dsc-statistics"
RUNDIR="/var/run/dsc-statistics-collector"
PIDFILE="dsc.pid"
CONFSRCFILE="/etc/dsc-statistics/dsc-collector.cfg"
CONFFILE="dsc-collector"
DSCCOMMENTS="no"

shopt -s nullglob
if [ -d "$EXTRAINSTANCEDIR" ]; then
  for INSTANCE in $EXTRAINSTANCEDIR/*; do
    INSTANCES="$INSTANCES $(basename $INSTANCE)"
  done
fi
INSTANCES="${INSTANCES:-default}"
INTERFACE_default="${INTERFACE:-}"
LOCAL_ADDRESS_default="${LOCAL_ADDRESS:-}"
OPTS_default="${OPTS:-}"

DAEMON="/usr/bin/dsc"
NAME="dsc-collector"
DESC="DNS Statistics Collector"

test -f $DAEMON || exit 0

# this is from madduck on IRC, 2006-07-06
# There should be a better possibility to give daemon error messages
# and/or to log things
log()
{
  case "$1" in
    [[:digit:]]*) success=$1; shift;;
    *) :;;
  esac
  log_action_begin_msg "$1"; shift
  log_action_end_msg ${success:-0} "$*"
}


removecomments() {
        if [ "x${DSCCOMMENTS}" = "xno" ] ; then
                grep -E -v '^[[:space:]]*#' | sed -e '/^$/N;/\n$/D' ;
        else
                cat
        fi
}

check_started () {
  INSTANCE="$1"
  lPIDFILE="${RUNDIR}/${INSTANCE}/${PIDFILE}"
  pidofproc -p $lPIDFILE $DAEMON > /dev/null
}

start_single_instance() {
local lINTERFACE
local lLOCAL_ADDRESS
local lOPTS
local lCONFFILE
local lLIBDIR
local lPIDFILE
local gINTERFACE="$INTERFACE"
local gLOCAL_ADDRESS="$LOCAL_ADDRESS"
local gOPTS="$OPTS"
local gBPF="$BPF"
local INTERFACE
local LOCAL_ADDRESS
local OPTS
local BPF

INSTANCE="$1"
lCONFFILE=""
lLIBDIR=""
lPIDFILE=""
lBPF=""
if [ -e "$EXTRAINSTANCEDIR/$INSTANCE" ]; then
  . "$EXTRAINSTANCEDIR/$INSTANCE"
  lINTERFACE="$INTERFACE"
  lLOCAL_ADDRESS="$LOCAL_ADDRESS"
  lOPTS="$OPTS"
  lBPF="$BPF"
else
  eval lINTERFACE=\$INTERFACE_${INSTANCE}
  eval lLOCAL_ADDRESS=\$LOCAL_ADDRESS_${INSTANCE}
  eval lOPTS=\$OPTS_${INSTANCE}
  eval lBPF=\$BPF_${INSTANCE}
fi
if [ -n "$lBPF" ]; then
  lBPF="bpf_program \"$lBPF\";"
fi
lOPTS="${lOPTS:-$gOPTS}"
lINTERFACE="${lINTERFACE:-$gINTERFACE}"
lCONFFILE="${RUNDIR}/${CONFFILE}_$INSTANCE.cfg"
lLIBDIR="${LIBDIR}/${INSTANCE}"
lRUNDIR="${RUNDIR}/${INSTANCE}"
lPIDFILE="${RUNDIR}/${INSTANCE}/${PIDFILE}"

log_daemon_msg "Starting $DESC ($INSTANCE)" "$NAME"

[ -e $lRUNDIR ] || \
  install -d -oroot -groot -m755 $lRUNDIR
[ -e $lLIBDIR ] || \
  install -d -oroot -groot -m755 $lLIBDIR
[ -e $lLIBDIR/upload ] || \
  install -d -oroot -groot -m755 $lLIBDIR/upload
[ -e $lLIBDIR/upload/default ] || \
  install -d -oroot -groot -m755 $lLIBDIR/upload/default


cat << EOF > ${lCONFFILE}.tmp
#########
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# this file is generated dynamically from $CONFSRCFILE
# Any changes you make here will be lost.
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
# WARNING WARNING WARNING
#########
EOF

IFACELINE=""
if [ "$lINTERFACE" == "all" ]; then
  lINTERFACE="$(ip --oneline link show | grep '[^_]UP[^_]' | awk '{print $2}' FS=":")"
fi

for iface in $lINTERFACE; do
  IFACELINE="$IFACELINE interface $iface;"
done

LADDRLINE=""
if [ "$lLOCAL_ADDRESS" == "all" ]; then
  lLOCAL_ADDRESS="$(ip --oneline addr show | sed -n '/.*inet6\?[[:space:]]\+\([a-f0-9\.:]\+\).*/{s||\1|;p;}')"
fi

for laddr in $lLOCAL_ADDRESS; do
  LADDRLINE="$LADDRLINE local_address $laddr;"
done

cat ${CONFSRCFILE} 2>/dev/null | \
  removecomments | \
  sed \
  -e "s|DSClibdirDSC|$lLIBDIR|g" \
  -e "s|DSCpidfileDSC|$lPIDFILE|g" \
  -e "s|DSCinterfaceDSC|$IFACELINE|g" \
  -e "s|DSClocal_addressDSC|$LADDRLINE|g" \
  -e "s|DSCbpf_programDSC|$lBPF|g" \
  >> ${lCONFFILE}.tmp

# test validity if called without -o
# this is not currently possible with dsc,
# but can be easily enabled with this (of course untested) example code
#if [ "x${CONFFILE}" = "x${AUTOCONFIGFILE}" ] && \
#        [ -x ${DAEMON} ] ; then
#        if ! ${DAEMON} --config "${CONFFILE}.tmp" > /dev/null ; then
#                log "Invalid new configfile ${CONFFILE}.tmp"
#                log "not installing ${CONFFILE}.tmp to ${CONFFILE}"
#                exit 1
#        fi
#fi

mv -f ${lCONFFILE}.tmp ${lCONFFILE}
if ! check_started $INSTANCE; then
  start_daemon -p $lPIDFILE $DAEMON $lOPTS $lCONFFILE
  ret=$?
else
  log_failure_msg "already running!"
  ret=1
fi
log_end_msg $ret

return $ret
}

start () {
  for INSTANCE in $INSTANCES; do
    start_single_instance $INSTANCE
  done
}

stop_single_instance () {
  INSTANCE="$1"
  lPIDFILE="${RUNDIR}/${INSTANCE}/${PIDFILE}"
  
  log_daemon_msg "Stopping $DESC ($INSTANCE)" "$NAME"
  killproc -p $lPIDFILE $DAEMON
  ret=$?
  if  [ $ret -eq 0 ]; then
    rm -f $lPIDFILE
  fi
  log_end_msg $ret
  return $ret
}

stop () {
  for INSTANCE in $INSTANCES; do
    stop_single_instance $INSTANCE
  done
}

status_single_instance()
{
  INSTANCE="$1"
  lPIDFILE="${RUNDIR}/${INSTANCE}/${PIDFILE}"

  log_action_begin_msg "checking $DAEMON ($INSTANCE)"
  if check_started $INSTANCE; then
    log_action_end_msg 0 "running"
  else
    if [ -e "$lPIDFILE" ]; then
      log_action_end_msg 1 "$DAEMON ($INSTANCE) failed"
      return 1
    else
      log_action_end_msg 0 "not running"
      return 3
    fi
  fi
}

check_status () {
  ret=0
  for INSTANCE in $INSTANCES; do
    iret=0
    status_single_instance $INSTANCE || iret=$?
    if [ $ret -lt $iret ]; then
      ret=$iret
    fi
  done
  return $ret
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart|force-reload)
    stop
    if [ -z "$?" -o "$?" = "0" ]; then
      start
    fi
    ;;
  status)
    check_status
    ;;
  *)
    log_failure_msg "Usage: $0 {start|stop|restart|force-reload|status}" >&2
    exit 1
    ;;
esac

exit 0
