#!/bin/bash

### BEGIN INIT INFO
# Provides:          fdtsms
# Required-Start:    autossh mosquitto
# Required-Stop:     autossh mosquitto
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: fdtsms
# Description:       fdtsms
### END INIT INFO

# Return values acc. to LSB for all commands but status:
# 0 - success
# 1 - misc error
# 2 - invalid or excess args
# 3 - unimplemented feature (e.g. reload)
# 4 - insufficient privilege
# 5 - program not installed
# 6 - program not configured
# 7 - program is not running
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signalling is not supported) are
# considered a success.

# Config-Datei einlesen
source /usr/local/smi/trx/etc/sms.conf

myname=$(echo $0 | $awk -F/ '{ print $NF }')

start_daemon()
{
	# Prüfen ob Daemon bereits läuft
	instances=0
	k=1
	while [ -n "$(eval echo '$'SmsTtyToBind_${k}_name)" ]; do
		runVAR="$(eval echo '$'SmsTtyToBind_${k}_name)"
		trxtype="$(eval echo '$'SmsTtyToBind_${k}_trxtype)"
		if ([ -e "${rundir}/${myname}.${trxtype}.rx.${runVAR}.pid" ] || [ -e "${rundir}/${myname}.${trxtype}.tx.${runVAR}.pid" ]); then ((instances++)); fi
		((k++))
	done
	if [ ! $instances -gt '0' ]; then
		echo -n "Starting ${myname}... "
		# Start des Skripts im Logfile vermerken
		log "$myname" "---------------------"
		log "$myname" "Start ${myname} begonnen"

		# Prüfen ob benötigte Binaries vorhanden sind
		missedfiles=0
		log "$myname" "prüfe Existenz nötiger Programme"
		test_if_exist=()
		test_if_exist+=($stty)
		test_if_exist+=($mysql)
		test_if_exist+=($awk)
		test_if_exist+=($php)
		test_if_exist+=($nullmodem)
		test_if_exist+=($socat)
		#test_if_exist+=($sms_program)
		test_if_exist+=($mosquitto_pub)	
		test_if_exist+=($mosquitto_sub)	
		#test_if_exist+=(${sms_program}/$readline)
		#test_if_exist+=(${sms_program}/$readchar)
		#test_if_exist+=(${sms_program}/$devicewriter)
		#test_if_exist+=(${sms_program}/$devicelogger)
		#test_if_exist+=(${sms_program}/$SmsMonitor)
		for i in "${!test_if_exist[@]}"; do
			if [ -e "${test_if_exist[$i]}" ]; then
				log "$myname" "  found: \"${test_if_exist[$i]}\""
			else
				log "$myname" "  missed: \"${test_if_exist[$i]}\""
				((missedfiles++))
			fi
		done
		if (( $missedfiles > 0 )); then
			log "$myname" "failed"
			echo "failed!"
			#stop_daemon
			exit 5
		fi
		log "$myname" "done"
		
		log "$myname" "initialisiere serielle Schnittstellen"
		# für alle seriellen Interfaces im configfile (SmsSerialDev_X_name)
		ret=0
		ret_serialinit=0
		i=1
		while [ -n "$(eval echo '$'SmsSerialDev_${i}_name)" ]; do
			# Initialisierungskommandos ausführen
			j=1
			while [ -n "$(eval echo '$'SmsSerialDev_${i}_init_${j})" ]; do
				$(eval echo '$'SmsSerialDev_${i}_init_${j}) > /dev/null 2>&1
				ret=$?
				# ein fehlgeschlagenes Initialisierungskommando wird einmal wiederholt (weil stty nach einem Rechner-Neustart beim 1. Aufruf fehlschlägt)
				if (( $ret > 0 ));then
					$(eval echo '$'SmsSerialDev_${i}_init_${j}) > /dev/null 2>&1
						ret=$?
				fi
				ret_serialinit=$(($ret_serialinit+$ret))
				((j++))
			done
                
			# Wenn Initialisierung nicht erfolgreich war
			if (( $ret_serialinit > 0 )); then
				# Fehlermeldung ins Logfile schreiben und Skript beenden
				log "$myname" "  failed: \"$(eval echo '$'SmsSerialDev_${i}_name)\""
			else
				log "$myname" "  ok: \"$(eval echo '$'SmsSerialDev_${i}_name)\""
			fi
			((i++))
		done
		if (( $ret_serialinit > 0 )); then
			log "$myname" "failed"
			echo "failed!"
			exit 1
		fi
		log "$myname" "done"

		# userdefinierbare Initialisierungskommandos ausführen
		ret=0
		ret_userinit=0
		l=1
		while [ -n "$(eval echo '$'SmsUserinit_${l})" ]; do
			log "$myname" "\"$(eval echo '$'SmsUserinit_${l}) start\""
			"$(eval echo '$'SmsUserinit_${l})" start > /dev/null 2>&1
			ret=$? 
			ret_userinit=$(($ret_userinit+$ret))
			log "$myname" "\"$(eval echo '$'SmsUserinit_${l}) start\" done"
			((l++))
		done
		# Wenn Initialisierung nicht erfolgreich war
		if (( $ret_userinit > 0 )); then
			# Fehlermeldung ins Logfile schreiben und Skript beenden
			log "$myname" "Stop! Userdefinierbares Init-Kommando fehlgeschlagen"
			echo "failed!"
			stop_daemon
			exit 1
		fi
		
		# Whitelist-Directories erstellen und Whitelist-Einträge laden
		log "$myname" "creating allow/deny list directories"
		if ([ -e "$SmsAllowRxConfdir" ] && [ -n "$useSmsAllowRx" ]); then
			if !([ -e "$SmsAllowRxRundir" ]); then
				log "$myname" "  creating \"$SmsAllowRxRundir\""
				mkdir -p "$SmsAllowRxRundir"
			fi
			for file in $(find $SmsAllowRxConfdir -maxdepth 1 -xtype f); do
				log "$myname" "    loading allow-rx list entries from \"$file\""
				while read -r line; do
					touch "$SmsAllowRxRundir/$(echo $line | awk -F: '{ print $1 }')"
				done < "$file"
			done
		fi
		if ([ -e "$SmsAllowTxConfdir" ] && [ -n "$useSmsAllowTx" ]); then
			if !([ -e "$SmsAllowTxRundir" ]); then
				log "$myname" "  creating \"$SmsAllowTxRundir\""
				mkdir -p "$SmsAllowTxRundir"
			fi
			for file in $(find $SmsAllowTxConfdir -maxdepth 1 -xtype f); do
				log "$myname" "    loading list entries from \"$file\""
				while read -r line; do
					touch "$SmsAllowTxRundir/$(echo $line | awk -F: '{ print $1 }')"
				done < "$file"
			done
		fi
		if ([ -e "$SmsDenyRxConfdir" ] && [ -n "$useSmsDenyRx" ]); then
			if !([ -e "$SmsDenyRxRundir" ]); then
				log "$myname" "  creating \"$SmsDenyRxRundir\""
				mkdir -p "$SmsDenyRxRundir"
			fi
			for file in $(find $SmsDenyRxConfdir -maxdepth 1 -xtype f); do
				log "$myname" "    loading list entries from \"$file\""
				while read -r line; do
					touch "$SmsDenyRxRundir/$(echo $line | awk -F: '{ print $1 }')"
				done < "$file"
			done
		fi
		if ([ -e "$SmsDenyTxConfdir" ] && [ -n "$useSmsDenyTx" ]); then
			if !([ -e "$SmsDenyTxRundir" ]); then
				log "$myname" "  creating \"$SmsDenyTxRundir\""
				mkdir -p "$SmsDenyTxRundir"
			fi
			for file in $(find $SmsDenyTxConfdir -maxdepth 1 -xtype f); do
				log "$myname" "    loading list entries from \"$file\""
				while read -r line; do
					touch "$SmsDenyTxRundir/$(echo $line | awk -F: '{ print $1 }')"
				done < "$file"
			done
		fi
		log "$myname" "done"

		# auf jedem konfigurierten Interface Read-Spooler, Write-Spooler, fdtsms und Modem-Init starten 
		k=1
		while [ -n "$(eval echo '$'SmsTtyToBind_${k}_name)" ]; do
			runVAR="$(eval echo '$'SmsTtyToBind_${k}_name)"
			trxtype="$(eval echo '$'SmsTtyToBind_${k}_trxtype)"
			baud="$(eval echo '$'SmsTtyToBind_${k}_baud)"
			
			# erstelle Portmultiplexer
			if [ $(ps -ef |grep nullmodem |grep -c ${runVAR}) = 0 ];then	
				log "$myname" "erstelle Portmultiplexer \"$runVAR\" mit 3 Ports"
				log "$myname" "/dev/${runVAR}_0 /dev/${runVAR}_1 /dev/${runVAR}_2"
				$nullmodem -qr /dev/${runVAR}_0 /dev/${runVAR}_1 /dev/${runVAR}_2
			fi
	
			if [ $(ps -ef |grep socat |grep -c ${runVAR}) = 0 ];then
				log "$myname" "binde \"/dev/${runVAR}\"(Modem) an \"/dev/${runVAR}_0\""
				$socat -ly /dev/${runVAR},nonblock,raw,b${baud} /dev/${runVAR}_0,raw,echo=0 &
				log "$myname" "erstelle Pseudoterminal \"/dev/${SmsScriptName}${k}_1\" an \"/dev/${runVAR}_1\""
				$socat -ly pty,link=/dev/${SmsScriptName}${k}_1,nonblock,raw,echo=0 /dev/${runVAR}_1,raw,echo=0 &
				log "$myname" "erstelle Pseudoterminal \"/dev/${SmsScriptName}${k}_2\" an \"/dev/${runVAR}_2\""
				$socat -ly pty,link=/dev/${SmsScriptName}${k}_2,nonblock,raw,echo=0 /dev/${runVAR}_2,raw,echo=0 &
			fi
	 
			log "$myname" "starte Read-Line-Logger auf \"$runVAR\""
			cp "${sms_program}/$devicelogger" "$rundir/$myname.$devicelogger.$readline.$runVAR"
			start-stop-daemon --start --quiet --pidfile "$rundir/$myname.$devicelogger.$readline.$runVAR.pid" --make-pidfile --background --exec  "$rundir/$myname.$devicelogger.$readline.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte Read-Line-Spooler auf \"$runVAR\""
			cp "${sms_program}/$readline" "$rundir/$myname.$readline.$runVAR"
			start-stop-daemon --start --quiet --pidfile "$rundir/$myname.$readline.$runVAR.pid" --make-pidfile --background --exec  "$rundir/$myname.$readline.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte Read-Char-Spooler auf \"$runVAR\""
			cp "${sms_program}/$readchar" "$rundir/$myname.$readchar.$runVAR"
			start-stop-daemon --start --quiet --pidfile "$rundir/$myname.$readchar.$runVAR.pid" --make-pidfile --background --exec  "$rundir/$myname.$readchar.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte Write-Logger auf \"$runVAR\""
			cp "${sms_program}/$devicelogger" "$rundir/$myname.$devicelogger.$devicewriter.$runVAR"
			start-stop-daemon --start --quiet --pidfile "$rundir/$myname.$devicelogger.$devicewriter.$runVAR.pid" --make-pidfile --background --exec  "$rundir/$myname.$devicelogger.$devicewriter.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte Write-Spooler auf \"$runVAR\""
			cp "${sms_program}/$devicewriter" "$rundir/$myname.$devicewriter.$runVAR"
			start-stop-daemon --start --quiet --pidfile "$rundir/$myname.$devicewriter.$runVAR.pid" --make-pidfile --background --exec  "$rundir/$myname.$devicewriter.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte ${trxtype}.rx auf \"$runVAR\""
			cp "${sms_program}/${trxtype}.rx" "${rundir}/${myname}.${trxtype}.rx.$runVAR"
			start-stop-daemon --start --quiet --pidfile "${rundir}/${myname}.${trxtype}.rx.$runVAR.pid" --make-pidfile --background --exec  "${rundir}/${myname}.${trxtype}.rx.$runVAR"
			log "$myname" "done"
			
			log "$myname" "starte ${trxtype}.tx auf \"$runVAR\""
			cp "${sms_program}/${trxtype}.tx" "${rundir}/${myname}.${trxtype}.tx.$runVAR"
			start-stop-daemon --start --quiet --pidfile "${rundir}/${myname}.${trxtype}.tx.$runVAR.pid" --make-pidfile --background --exec  "${rundir}/${myname}.${trxtype}.tx.$runVAR"
			log "$myname" "done"
			
			log "$myname" "\"${sms_program}/${trxtype}.init start $runVAR\""
			"${sms_program}/${trxtype}.init" start $runVAR
			log "$myname" "done"
			
			((k++))
		done

		# Cronjob für regular run skript anlegen
		log "$myname" "erstelle Cronjob für monitor skript"
		echo "*/1 *    * * *   root	${sms_program}/${SmsMonitor} >/dev/null 2>&1" > "$crondir/${myname}"
		log "$myname" "done"

		log "$myname" "Start ${myname} abgeschlossen"
		log "$myname" "--------------------------"
		echo "done!"
	else
		echo "Daemon is still running! Nothing to do."
	fi
}

stop_daemon()
{
    echo -n "Stopping ${myname}... "
	log "$myname" "--------------------"
	log "$myname" "Stop ${myname} begonnen"

	# Cronjob löschen, der beim Starten angelegt wurde
	if [ -e "$crondir/${myname}" ]; then
		log "$myname" "lösche Cronjob für monitor skript"
		rm -f "$crondir/${myname}"
		log "$myname" "done"
	fi

    # auf allen konfigurierten Interfaces
	l=1
	while [ -n "$(eval echo '$'SmsTtyToBind_${l}_name)" ]; do
		runVAR="$(eval echo '$'SmsTtyToBind_${l}_name)"
		trxtype="$(eval echo '$'SmsTtyToBind_${l}_trxtype)"
		
		# fdtsms beenden
		if [ -e "${rundir}/${myname}.${trxtype}.rx.$runVAR.pid" ]; then
			pid=$(cat "${rundir}/${myname}.${trxtype}.rx.$runVAR.pid")
			log "$myname" "beende ${trxtype}.rx auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "${rundir}/${myname}.${trxtype}.rx.$runVAR"
			rm -f "${rundir}/${myname}.${trxtype}.rx.$runVAR.pid"
			log "$myname" "done"
		fi
		if [ -e "${rundir}/${myname}.${trxtype}.tx.$runVAR.pid" ]; then
			pid=$(cat "${rundir}/${myname}.${trxtype}.tx.$runVAR.pid")
			log "$myname" "beende ${trxtype}.tx auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "${rundir}/${myname}.${trxtype}.tx.$runVAR"
			rm -f "${rundir}/${myname}.${trxtype}.tx.$runVAR.pid"
			log "$myname" "done"
		fi

		# Schnittstelleninitialisierungsskript mit "stop" ausführen	
		log "$myname" "\"${sms_program}/${trxtype}.init stop $runVAR\""
		"${sms_program}/${trxtype}.init" stop $runVAR
		log "$myname" "done"

		# Read-Char-Spooler beenden
		if [ -e "$rundir/$myname.$readchar.$runVAR.pid" ]; then
			pid=$(cat "$rundir/$myname.$readchar.$runVAR.pid")
			log "$myname" "beende Read-Char-Spooler auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "$rundir/$myname.$readchar.$runVAR"
			rm -f "$rundir/$myname.$readchar.$runVAR.pid"
			log "$myname" "done"
		fi

		# Read-Line-Spooler beenden
		if [ -e "$rundir/$myname.$readline.$runVAR.pid" ]; then
			pid=$(cat "$rundir/$myname.$readline.$runVAR.pid")
			log "$myname" "beende Read-Line-Spooler auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "$rundir/$myname.$readline.$runVAR"
			rm -f "$rundir/$myname.$readline.$runVAR.pid"
			log "$myname" "done"
		fi

		# Read-Line-Logger beenden
		if [ -e "$rundir/$myname.$devicelogger.$readline.$runVAR.pid" ]; then
			pid=$(cat "$rundir/$myname.$devicelogger.$readline.$runVAR.pid")
			log "$myname" "beende Read-Line-Logger auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "$rundir/$myname.$devicelogger.$readline.$runVAR"
			rm -f "$rundir/$myname.$devicelogger.$readline.$runVAR.pid"
			log "$myname" "done"
		fi		
	
		# Write-Spooler beenden
		if [ -e "$rundir/$myname.$devicewriter.$runVAR.pid" ]; then
			pid=$(cat "$rundir/$myname.$devicewriter.$runVAR.pid")
			log "$myname" "beende Write-Spooler auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "$rundir/$myname.$devicewriter.$runVAR"
			rm -f "$rundir/$myname.$devicewriter.$runVAR.pid"
			log "$myname" "done"
		fi
	
		# Write-Logger beenden
		if [ -e "$rundir/$myname.$devicelogger.$devicewriter.$runVAR.pid" ]; then
			pid=$(cat "$rundir/$myname.$devicelogger.$devicewriter.$runVAR.pid")
			log "$myname" "beende Write-Logger auf \"$runVAR\" mit PID \"$pid\""
			for k in $(pstree -p $(echo $pid) | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "); do
				kill $k > /dev/null 2>&1
			done
			rm -f "$rundir/$myname.$devicelogger.$devicewriter.$runVAR"
			rm -f "$rundir/$myname.$devicelogger.$devicewriter.$runVAR.pid"
			log "$myname" "done"
		fi
		
		# von den angeschlossenen Modems werden beim Initialisieren own_number,network_operator,registration_status,signal_strength_dBm
		# ausgelesen 
		# hier werden sie beim Beenden wieder gelöscht
		#
		log "$myname" "deleting status files for \"$runVAR\""
		if [ -e "$rundir/$runVAR.last_vital" ]; then
			log "$myname" "  \"$rundir/$runVAR.last_vital\""
			rm -f "$rundir/$runVAR.last_vital"
		fi	
		if [ -e "$rundir/$runVAR.own_number" ]; then
			log "$myname" "  \"$rundir/$runVAR.own_number\""
			rm -f "$rundir/$runVAR.own_number"
		fi	
		if [ -e "$rundir/$runVAR.toa" ]; then
			log "$myname" "  \"$rundir/$runVAR.toa\""
			rm -f "$rundir/$runVAR.toa"
		fi	
		if [ -e "$rundir/$runVAR.signal_strength_dBm" ]; then
			log "$myname" "  \"$rundir/$runVAR.signal_strength_dBm\""
			rm -f "$rundir/$runVAR.signal_strength_dBm"
		fi	
		if [ -e "$rundir/$runVAR.registration_status" ]; then
			log "$myname" "  \"$rundir/$runVAR.registration_status\""
			rm -f "$rundir/$runVAR.registration_status"
		fi	
		if [ -e "$rundir/$runVAR.network_operator" ]; then
			log "$myname" "  \"$rundir/$runVAR.network_operator\""
			rm -f "$rundir/$runVAR.network_operator"
		fi	
		log "$myname" "done"
		
		# beende Portmultiplexer
		if [ $(ps -ef |grep nullmodem |grep -c ${runVAR}) > 0 ];then
			pid=$(ps -ef |grep nullmodem |grep ${runVAR} |$awk '{ print $2 }')
			log "$myname" "beende Portmultiplexer \"${runVAR}\" mit PID \"$pid\""
		kill $pid > /dev/null 2>&1
	fi
		
		((l++))
    done
	
    # allow/deny list Verzeichnisse löschen
	log "$myname" "deleting allow/deny list directories"
	if [ -e "$SmsAllowRxRundir" ]; then
		log "$myname" "  \"$SmsAllowRxRundir\""
		rm -rf "$SmsAllowRxRundir"
	fi
	if [ -e "$SmsAllowTxRundir" ]; then
		log "$myname" "  \"$SmsAllowTxRundir\""
		rm -rf "$SmsAllowTxRundir"
	fi
	if [ -e "$SmsDenyRxRundir" ]; then
		log "$myname" "  \"$SmsDenyRxRundir\""
		rm -rf "$SmsDenyRxRundir"
	fi
	if [ -e "$SmsDenyTxRundir" ]; then
		log "$myname" "  \"$SmsDenyTxRundir\""
		rm -rf "$SmsDenyTxRundir"
	fi
	log "$myname" "done"

    # userdefinierbares Init-Skript beim Stop ausführen
	l=1
	while [ -n "$(eval echo '$'SmsUserinit_${l})" ]; do
		log "$myname" "\"$(eval echo '$'SmsUserinit_${l}) stop\""
		"$(eval echo '$'SmsUserinit_${l})" stop > /dev/null 2>&1
		log "$myname" "\"$(eval echo '$'SmsUserinit_${l}) stop\" done"
		((l++))
	done
	
	log "$myname" "Stop ${myname} abgeschlossen"
    log "$myname" "-------------------------"
    echo "done!"
	
 }

 status_daemon(){
	# Prüfen ob Daemon bereits läuft
	instances=0
	k=1
	while [ -n "$(eval echo '$'SmsTtyToBind_${k}_name)" ]; do
		runVAR="$(eval echo '$'SmsTtyToBind_${k}_name)"
		trxtype="$(eval echo '$'SmsTtyToBind_${k}_trxtype)"
		if ([ -e "${rundir}/${myname}.${trxtype}.rx.${runVAR}.pid" ] || [ -e "${rundir}/${myname}.${trxtype}.tx.${runVAR}.pid" ]); then ((instances++)); fi
		((k++))
	done
	if [ $instances -gt '0' ]; then
		echo "Daemon is running"
	else
		echo "Daemon is not running"
	fi
 }

case "$1" in
  start)
    start_daemon
    ;;
  stop)
    stop_daemon
    ;;
  restart)
     stop_daemon
	 sleep 6
     start_daemon
     ;;
  status)
     status_daemon
     ;;
  *)
     echo "Usage: $0 {start|stop|restart|status}" >&2
     exit 2
esac
exit 0
