#! /bin/bash
#
# Author: Mihai Dumitru
#
# /etc/init.d/blfd
#
### BEGIN INIT INFO
# Provides: blfd
# Required-Start: $syslog $local_fs $network
# Required-Stop:  $syslog $local_fs $network
# Default-Start:  3 4 5
# Default-Stop:   0 1 2 6
# Short-Description: BLF control daemon
# Description: Starts and Stops BLF Server and monitors configuration changes
### END INIT INFO

#### HOC #################
# 21.12.2016: mihai
#  - initial creation
# 10.05.2017: mihai
#  - readd blfd to sudoers in case it is gone
# 28.08.2018: bogdan
#  - compare blf pid with possible list of pids (in case of multiple instances)
# 28.08.2018: andrei
#  - kill all instances of blf_lsrv when stopping and before starting a new instance

export PATH=/usr/bin:/bin:$PATH

#lock file for mutual exclusion of start/stop/status operations
LOCK_FILE=/var/lock/subsys/blfd
[ -e $LOCK_FILE ] || ( mkdir -p /var/lock/subsys ; touch $LOCK_FILE )

#max timeout of exlusive lock used for start/stop/status operations
LOCK_TIMEOUT=10

BLFCMD="/opt/blf/blf_lsrv -a 127.0.0.1"
BLFCFGFILE="/opt/blf/blf_config"

PIDFILE=/var/run/blfd.pid

CMDLOCK="/usr/bin/flock -x -w $LOCK_TIMEOUT $LOCK_FILE /usr/bin/sudo /etc/init.d/blfd _locked_"

. /etc/rc.status

rc_reset

function start_blf() {
	#update config age right before reading
	cfgfileage=`stat -c %Z $BLFCFGFILE`
	if [ -e "$BLFCFGFILE" ]; then
		true
	else
		logger -t blfd "Config file $BLFCFGFILE is missing."
		exit 1
	fi
	cstaport=`grep cstaport $BLFCFGFILE | awk '{print $NF}'`
	blflistenport=`grep listenport $BLFCFGFILE | awk '{print $NF}'`
	server_enabled=`grep server_enabled $BLFCFGFILE | awk '{print $NF}'`
	( [ -n "$cstaport" ] && [ $cstaport -eq $cstaport ] ) || {
		logger -t blfd "Config file $BLFCFGFILE is corrupt : cstaport $cstaport is not a number"
		exit 1
	}
	( [ -n "$blflistenport" ] && [ $blflistenport -eq $blflistenport ] ) || {
		logger -t blfd "Config file $BLFCFGFILE is corrupt : listenport $blflistenport is not a number"
		exit 1
	}
	( [ -n "$server_enabled" ] && [ $server_enabled -eq $server_enabled ] ) || {
		logger -t blfd "Config file $BLFCFGFILE is corrupt : server_enabled $server_enabled is not a number"
		exit 1
	}
	if [ "$server_enabled" = "0" ]; then
		echo "D" > $PIDFILE
		return 0
	fi
	
	#check any other instance of blf and kill it
	otherblfisrunning=false
	[[ "`ps -eo pid,cmd | grep blf_lsrv | grep -v grep | awk '{print $1}' | wc -l`" -gt 0 ]] && otherblfisrunning=true	
	if $otherblfisrunning; then
		pkill blf_lsrv
	fi
	
	export LD_LIBRARY_PATH=/usr/lib:/opt/blf/
	#TODO FixMe - improvement - check if listen port is not already in use
	$BLFCMD -p $cstaport -l $blflistenport &
	#write actual PID in the pid file for monitoring
	echo $! > $PIDFILE
	logger -t blfd "Started BLF Server PID `cat $PIDFILE`"
}

function stop_blf() {
	#nothing to do if disabled
	grep -q "I" $PIDFILE && return 0
	grep -q "D" $PIDFILE && return 0
	logger -t blfd "Terminating BLF Server PID `cat $PIDFILE`"
	#kill nice ; TODO FixMe - improve/adapt if BLF takes longer to stop nicely
	kill $(cat $PIDFILE)
	#wait max 3 seconds for the stop
	for i in {0..9}; do
		sleep 0.3
		[ "`cat $PIDFILE`" = "`ps -eo pid,cmd | grep blf_lsrv | grep -v grep | awk '{print $1}'`" ] || break
	done
	#brutal killing in case nice killing timeout
	[ "`cat $PIDFILE`" = "`ps -eo pid,cmd | grep blf_lsrv | grep -v grep | awk '{print $1}'`" ] && kill -9 $(cat $PIDFILE)
	
	#kill any other instance of blf_lsrv
	pkill blf_lsrv
}

case "$1" in
	_locked_)
		logger -t blfd "$*"
		case "$2" in
			start)
				if [ -e $PIDFILE ]; then
					grep -q "I" $PIDFILE && echo "BLF is in initialization. Please repeat the call." && exit 55
					grep -q "D" $PIDFILE && echo "BLF is disabled" && exit 3
					echo "BLF Server is already running."
					exit 0
				fi
				#mark as running by creating empty pidfile
				echo "I" > $PIDFILE
				rm -f $PIDFILE.instop
				#launch daemon
				/usr/bin/setsid /etc/init.d/blfd _daemon_ &
				echo "BLF Server monitoring daemon started."
				exit 0
				;;
			stop)
				if [ -e $PIDFILE ]; then
					touch $PIDFILE.instop
					echo -en "Stopping BLF Server and monitoring daemon ... "
					#wait max 5 seconds for the PIDFILE to dissapear as an success indicator
					for i in {0..9}; do
						sleep 0.5
						[ -e $PIDFILE ] || break
					done
					if [ -e $PIDFILE ]; then
						echo "stop timed out."
						exit 1
					else
						echo "stop was ok"
						exit 0
					fi
				else
					echo "BLF Server is not running."
					exit 0
				fi
				;;
			status)
				if [ -e $PIDFILE ]; then
					grep -q "I" $PIDFILE && echo "BLF is in initialization. Please repeat the call." && exit 55
					grep -q "D" $PIDFILE && echo "BLF is disabled" && exit 3
					exit 0
				fi
				exit 3
				;;
		esac
		/usr/bin/setsid /etc/init.d/blfd _daemon_ &
		;;
	_daemon_)
		#close all FDs so that children do not inherit them
		pushd /proc/$$/fd 1>/dev/null 2>/dev/null
		for afd in $(ls -1); do
			eval exec $afd'>&-'	
		done
		popd 1>/dev/null 2>/dev/null
		#TEMP redirect of out and err
		#TODO FixMe - replace/readapt according to logging
		exec 1>>/var/log/blfd-out-and-err.log
		exec 2>&1
		#remember config age in order to detect changes
		start_blf
		i=0
		while [ -e $PIDFILE ]; do
			sleep 1
			i=$(($i + 1))
			[ $i -eq 10 ] && {
				i=0
				#fixup sudoers in case it is destryoed by CSTA RPM
				if 1>/dev/null 2>/dev/null /usr/bin/grep /etc/init.d/blfd /etc/sudoers; then
					true
				else
					echo 'tomcat ALL=NOPASSWD:/etc/init.d/blfd *' >> /etc/sudoers
				fi
			}
			[ -e $PIDFILE ] || break
			pidisrunning=false
			[[ "`ps -eo pid,cmd | grep blf_lsrv | grep -v grep | awk '{print $1}'`" = *"`cat $PIDFILE`"* ]] && pidisrunning=true
			#daca pid nu mai e atunci dead - restart daca nu e in stop
			if $pidisrunning; then
				true
			else
				[ -e $PIDFILE.instop ] || {
					grep -q "D" $PIDFILE || {
						logger -t blfd "BLF Server died. Will restart it"
						start_blf
						continue
					}
				}
			fi
			#daca e in stop atunci stop
			[ -e $PIDFILE.instop ] && {
				$pidisrunning && stop_blf
				#indicate stop by removing PIDFILE
				rm -f $PIDFILE
				#also terminate this daemon immediately
				exit 0
			}
			#daca cfg changed restart
			[ "$cfgfileage" = "`stat -c %Z $BLFCFGFILE`" ] || {
				logger -t blfd "Config file changed for BLF Server. Will restart it"
				$pidisrunning && stop_blf
				start_blf
			}
		done
		exit 0
		;;
	start)
		$CMDLOCK start
		rc_status -v
		;;
	stop)
		$CMDLOCK stop
		rc_status -v
		;;
	status)
		echo -en "Checking for BLF Server status ..."
		$CMDLOCK status
		rc_status -v
		;;
	*)
		echo "Usage: $0 {start|stop|status}"
		exit 1
		;;
esac

# Set exit status
rc_exit
