#!/bin/bash
#
# chkconfig: - 65 35
# description: The Cyrus IMAPD master serves as a master process for the Cyrus \
#              IMAP and POP servers.
# config: /etc/cyrus.conf
# config: /etc/imapd.conf
# pidfile: /var/run/cyrus-master.pid

# author: (c) 2002,2019 - Simon Matter <simon.matter@invoca.ch>
# version: 2019010800

# Source function library
if [ -f /etc/init.d/functions ]; then
  . /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ]; then
  . /etc/rc.d/init.d/functions
else
  exit 0
fi

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0

# Detect our basename and instance name
# $INSTANCE is '2' if $BASENAME is 'cyrus-imapd2'
TMP_NAME=$0
TMP_PWD=$PWD
while [ -L $TMP_NAME ]; do
  if [ ${TMP_NAME/\/} != $TMP_NAME ]; then
    cd ${TMP_NAME%/*}
  fi
  INSTANCE=${TMP_NAME##*/}
  INSTANCE=${INSTANCE/*cyrus-imapd}
  TMP_NAME=$(readlink ${TMP_NAME##*/})
done
cd $TMP_PWD
declare -r BASENAME=${TMP_NAME##*/}${INSTANCE}
unset TMP_NAME
unset TMP_PWD

# instance config
CYRUSCONF=/etc/cyrus${INSTANCE}.conf
IMAPDCONF=/etc/imapd${INSTANCE}.conf
PIDFILE=/var/run/cyrus-master${INSTANCE}.pid
LOCKFILE=/var/lock/subsys/${BASENAME}

# make sure what we have is a valid instance
# and that config files are present
if [ -n "$INSTANCE" ]; then
  [ -L /etc/rc.d/init.d/${BASENAME} ] || exit 0
fi
[ -f $CYRUSCONF ] || exit 0
[ -f $IMAPDCONF ] || exit 0

# expand_config <path>
# handle "@include" sections from imapd style config file
expand_config() {
  while read line; do
    if printf "%s\n" "${line}" | grep -q '^@include:'; then
      expand_config "$( printf "%s\n" "${line}" | cut -d : -f 2- | sed -e 's/^[\t ]*//' )"
    else
      printf "%s\n" "${line}"
    fi
  done < $1
}

# get_config <config> [<default>]
# extracts config option from config file
get_config() {
  searchstr=$1
  if config="$(expand_config $IMAPDCONF | egrep "^${searchstr}:")"; then
    printf "%s\n" "$config" | cut -d : -f 2- | sed -e 's/^[\t ]*//'
  else
    echo $2
  fi
}

# default values
CONFIGDIRECTORY=$(get_config configdirectory /var/lib/imap${INSTANCE})
CYRUSMASTER=/usr/lib/cyrus-imapd/cyrus-master
QUIT_TIMEOUT=10

# fallback to su if runuser not available
if [ -x /sbin/runuser ]; then
  RUNUSER=runuser
else
  RUNUSER=su
fi

QUICK=0

# Source service configuration.
if [ -f /etc/sysconfig/${BASENAME} ]; then
  . /etc/sysconfig/${BASENAME}
else
  echo "${BASENAME}: configfile /etc/sysconfig/${BASENAME} does NOT exist!"
  exit 1
fi

RETVAL=0
RETVAL2=0

is_running() {
  RUNNING=1
  if [ -f $PIDFILE ]; then
    read CYRUS_PID < $PIDFILE
    if [ -n "$CYRUS_PID" ]; then
      ps -p $CYRUS_PID > /dev/null 2>&1
      RUNNING=$?
    fi
  fi
  return $RUNNING
}

start() {
  if is_running; then
    echo -n $"$BASENAME already running."
    false
    echo
  else
    if [ $QUICK -eq 0 ]; then
      echo -n $"Importing $BASENAME databases: "
      cd $CONFIGDIRECTORY
      $RUNUSER - cyrus -s /bin/bash -c "umask 0166 ; INSTANCE=$INSTANCE /usr/lib/cyrus-imapd/cvt_cyrusdb_all > ${CONFIGDIRECTORY}/rpm/db_import.log 2>&1" < /dev/null
      RETVAL=$?
      if [ $RETVAL -eq 0 ]; then
        success $"$BASENAME importing databases"
      else
        failure $"$BASENAME error importing databases, check ${CONFIGDIRECTORY}/rpm/db_import.log"
      fi
      echo
    fi
    if [ $RETVAL -eq 0 ]; then
      echo -n $"Starting ${BASENAME}: "
      $CYRUSMASTER -C $IMAPDCONF -M $CYRUSCONF -p $PIDFILE -d $CYRUSOPTIONS 2>/dev/null 1>&2
      RETVAL=$?
      [ $RETVAL -eq 0 ] && success $"$BASENAME startup" || failure $"$BASENAME startup"
      echo
    fi
  fi
  [ $RETVAL -eq 0 ] && touch $LOCKFILE
  return $RETVAL
}

stop() {
  echo -n $"Shutting down ${BASENAME}: "
  if ! is_running; then
    echo -n $"$BASENAME not running."
    echo_failure
  else
    read CYRUS_PID < $PIDFILE
    kill -QUIT $CYRUS_PID > /dev/null 2>&1
    for ((QUIT=0; QUIT < $QUIT_TIMEOUT; QUIT++)); do
      if is_running; then
        sleep 1
      else
        break
      fi
    done
    if is_running; then
      kill -TERM $CYRUS_PID > /dev/null 2>&1
    else
      echo_success
    fi
    rm -f $PIDFILE
  fi
  RETVAL=$?
  if [ $QUICK -eq 0 ]; then
    if ! is_running; then
      echo
      echo -n $"Exporting $BASENAME databases: "
      cd $CONFIGDIRECTORY
      $RUNUSER - cyrus -s /bin/bash -c "umask 0166 ; INSTANCE=$INSTANCE /usr/lib/cyrus-imapd/cvt_cyrusdb_all export > ${CONFIGDIRECTORY}/rpm/db_export.log 2>&1" < /dev/null
      RETVAL2=$?
      if [ $RETVAL2 -eq 0 ]; then
        success $"$BASENAME exporting databases"
      else
        failure $"$BASENAME error exporting databases, check ${CONFIGDIRECTORY}/rpm/db_export.log"
      fi
    fi
  fi
  echo
  [ $RETVAL -eq 0 ] && rm -f $LOCKFILE
  return $RETVAL
}

restart() {
  stop
  start
}

reload() {
  if ! is_running; then
    echo -n $"$BASENAME not running."
    false
    echo
  else
    echo -n $"Reloading $BASENAME configuration: "
    read CYRUS_PID < $PIDFILE
    kill -HUP $CYRUS_PID > /dev/null 2>&1
    RETVAL=$?
    echo
  fi
  return $RETVAL
}

condrestart() {
  if [ -f $LOCKFILE ]; then
    restart
  fi
}

svcstatus() {
  if [ -f $PIDFILE ]; then
    read CYRUS_PID < $PIDFILE
    if ps -p $CYRUS_PID > /dev/null 2>&1; then
      echo $"$BASENAME (pid $CYRUS_PID) is running..."
      RETVAL=0
    else
      echo $"$BASENAME dead but pid file exists"
      RETVAL=1
    fi
  else
    if [ -f $LOCKFILE ]; then
      echo $"$BASENAME dead but subsys locked"
      RETVAL=2
    else
      echo $"$BASENAME is stopped"
      RETVAL=3
    fi
  fi
  return $RETVAL
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  reload)
    reload
    ;;
  condrestart)
    condrestart
    ;;
  status)
    svcstatus
    ;;
  quickstart)
    QUICK=1
    start
    ;;
  quickstop)
    QUICK=1
    stop
    ;;
  quickrestart)
    QUICK=1
    restart
    ;;
  *)
    echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|quickstart|quickstop|quickrestart}"
    RETVAL=1
esac

exit $RETVAL
