#! /bin/sh
### BEGIN INIT INFO
# Provides:          saslauthd
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: saslauthd startup script
# Description:       This script starts the saslauthd daemon. It is
#                    configured using the file /etc/default/saslauthd.
### END INIT INFO

# Author: Fabian Fagerholm <fabbe@debian.org>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin

# Global variables
DAEMON=/usr/sbin/saslauthd
DEFAULT_FILES=`find /etc/default -regex '/etc/default/saslauthd[_a-zA-Z0-9\-]*$' -print | sort`

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

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

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Function that starts all saslauthd instances
# Parameters: none
# Return value: none
do_startall()
{
	for instance in $DEFAULT_FILES
	do
		start_instance $instance
	done
}

# Function that stops all saslauthd instances
# Parameters: none
# Return value: none
do_stopall()
{
	for instance in $DEFAULT_FILES
	do
		stop_instance $instance
	done
}

# Function that sends a SIGHUP to all saslauthd instances
# Parameters: none
# Return value: none
do_reloadall()
{
	for instance in $DEFAULT_FILES
	do
		reload_instance $instance
	done
}

# Function that sends a SIG0 to all saslauthd instances
# Parameters: none
# Return value: none
do_checkall()
{
	for instance in $DEFAULT_FILES
	do
		check_instance $instance
	done
}

# Function that starts a single saslauthd instance
# Parameters:
#	$1 = path of default file for this instance
# Return value:
#	0 on success (does not mean the instance started)
#	1 on failure
start_instance()
{
	# Load defaults file for this instance.
	. $1

	# If the daemon is not enabled, give the user a warning and stop.
	if [ "$START" != "yes" ]; then
		log_warning_msg "To enable $NAME, edit $1 and set START=yes"
		return 0
	fi

	# If the short name of this instance is undefined, warn the user
	# but choose a default name.
	if [ -z "$NAME" ]; then
		log_warning_msg "Short name (NAME) undefined in $1, using default"
		NAME=default
	fi

	log_daemon_msg "Starting $DESC" "$NAME"

	# Check to see if the debug option is specified; fail if it is
	if [ `expr match "$OPTIONS" '-d'` -ne 0 ]; then
		log_failure_msg "The debug option (-d) has been set in /etc/default/saslauthd or elsewhere, not starting"
		return 1
	fi
	# Set OPTIONS to a default value, as noted in the defaults file
	if [ -z "$OPTIONS" ]; then
		log_warning_msg "Options (OPTIONS) undefined in $1, using default (-c -m /var/run/saslauthd)"
		OPTIONS="-c -m /var/run/saslauthd"
	fi

	# Determine run directory and pid file location by looking
	# for an -m option.
	RUN_DIR=`echo "$OPTIONS" | xargs -n 1 echo | sed -n '/^-m$/{n;p}'`
	if [ -z "$RUN_DIR" ]; then
		# No run directory defined in defaults file, fail.
                log_failure_msg "No run directory defined for $NAME (did you forget to set OPTIONS=\"-c -m /var/run/saslauthd\" in the defaults file?), not starting"
		return 1
	fi
	PIDFILE=$RUN_DIR/saslauthd.pid

	# If no mechanisms are defined, fail.
	if [ -z "$MECHANISMS" ]; then
		log_failure_msg "No mechanisms defined in $1, not starting $NAME"
		return 1
	fi

	# If there are mechanism options defined, prepare them for use with
	# the -O flag.
	if [ -n "$MECH_OPTIONS" ]; then
		MECH_OPTIONS="-O $MECH_OPTIONS"
	fi

	# If there is a threads option defined, prepare it for use with
	# the -n flag.
	if [ -n "$THREADS" ]; then
		THREAD_OPTIONS="-n $THREADS"
	fi

	# Construct argument string.
	DAEMON_ARGS="-a $MECHANISMS $MECH_OPTIONS $OPTIONS $THREAD_OPTIONS"

	# If there is a statoverride for the run directory, then pull
	# permission and ownership information from it and create the directory.
	# Otherwise, we create the directory with default permissions and
	# ownership (root:sasl, 710).
	if dpkg-statoverride --list $RUN_DIR > /dev/null; then
		createdir `dpkg-statoverride --list $RUN_DIR`
	else
		createdir root sasl 710 $RUN_DIR
	fi

	# Start the daemon, phase 1: see if it is already running.
	start-stop-daemon --start --quiet --pidfile $PIDFILE --name $NAME \
		--exec $DAEMON --test > /dev/null
	if [ "$?" != "0" ]; then
		log_progress_msg "(already running)"
		log_end_msg 0
		return 0
	fi

	# Start the daemon, phase 2: it was not running, so actually start it now.
	start-stop-daemon --start --quiet --pidfile $PIDFILE --name $NAME \
		--exec $DAEMON -- $DAEMON_ARGS
	if [ "$?" -ne "0" ]; then
		log_end_msg 1
		return 1
	fi

	# Started successfully.
	log_end_msg 0
	return 0
}

# Function that stops a single saslauthd instance
# Parameters:
#	$1 = path of default file for this instance
# Return value:
#	0 on success (daemon was stopped)
#	1 if the daemon was already stopped
#	2 if the daemon could not be stopped
stop_instance()
{
	# Load defaults file for this instance.
	. $1

	# If the short name of this instance is undefined, warn the user
	# but choose a default name.
	if [ -z "$NAME" ]; then
		log_warning_msg "Short name (NAME) undefined in $1, using default"
		NAME=default
	fi

	# Set OPTIONS to a default value, as noted in the defaults file
	if [ -z "$OPTIONS" ]; then
		log_warning_msg "Options (OPTIONS) undefined in $1, using default (-c -m /var/run/saslauthd)"
		OPTIONS="-c -m /var/run/saslauthd"
	fi

	# Determine run directory and pid file location by looking
	# for an -m option.
	RUN_DIR=`echo "$OPTIONS" | xargs -n 1 echo | sed -n '/^-m$/{n;p}'`
	if [ -z "$RUN_DIR" ]; then
		# No run directory defined in defaults file, fail.
                log_failure_msg "No run directory defined for $NAME (did you forget to set OPTIONS=\"-c -m /var/run/saslauthd\" in the defaults file?), not starting"
		return 2
	fi
	PIDFILE=$RUN_DIR/saslauthd.pid

	log_daemon_msg "Stopping $DESC" "$NAME"

	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
		--pidfile $PIDFILE --exec $DAEMON

	if [ "$?" -eq "2" ]; then
		# Failed to stop.
		log_end_msg 1
		return 2
	fi

	if [ "$?" -eq "1" ]; then
		# Already stopped.
		log_progress_msg "(not running)"
	fi

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

	# Stopped successfully.
	log_end_msg 0
	return $RETVAL
}

# Function that sends a SIGHUP to a single saslauthd instance
# Parameters:
#	$1 = path of default file for this instance
# Return value:
#	0 on success (does not mean the daemon was reloaded)
#	other values on failure
reload_instance()
{
	# Load defaults file for this instance.
	. $1

	# If the short name of this instance is undefined, warn the user
	# but choose a default name.
	if [ -z "$NAME" ]; then
		log_warning_msg "Short name (NAME) undefined in $1, using default"
		NAME=default
	fi

	# Set OPTIONS to a default value, as noted in the defaults file
	if [ -z "$OPTIONS" ]; then
		log_warning_msg "Options (OPTIONS) undefined in $1, using default (-c -m /var/run/saslauthd)"
		OPTIONS="-c -m /var/run/saslauthd"
	fi

	# Determine run directory and pid file location by looking
	# for an -m option.
	RUN_DIR=`echo "$OPTIONS" | xargs -n 1 echo | sed -n '/^-m$/{n;p}'`
	if [ -z "$RUN_DIR" ]; then
		# No run directory defined in defaults file, fail.
                log_failure_msg "No run directory defined for $NAME (did you forget to set OPTIONS=\"-c -m /var/run/saslauthd\" in the defaults file?), not starting"
		return 2
	fi
	PIDFILE=$RUN_DIR/saslauthd.pid

	log_daemon_msg "Reloading $DESC" "$NAME"

	# Reload the daemon. First, see if it is already running.
	start-stop-daemon --start --quiet --pidfile $PIDFILE \
		--exec $DAEMON --test > /dev/null

	if [ "$?" -eq "0" ]; then
		# Not running, signal this and stop.
		log_progress_msg "(not running)"
		log_end_msg 0
		return 0
	fi

	start-stop-daemon --stop --signal 1 \
		--pidfile $PIDFILE --exec $DAEMON
	log_end_msg $?
}

# Function that sends a SIG0 to a single saslauthd instance
# Parameters:
#	$1 = path of default file for this instance
# Return value:
#	0 on success (does not mean the daemon was reloaded)
#	other values on failure
check_instance()
{
	# Load defaults file for this instance.
	. $1

	# If the short name of this instance is undefined, warn the user
	# but choose a default name.
	if [ -z "$NAME" ]; then
		log_warning_msg "Short name (NAME) undefined in $1, using default"
		NAME=default
	fi

	# Determine run directory and pid file location by looking
	# for an -m option.
	RUN_DIR=`echo "$OPTIONS" | xargs -n 1 echo | sed -n '/^-m$/{n;p}'`
	if [ -z "$RUN_DIR" ]; then
		# No run directory defined in defaults file, fail.
        log_failure_msg "No run directory defined for $NAME, cannot check"
		return 2
	fi
	PIDFILE=$RUN_DIR/saslauthd.pid

	log_daemon_msg "Checking $DESC" "$NAME"

	# Reload the daemon. First, see if it is already running.
	start-stop-daemon --start --quiet --pidfile $PIDFILE \
		--exec $DAEMON --test > /dev/null

	if [ "$?" -eq "0" ]; then
		# Not running, signal this and stop.
		log_progress_msg "(not running)"
		log_end_msg 3
		return 3
	fi

	log_progress_msg "(running)"
	log_end_msg $?
	return 0
}

# Function that creates a directory with the specified
# ownership and permissions
# Parameters:
#	$1 = user
#	$2 = group
#	$3 = permissions (octal)
#	$4 = path to directory
# Return value: none
createdir()
{
	# In the future, use -P/-Z to have SE Linux enhancement
	install -d --group="$2" --mode="$3" --owner="$1" "$4"
	[ -x /sbin/restorecon ] && /sbin/restorecon "$4"
}

# Action switch
case "$1" in
	start)
		do_startall
		;;
	stop)
		do_stopall
		;;
	reload|force-reload)
		do_reloadall
		;;
	restart)
		do_stopall
		do_startall
		;;
	status)
		do_checkall
		exit $?
		;;
	start-instance)
		if [ -f /etc/default/$2 ]; then
			start_instance /etc/default/$2
		else
			log_failure_msg "Instance $2 does not exist."
		fi
		;;
	stop-instance)
		if [ -f /etc/default/$2 ]; then
			stop_instance /etc/default/$2
		else
			log_failure_msg "Instance $2 does not exist."
		fi
		;;
	reload-instance|force-reload-instance)
		if [ -f /etc/default/$2 ]; then
			reload_instance /etc/default/$2
		else
			log_failure_msg "Instance $2 does not exist."
		fi
		;;
	restart-instance)
		if [ -f /etc/default/$2 ]; then
			stop_instance /etc/default/$2
			start_instance /etc/default/$2
		else
			log_failure_msg "Instance $2 does not exist."
		fi
		;;
	*)
		SCRIPTNAME=$0
		echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
		echo "       or {start-instance|stop-instance|restart-instance|" >&2
		echo "          reload-instance|force-reload-instance} " \
		     "<instance name>" >&2
		exit 3
		;;
esac

:
