#! /bin/sh
#
# Copyright (c) 2002-2015 by Symas Corporation
# All rights reserved.
#
# The script will source the file pointed to by $SOL_CONF_FILE,
# which can change any of several variables that control the
# way this script behaves.
#
# LSB-style init information:
### BEGIN INIT INFO
# Provides: slapd
# Required-Start: $network $syslog
# Required-Stop:  $network $syslog
# Default-Start:  2 3 4 5
# Default-Stop:   0 6
# Description:    Symas OpenLDAP
### END INIT INFO
# 
# chkconfig-style init information:
# chkconfig: 2345 60 60
# description: Symas OpenLDAP

# set path so HP-UX basename is visible for USAGE
PATH=/usr/bin:$PATH
CONF_DIR=/opt/symas/etc/openldap
SOL_CONF_FILE=$CONF_DIR/symas-openldap.conf
SLAPD_CONF_FILE=$CONF_DIR/slapd.conf
SLAPD_CONF_DYNDIR=$CONF_DIR/slapd.d
PROD_NAME="Symas OpenLDAP LDAP services"
USAGE="Usage: `basename $0` {start|stop|status|try-restart|condrestart|restart|force-reload|reload|probe|start_msg|stop_msg} [--gdb {attach|backtrace|core-grab|core-wait|script SCRIPT_PATH}] [-d n]\n"

# Sane values for things that are usually set in
# symas-openldap.conf. They'll be overridden when symas-openldap.conf
# is sourced.
RUN_SLAPD=Y
SLAPD_USER=root
# set SLAPD_GROUP below for AIX/OSX customization
# SLAPD_GROUP=root
HOST_LIST="ldap:///"
SLAPD_TIMEOUT=60

GDB_PATH="`which gdb 2>/dev/null`"
GDB_ARGS="-nx -q"
GDB_EXTRA_ARGS=""
GDB_SCRIPT_DIR="/opt/symas/lib64/gdb"
GDB_ATTACH_SCRIPT="$GDB_SCRIPT_DIR/default_attach.gdb"
GDB_BT_SCRIPT="$GDB_SCRIPT_DIR/all_threads_full_bt.gdb"
GDB_CORE_GRAB="$GDB_SCRIPT_DIR/core_grab.gdb"
GDB_CORE_WAIT="$GDB_SCRIPT_DIR/core_wait.gdb"
GDB_ON_START='N'

USAGE="Usage: `basename $0` {start|stop|status|try-restart|condrestart|restart|force-reload|reload|probe|start_msg|stop_msg} [-d n]"
if [ -x "$GDB_PATH" ]; then
	USAGE="$USAGE [--gdb {attach|backtrace|core-grab|core-wait|script SCRIPT_PATH}]\n"
else
	USAGE="$USAGE\n\t\tNote: Unable to find gdb binary so some options are not available for use.\n"
fi

# 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
fi

if [ "$UNAME" = AIX ]; then
        SLAPD_GROUP=system
elif [ "$UNAME" = Darwin ]; then
        SLAPD_GROUP=wheel
elif [ "$UNAME" = FreeBSD ]; then
        SLAPD_GROUP=wheel
else
        SLAPD_GROUP=root
fi

if [ "$UNAME" = Darwin ]; then
        SU=/usr/bin/su
else
        SU=/bin/su
fi

if [ "$UNAME" = Linux ]; then
	PRELOAD_STMT="LD_PRELOAD=\$SOL_PRELOAD;export LD_PRELOAD"
elif [ "$UNAME" = SunOS ]; then
	PRELOAD_STMT="LD_PRELOAD=\$SOL_PRELOAD;export LD_PRELOAD"
elif [ "$UNAME" = HP-UX ]; then
	PRELOAD_STMT="LD_PRELOAD=\$SOL_PRELOAD;export LD_PRELOAD"
elif [ "$UNAME" = Darwin ]; then
	PRELOAD_STMT="DYLD_INSERT_LIBRARIES=\$SOL_PRELOAD;DYLD_FORCE_FLAT_NAMESPACE=1;export LD_PRELOAD;export DYLD_FORCE_FLAT_NAMESPACE"
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
	elif [ "$UNAME" = "SunOS" ]; then
		# sun echo works different inside `` or $()
		echo $1\\c
        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
}

EXEC_DIR=/opt/symas/lib64
SOL_LIB=/opt/symas/lib64

case `basename $0` in
	*solserver*|*SOLServer*)
	PROC=slapd
	if [ ! -r $SLAPD_CONF_FILE ] && [ ! -d $SLAPD_CONF_DYNDIR ]; then
                pecho "$PROD_NAME $PROC has not been configured"
		exit_disabled
	fi
	;;

	*)
        pecho "Symas OpenLDAP: $0 is not a recognized link for this script"
        exit_failed 1
	;;
esac

# Check the current and soon-to-be new default locations for the slapd PID
# file. 
PID_FILE=/var/symas/${PROC}.pid

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

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

# Pick up values that may have changed in SOL_CONF_FILE. $* is at the end
# of ARGS so that an alternative -g and -u values can be specified on the
# command line. ARGS gets set again the same way after the GDB code. 
RUN=$RUN_SLAPD
ARGS="-u $SLAPD_USER -g $SLAPD_GROUP $*"

# 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

# Set up optional GDB Loading
if [ "$CMD" = '--gdb' -o "$1" = '--gdb' ]; then

	if [ ! -x "$GDB_PATH" ]; then 
		pecho "Could not find executable gdb. Is gdb installed?"
		exit_failed 1
	fi

	if [ ! -n "$GDB_SCRIPT_DIR" ]; then 
		GDB_SCRIPT_DIR="/opt/symas/lib64/gdb"
	fi

	# TODO: Add support for other methods. e.g. 'restart'. requires refactoring of prior code.
	if [ $CMD = 'start' ]; then 

		if [ $# -lt 1 ]; then echo $USAGE; exit_failed 1; fi
		shift
		
		case "$1" in
			attach|backtrace)
				ARGS_REQ=1
				GDB_MODE_ARGS="--gdb $1"
				;;

			core-grab)
				pecho "Core Dumps at server start not supported."
				exit_failed 1
				;;

			core-wait)
				ARGS_REQ=1
				GDB_MODE_ARGS="--gdb $1"
				;;

			script)
				ARGS_REQ=2
				GDB_MODE_ARGS="--gdb $1 $2"
				;;
			*)
				echo $USAGE
				exit_failed 1
				;;
		esac
		
		GDB_ON_START=Y

		if [ $# -lt $ARGS_REQ ]; then echo $USAGE; exit_failed 1; fi
		shift $ARGS_REQ

	elif [ $CMD = '--gdb' ]; then # Cases where we attach to slapd
		
		if [ ! -n "$PID" ]; then
			exit_failed 1
		fi

		case "$1" in
		
			attach)
				GDB_ARGS="$GDB_ARGS -x $GDB_ATTACH_SCRIPT"
				;;
	
			backtrace)
				GDB_ARGS="$GDB_ARGS -batch -x $GDB_BT_SCRIPT"
				;;
			
			core-grab)
				GDB_ARGS="$GDB_ARGS -x $GDB_CORE_GRAB"
				;;

			core-wait)
				GDB_ARGS="$GDB_ARGS -x $GDB_CORE_WAIT"
				;;

			script)
				if [ $# -lt 1 ]; then echo $USAGE; exit_failed 1; fi
				shift

				if [ -f "$1" ]; then
					GDB_SCRIPT="$1"
				elif [ -f "$GDB_SCRIPT_DIR/$1" ]; then
					GDB_SCRIPT="$GDB_SCRIPT_DIR/$1"
				else
					pecho "$USAGE"
				exit_failed 1	
				fi
				
				GDB_ARGS="$GDB_ARGS -batch -x $GDB_SCRIPT"
				;;

			*)
				pecho "$USAGE"
				exit_failed 1
				;;

		esac

		$GDB_PATH $GDB_ARGS $GDB_EXTRA_ARGS $EXEC_DIR/$PROC $PID
		if [ $?	-ne 0 ]; then
			pecho "GDB returned error \"$?\". Do you have appropriate privilegess to attach?"
		else
			exit_success
		fi
	
	fi

fi


#Set ARGS again, in case we shifted off now processed gdb params. 
ARGS="-u $SLAPD_USER -g $SLAPD_GROUP $*"


# 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 Symas OpenLDAP 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" = slapd ]; then
		# Perform a check to see if a preload is being requested and if
		# preloading is supported.
		if [ -n "$SOL_PRELOAD" -a -z "$PRELOAD_STMT" ]; then
			pecho "$PROD_NAME: pre-loading is not supported on this platform."
			exit_failed 1
		elif [ -n "$SOL_PRELOAD" ]; then
			eval $PRELOAD_STMT
		fi
		"$EXEC_DIR/$PROC" $ARGS -h "$HOST_LIST" $EXTRA_SLAPD_ARGS
	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" = slapd ]; then 
                timeout=$SLAPD_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
        ;;

	# OpenLDAP has dynamic configuration, but not in a fashion
	# usable by an init script
        reload)
        pecho "$PROD_NAME $PROC must use restart"
        exit_failed 3
        ;;

        probe)
        if [ "$UNAME" = Linux ]; then
                # -nt is a bashism
                if [ "$SLAPD_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" -d 0 $ARGS -h "$HOST_LIST"
        exit 1
        ;;

	*)
	echo $USAGE
	exit 1
	;;
esac

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