#! /bin/sh
#
### BEGIN INIT INFO
# Provides: cyrus-common cyrus-imapd
# Required-Start: $syslog $network $remote_fs
# Required-Stop: $syslog $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: common init system for cyrus IMAP/POP3 daemons.
# Description: common init system the for cyrus IMAP/POP3 daemons.
#              starts the central cyrus master process, which can 
#              then start various services depending on configuration.
#              Typically starts IMAP and POP3 daemons, but might also
#              start an NNTP daemon and various helper daemons for
#              distributed mail/news storage systems (high-performance
#              and/or high-reliability setups).
### END INIT INFO
#
#		Copyright 2001-2005 by Henrique de Moraes Holschuh <hmh@debian.org>
#		Various modifications done by Sven Mueller <debian@incase.de>
#               Updated with regards to current /etc/init.d/skeleon by Ondřej Surý <ondrej@sury.org>
#
#		Distributed under the GPL version 2

# Make sure we get sane results on borked locales
LC_ALL=C
export LC_ALL

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME=cyrmaster
DAEMON=/usr/sbin/${NAME}
PIDFILE="/var/run/${NAME}.pid"
DESC="Cyrus IMAPd"

# Check if Cyrus is installed (vs. removed but not purged)
test -x "$DAEMON" || exit 0

# Overridable defaults
unset CYRUS_VERBOSE
unset LISTENQUEUE
unset CONF
unset MASTERCONF

# Read configuration variable file if it is present
[ -r /etc/default/cyrus-imapd ] && . /etc/default/cyrus-imapd

[ "x${CYRUS_VERBOSE}" != "x" ] && export CYRUS_VERBOSE
# Make sure the master process is daemonized
OPTIONS="${OPTIONS} -d"
[ "x${CONF}" != "x" ] && OPTIONS="-C ${CONF} ${OPTIONS}"
[ "x${MASTERCONF}" != "x" ] && OPTIONS="-M ${MASTERCONF} ${OPTIONS}"
[ "x${LISTENQUEUE}" != "x" ] && OPTIONS="-l ${LISTENQUEUE} ${OPTIONS}"

if [ -n "$CONF" ]; then
       	[ -r "$CONF" ] || ( echo Could not read config file $CONF; exit 1)
else
       	CONF=/etc/imapd.conf
fi

SYNC_CLIENT=/usr/lib/cyrus/bin/sync_client
SYNCSHUTDOWN="$(gawk '/^sync_shutdown_file:[[:blank:]]/ { print $2 }' $CONF)"
CONFIGDIR="$(gawk '/^configdirectory:[[:blank:]]/ {print $2}' $CONF)"
LOCK_DIR="$(gawk '/^mboxname_lockpath:[[:blank:]]/ {print $2}' $CONF)"
PROC_DIR="$(gawk '/^proc_path:[[:blank:]]/ {print $2}' $CONF)"
[ -z "$LOCK_DIR" ] && LOCK_DIR="$CONFIGDIR/lock"
[ -z "$PROC_DIR" ] && PROC_DIR="$CONFIGDIR/proc"

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

check_hardwired_config() {
    grep -qE '^PACKAGE_VERSION[[:blank:]]+([0-9]+:|)2[.][24]' \
	/usr/lib/cyrus/cyrus-hardwired-config.txt >/dev/null 2>&1
    return $?
}

verifydb() {
   while read -r DBKEY DBVALUE ; do
	match=`sort -u < $1 | gawk "/^${DBKEY}[[:blank:]]/ { print \\$2 }"`
	[ "x${match}" != "x${DBVALUE}" ] && return 0
   done
   return 1
}

createdir() {
# $1 = user
# $2 = group
# $3 = permissions (octal)
# $4 = path to directory
    [ "$VERBOSE" = "yes" ] && OPT="-c"
    [ -d "$4" ] || mkdir -p "$4"
    chown $OPT -h "$1:$2" "$4"
    chmod $OPT "$3" "$4"
}

missingstatoverride () {
    echo "$0: You are missing a dpkg-statoverride on $1.  Add it." >&2
    exit 1
}

fixdirs () {
	dir=$(dpkg-statoverride --list /var/run/cyrus) \
		|| missingstatoverride /var/run/cyrus
	[ -z "$dir" ] \
		|| createdir $dir
	dir=$(dpkg-statoverride --list /var/run/cyrus/socket) \
		|| missingstatoverride /var/run/cyrus/socket
	[ -z "$dir" ] \
		|| createdir $dir
}

#
# Function that checks consistency of used database backends
#
check_database_backends() {
    # Verify consistency of database backends
    [ -f /usr/lib/cyrus/cyrus-db-types.active ] && {
        # is it safe to start cyrmaster? compare "key value" pairs
        # from the (old) active database types file with the new one
	( sort -u /usr/lib/cyrus/cyrus-db-types.active \
	    | grep DBENGINE \
	    | verifydb /usr/lib/cyrus/cyrus-db-types.txt \
	    ) && {
	    return 1
	}
    }
    return 0
}

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    
    # Clean stale entries
    find "$LOCK_DIR" -mindepth 1 -depth -size 0 -delete
    find "$PROC_DIR" -mindepth 1 -depth -name '[0-9]*' -delete

    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
	|| return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
	$OPTIONS \
	|| return 2

    # cyrmaster is not running
    pidofproc $DAEMON >/dev/null || return 2
}

sync_stop () {
    if [ -e $SYNC_CLIENT ]; then
	# is sync_client running?
	pidofproc $SYNC_CLIENT >/dev/null || return 1

        # Check if the sync file is set and use it is defined
	if [ -n "$SYNCSHUTDOWN" ]; then
	    touch "$SYNCSHUTDOWN" || return 2
	    start-stop-daemon --stop --quiet --retry 0/10 --exec $SYNC_CLIENT
	    rm -f $SYNCSHUTDOWN
	fi
    fi
    return 0
}


#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred

    sync_stop
    [ "$?" = 2 ] && return 2
    
    start-stop-daemon --stop --quiet --retry=QUIT/30/TERM/10/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2

    # cyrmaster is still running
    pidofproc $DAEMON >/dev/null && return 2

    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0
}

# Check for the sanity of the cyrus-imapd environment
if ! check_hardwired_config; then
    echo "$0: cyrus-hardwired-config.txt doesn't contain current version"
    echo "$0: of the package (2.2 or 2.4)"
    exit 1
fi

if ! check_database_backends; then
    /usr/lib/cyrus/bin/upgrade-db || {
	echo "$0: Database backends mismatch and automatic upgrade failes!" 1>&2
	echo "$0: You must manually verify and update the Cyrus databases" 1>&2
	echo "$0: to the new backends." 1>&2
	echo "$0: Please refer to /usr/share/doc/cyrus-common/README.Debian*" 1>&2
	echo "$0: for instructions." 1>&2
	echo
	echo "$0: Cyrmaster not started."
	exit 6
    }
fi

case "$1" in
    start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	fixdirs
	do_start
	case "$?" in
	    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
	    2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
    stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
	    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
	    2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  reload|force-reload)
	log_daemon_msg "Reloading $DESC" "$NAME"
	do_reload
	log_end_msg $?
  	;;
  restart)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	    0|1)
		do_start
		case "$?" in
		    0) log_end_msg 0 ;;
		    1) log_end_msg 1 ;; # Old process is still running
		    *) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  try-restart)
  	pidofproc "$DAEMON" >/dev/null && exec $0 restart
	;;
  *)
	echo "Usage: $0 {start|stop|status|restart|reload|force-reload|try-restart}" 1>&2
	exit 3
	;;
esac

:
