#! /bin/sh
#########################################################################
#
# Copyright (c) 2007,2008 Symas Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
#   copyright notice, this list of conditions and the following disclaimer
#   in the documentation and/or other materials provided with the
#   distribution.
# * Neither the name of the Symas Corporation nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This script will source the file pointed to by $KRB_CONF_FILE,
# which can change any of several variables that control the
# way this script behaves.
#

# LSB-style init information:
### BEGIN INIT INFO
# Provides: kpasswdd
# Required-Start: $network $syslog kdc
# Required-Stop:  $network $syslog kdc
# Default-Start:  2 3 4 5
# Default-Stop:   0 6
# Description:    Symas OpenLDAP KPasswdD
### END INIT INFO
# 
# chkconfig-style init information:
# chkconfig: 2345 61 59
# description: Symas OpenLDAP KPasswdD

# set path so HP-UX basename is visible for USAGE
PATH=/usr/bin:$PATH
CONF_DIR=/opt/symas/etc/heimdal
KRB_CONF_FILE=$CONF_DIR/symas-heimdal.conf
KDC_CONF_FILE=$CONF_DIR/krb5.conf
KPD_CONF_FILE=$KDC_CONF_FILE
PROD_NAME="Symas OpenLDAP Kerberos kpasswd Service"
USAGE="Usage: `basename $0` {start|stop|status|try-restart|condrestart|restart|force-reload|reload|probe|start_msg|stop_msg}"

# Sane values for things that are usually set in symas-heimdal.conf. 
# They'll be overridden when symas-heimdal.conf is sourced.
RUN_KPD=Y
KPD_TIMEOUT=60

# Force a PID file check location. 
#KPD_PID_OVERRIDE=/var/symas/run/kpasswdd.pid

# Basic sanity checking
if [ $# -lt 1 ]; then
	echo $USAGE
	exit 1
fi

# What are we running on?
UNAME=`uname`
if [ "$UNAME" = Linux ]; then
        DIST=unknown
        if [ -r /etc/SuSE-release ]; then
                DIST=SuSE
                test -r /etc/rc.config && . /etc/rc.config
                if [ -r /etc/rc.status ]; then
                        . /etc/rc.status
                        rc_reset
                fi
        fi
        if [ -r /etc/redhat-release ]; then
                DIST=Redhat
                if [ -r /etc/rc.d/init.d/functions ]; then
                        . /etc/rc.d/init.d/functions
                fi
                if [ -f /etc/sysconfig/network ] ; then
                        . /etc/sysconfig/network
                        [ "${NETWORKING}" = "no" ] && exit 0
                fi
        fi
        # Debian requires no specialization at this time
        if [ -r /etc/debian_version ]; then
                DIST=Debian
        fi
	PRELOAD_STMT="LD_PRELOAD=\$KRB_PRELOAD;export LD_PRELOAD"
fi

# Save off the command and remove it from the cmd line
CMD="$1"
shift

# "portably" echo without a newline
pecho () {
        if [ "x$(echo -n foo\cbar)x" = "x-n foox" ]; then
                # ancient bourne shells only have \c
                echo $1\\c
        elif [ "x$(echo -n foo\\cbar)x" = "x-n foox" ]; then
                # some shells unquote differently
                echo $1\\c
        elif [ "x$(echo -n foo\cbar)x" = "xfoocbarx" ]; then
                # bash likes it csh style
                echo -n $1
        elif [ "x$(echo -n foo\\cbar)x" = "xfoocbarx" ]; then
                # some shells unquote differently
                echo -n $1
        else
                # ouch
                echo $1
        fi
}

# Signal a failure for our UNAME and DIST
exit_failed () {
        if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
                rc_failed $1
                rc_status -v
                rc_exit
        elif [ "$UNAME" = Linux -a "$DIST" = Redhat ]; then
                echo_failure
                echo
                exit 1
        else
                echo "...  failed."
                exit 1
        fi
}

# Signal failure but exit with success
exit_disabled () {
    echo "...  ignoring."
    exit 0
}

# Signal a success for our UNAME and DIST
exit_success () {
        if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
                rc_status -v
                rc_exit
        elif [ "$UNAME" = Linux -a "$DIST" = Redhat ]; then
                echo_success
                echo
                exit 0
        else
                echo "...  done."
                exit 0
        fi
}


pid_file_fix () {
	
	if [ -n "$KPD_PID_OVERRIDE" ]; then
		PID_FILE=$KPD_PID_OVERRIDE
		return
	fi

	if [ -f /var/symas/run/${PROC}.pid ]; then
		PID_FILE=/var/symas/run/${PROC}.pid
		return
	fi

	if [ -f /var/symas/${PROC}.pid ]; then
		PID_FILE=/var/symas/${PROC}.pid
		return
	fi

#	if [ -f /var/run/${PROC}.pid ]; then
#		PID_FILE=/var/run/${PROC}.pid
#		return
#	fi
	
}

# Determine if Symas OpenLDAP Kerberos Server is configured. The installer
# only installs symas-kerberos.conf.default, so a missing symas-kerberos.conf 
# is an indicator no one's configured Symas OpenLDAP Kerberos Server. Otherwise, 
# go ahead and source the file.
if [ ! -f $KRB_CONF_FILE ]; then
        pecho "$PROD_NAME is not configured"
        exit_disabled
else
        . $KRB_CONF_FILE
fi

EXEC_DIR=$LIB

case `basename $0` in
	*kpasswddserver|*KPasswdDServer|*kpdserver|*KPDServer)
	PROC=kpasswdd
	if [ ! -r $KPD_CONF_FILE ]; then
                pecho "$PROD_NAME $PROC has not been configured"
                exit_disabled
	fi
	RUN=$RUN_KPD
	;;

	*)
        pecho "$PROD_NAME: $0 is not a recognized link for this script"
        exit_failed 1
	;;
esac
	
PID_FILE=/var/symas/run/${PROC}.pid
pid_file_fix #TODO: Remove in future release.

# Determine if the daemon is running. This will set the $PID variable
# to the process ID of the proc if it is, otherwise it'll make it zero
# length.
if [ -f $PID_FILE ]; then
        PID=`cat $PID_FILE`
        ps -p $PID | grep $PROC > /dev/null
        if [ "$?" -ne 0 ]; then
                PID=""
        fi
fi

# Now process the command.
case "$CMD" in
	# Display start/stop messages. HP/UX makes these calls
	start_msg)
	echo "Starting $PROD_NAME $PROC"
	;;
	stop_msg)
	echo "Stopping $PROD_NAME $PROC"
	;;
	
	# Start the server
	start)
	# Check the run flag in the Heimdal config file. If not set to
	# "Y", then we say "not configured to run" and exit with
	# a status of success.
	# We'll also exit with success if the process is already
	# running, saying "already running".
	if [ "$RUN" != "Y" ]; then
                pecho "$PROD_NAME $PROC is not configured to run"
                exit_success
	elif [ -n "$PID" ]; then
                pecho "$PROD_NAME $PROC is already running"
                exit_success
	fi
	rm -f ${PID_FILE}
        pecho "$PROD_NAME $PROC starting"
	if [ "$PROC" = kpasswdd ]; then
	    # Perform a check to see if a preload is being requested and if
	    # preloading is supported.
	    if [ -n "$KRB_PRELOAD" -a -z "$PRELOAD_STMT" ]; then
		pecho "$PROD_NAME: pre-loading is not supported on this platform."
		exit_failed 1
	    elif [ -n "$KRB_PRELOAD" ]; then
		eval $PRELOAD_STMT
	    fi    
	    nohup "$EXEC_DIR/$PROC" $EXTRA_KPD_ARGS > /dev/null 2>&1 &

		# TODO: If run without appropriate permissions kpasswdd exits with 
		# status 1 but the script is not picking it up. This fix works but 
		# adds a full second to it's run time. Looking at other options for
		# the future. -MSW
		sleep 1
		pid_file_fix #TODO: Remove in future release
		if [ ! -f $PID_FILE ]; then
			exit_failed 1	
		fi
    
	fi
	;;

	# Stop and restart the server
	restart|force-reload)
	$0 stop; $0 start
        exit $?
        ;;

        # restart the server if it was running
        try-restart|condrestart)
	if [ -z "$PID" ]; then
                pecho "$PROD_NAME $PROC is not running"
                exit_failed 7
	fi
        $0 stop && $0 start
        exit $?
        ;;
    
	# Stop the server
        stop)
	if [ -z "$PID" ]; then
                pecho "$PROD_NAME $PROC is not running"
                exit_success
	fi
        pecho "$PROD_NAME $PROC stopping"
	kill $PID
        if [ $? -gt 0 ]; then
                pecho "$PROD_NAME $PROC stopping: kill failed"
                exit_failed 1
        fi
        elapsed=0
        if [ "$PROC" = kpasswdd ]; then 
                timeout=$KPD_TIMEOUT
        fi
        while kill -0 "$PID" 2>/dev/null; do
                pecho "."
                sleep 1
                elapsed=`expr $elapsed + 1`
                if [ $elapsed -gt $timeout ]; then
                        exit_failed 1
                fi
        done
	rm -f $PID_FILE 2>/dev/null
        exit_success
	;;
    
	# Report the status of the server
        status)
	if [ -z "$PID" ]; then
                NOT=" not"
	fi
	pecho "$PROD_NAME $PROC is${NOT} running"
        if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
                if [ -z "$PID" ]; then
                        rc_failed 3
                else
                        rc_failed 0
                fi
                rc_status -v
                rc_exit
        else
                echo
                exit 0
        fi
        ;;

        reload)
        pecho "$PROD_NAME $PROC must use restart"
        exit_failed 3
        ;;

        probe)
        if [ "$UNAME" = Linux ]; then
                # -nt is a bashism
                if [ "$KPD_CONF_FILE" -nt "$PID_FILE" ]; then
                        echo restart
                fi
        else
                # well, no one else is likely to call probe, but...
                echo restart
        fi
        exit 0
        ;;

        # For starting directly under init, like AIX
        underinit)
	exec "$EXEC_DIR/$PROC" $ARGS &
        exit 1
        ;;

	*)
	echo $USAGE
	exit 1
	;;
esac

if [ "$?" != 0 ]; then
        exit_failed 1
else
        exit_success
fi
exit 0
