#!/bin/sh
#
### BEGIN INIT INFO
# Provides: cyrus-imapd
# Required-Start: $remote_fs $syslog $network
# Required-Stop: $remote_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Init system for Kolab Cyrus IMAP/POP3 daemons.
# Description: Init system for Kolab Cyrus IMAP/POP3 daemons.
#              Starts the central Kolab 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
#
# chkconfig: - 65 35
# config: /etc/cyrus.conf
# config: /etc/imapd.conf
# pidfile: /var/run/cyrus-master.pid
#
#		Copyright 2001-2005 by Henrique de Moraes Holschuh <hmh@debian.org>
#		Various modifications done by Sven Mueller <debian@incase.de>
#		Various modifications done by Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
#		Distributed under the GPL version 2
#
# $Id: cyrus-common-2.2.cyrus2.2.init 759 2008-04-02 15:06:19Z sven $

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

PROG="cyrus-master"
SERVICE="cyrus-imapd"

# Default values
CYRUS_CONFIG="/etc/cyrus.conf"
IMAPD_CONFIG="/etc/imapd.conf"
LISTENQUEUE=32
CYRUS_OPTIONS=""
CYRUS_VERBOSE=""
PIDFILE="/var/run/${PROG}.pid"

# Load config
[ -f /etc/sysconfig/${SERVICE} ] && . /etc/sysconfig/${SERVICE}
[ -r /etc/default/${SERVICE} ] && . /etc/default/${SERVICE}

# get_config [config default]
# Extracts config option from config file
get_config() {
    [ $# -ne 2 ] && cyrus_failure "Error in init.d rc script"
    [ ! -f ${IMAPD_CONFIG} ] && return $2
    if conf=$(grep "^$1" ${IMAPD_CONFIG}); then
        echo $conf | awk -F: '{print $2}' | sed -e 's/ //g'
    else
        echo $2
    fi
}

export CONFIGDIRECTORY=$(get_config configdirectory /var/lib/imap)

cyrus_success() {
    if [ $(success >/dev/null 2>&1; echo $?) -ne 0 ]; then
        success $@
    elif [ $(log_success_msg >/dev/null 2>&1; echo $?) -ne 0 ]; then
        log_success_msg $@
    fi
}

cyrus_failure() {
    if [ $(failure >/dev/null 2>&1; echo $?) -ne 0 ]; then
        failure $@
    elif [ $(log_failure_msg >/dev/null 2>&1; echo $?) -ne 0 ]; then
        log_failure_msg $@
    fi
}

cyrus_message() {
    if [ $(log_daemon_msg >/dev/null 2>&1; echo $?) -ne 0 ]; then
        log_daemon_msg $@
    elif [ $(log_success_msg >/dev/null 2>&1; echo $?) -ne 0 ]; then
        echo $@
    fi
}

cyrus_runuser() {
    while [ $# -gt 0 ]; do
        case $1 in
            -s)
                shell="-s $2"
                shift; shift
            ;;
            -c)
                command="-c '$2'"
                shift; shift
            ;;
            -)
                login="-"
                shift
            ;;
            *)
                user=$1
                shift
            ;;
        esac
    done

    if [ -x $(which runuser) ]; then
        runuser $shell $login $user $command; retval=$?
    else
        su $login $shell $user $command; retval=$?
    fi

    return $retval
}

cyrus_exportdb() {
    echo -n "Exporting $prog databases: "
    cd $CONFIGDIRECTORY
    cyrus_runuser - cyrus -s /bin/sh -c "umask 166 ; /usr/lib/cyrus-imapd/cvt_cyrusdb_all export > ${CONFIGDIRECTORY}/db_export.log 2>&1" < /dev/null
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
        cyrus_success "${PROG} exporting databases"
    else
        cyrus_failure "${PROG} error exporting databases, check ${CONFIGDIRECTORY}/db_export.log"
    fi
}

cyrus_importdb() {
    echo -n $"Importing $prog databases: "
    cd $CONFIGDIRECTORY
    cyrus_runuser - cyrus -s /bin/sh -c "umask 166 ; /usr/lib/cyrus-imapd/cvt_cyrusdb_all > ${CONFIGDIRECTORY}/db_import.log 2>&1" < /dev/null
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
        cyrus_success "${PROG} importing databases"
    else
        cyrus_failure "${PROG} error importing databases, check ${CONFIGDIRECTORY}/db_import.log"
    fi
}

# Fedora + derivatives
if [ -f /etc/init.d/functions ]; then
    . /etc/init.d/functions
elif [ -f /lib/lsb/init-functions ]; then
    . /lib/lsb/init-functions
fi

# Now that we've loaded the possible config overriides, check them
# Keep the tests in quotes since the following is true:
#
# if [ -f ]; then echo "yes"; fi
#
[ -f "${CYRUS_CONFIG}" ] && \
    CYRUS_OPTIONS="${CYRUS_OPTIONS} -M ${CYRUS_CONFIG}" || \
    error_out "Configuration file ${CYRUS_CONFIG} does not exist." 6
[ -f "${IMAPD_CONFIG}" ] && \
    CYRUS_OPTIONS="${CYRUS_OPTIONS} -C ${IMAPD_CONFIG}" || \
    error_out "Configuration file ${IMAPD_CONFIG} does not exist." 6

CONFIGDIRECTORY=$(get_config configdirectory /var/lib/imap)
CYRUSMASTER=/usr/lib/cyrus-imapd/cyrus-master
CYRUS_PROC_NAME=$(basename $CYRUSMASTER)
ALWAYS_CONVERT=1

# Check the verbose option
if [ ! -z "${CYRUS_VERBOSE}" ]; then
    # See if it is in fact a numeral
    if [ ! -z "echo ${CYRUS_VERBOSE} | grep -E '^[0-9]+$'" ]; then
        export CYRUS_VERBOSE
    else
        echo "WARNING: verbosity not a numeral, setting to 5"
        export CYRUS_VERBOSE=5
    fi
fi

# Check the listenqueue option
if [ ! -z "${LISTENQUEUE}" ]; then
    # See if it is in fact a numeral
    if [ ! -z "echo ${LISTENQUEUE} | grep -E '^[0-9]+$'" ]; then
        CYRUS_OPTIONS="${CYRUS_OPTIONS} -l ${LISTENQUEUE}"
    else
        echo "WARNING: listen queue size not really set to a numeral. Falling back to 32."
    fi
fi

DAEMON=/usr/lib/cyrus-imapd/cyrus-master
DESCRIPTION="Kolab Cyrus IMAP Server"

set -e

START="--start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} --name ${PROG} -- ${CYRUS_OPTIONS} -d"

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

    [ $# -ne 4 ] && return 0

    [ -d "$4" ] || mkdir -p "$4"
    chown -c -h "$1:$2" "$4"
    chmod -c "$3" "$4"
}

check_status () {
    if [ "$1" = "verbose" ]; then
        PRINTIT=echo
    else
        PRINTIT=true 
    fi
    if [ ! -f ${PIDFILE} ]; then
        # using [c] in the grep avoids catching the grep 
        # process itself
        if ps auxww | grep ${PROG} | grep -v grep ; then
            # Damn, PID file doesn't exist, but cyrmaster process
            # exists. Though strictly speaking, we should not
            # do this, reconstruct the PID file here.
            pidof ${DAEMON} > /dev/null 2>&1 \
                && pidof ${DAEMON} > ${PIDFILE}
            ${PRINTIT} "${PROG} running with PID `cat ${PIDFILE}`"
            return 0
        fi
    fi	
    if [ -s ${PIDFILE} ] && kill -0 `cat ${PIDFILE}` > /dev/null 2>&1; then
		${PRINTIT} "${PROG} running with PID `cat ${PIDFILE}`"
		return 0
    else
        # the PID file might simply not match the cyrmaster process.
        if pidof ${DAEMON} > /dev/null 2>&1 ; then
            # go ahead and fix it
            pidof ${DAEMON} > ${PIDFILE}
            ${PRINTIT} "${PROG} running with PID `cat ${PIDFILE}`"
            return 0
        else
            # no process and/or no PID file, return failure
            ${PRINTIT} "${PROG} not running"
            return 1
        fi
    fi
    # this point should never be reached, return unknown status if it 
    # is anyway
    return 4
}

case "$1" in
    start)
        echo -n "Starting ${DESC}: "
        if check_status ; then
            echo "${DAEMON} already running."
            exit 0
        fi
        if start-stop-daemon ${START} >/dev/null 2>&1 ; then
            echo "$PROG."
        else
            if ! check_status ; then
                echo "(failed)."
                exit 1
            fi
        fi
    ;;

    stop)
        echo -n "Stopping $DESC: "
        if start-stop-daemon --stop --quiet --pidfile /var/run/$PROG.pid \
            --name ${PROG} --quiet --startas $DAEMON >/dev/null 2>&1 ; then
            echo "$PROG."
            rm -f ${PIDFILE}
            exit 0
	else
            # process running?
            if check_status; then
                # Yes, report failure.
                echo "(failed)."
                exit 1
            else
                # No, return as if stopped a running process 
                # successfully.
                echo "."
                rm -f ${PIDFILE}
                exit 0
            fi
        fi
    ;;
    reload|force-reload)
        echo "Reloading $DESC configuration files."
        if start-stop-daemon --stop --signal 1 --quiet \
            --name ${PROG} --pidfile /var/run/$PROG.pid >/dev/null 2>&1 ; then
            exit 0
        else
            exit 1
        fi
    ;;
    restart)
        $0 stop && {
            echo -n "Waiting for complete shutdown..."
            i=5
            while [ $i -gt 0 ] ; do
                # exit look when server is not running
                check_status || break
                sleep 2s
                i=$(($i - 1))
                echo -n "."
            done
            [ $i -eq 0 ] && {
                echo
                echo "fatal: incomplete shutdown detected, aborting."
                exit 1
            }
            echo
        }
        exec $0 start
    ;;
    status)
        check_status verbose
        exit $?
    ;;
    try-restart)
        check_status
        if [ "$?" -eq 0 ]; then
            exec $0 restart
        else
            # LSB says to return 0 in try-restart if the service is
            # not running.
            exit 0
        fi
    ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|force-reload}" 1>&2
        exit 1
    ;;
esac

exit 0
