#!/bin/sh
#
# Start/Stop AvGuard
#
# Copyright 2006 Avira GmbH
#

PATH="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin"

DEVNAME="dazuko"
DAEMONNAME="antivir"
AVDIR="/usr/lib/AntiVir"

DEVFILE="/dev/${DEVNAME}"
DAEMON="${AVDIR}/${DAEMONNAME}"
OS=`uname | env LANG=C LC_ALL=C LC_CTYPE=C tr '[:upper:]' '[:lower:]'`
OSREL="`uname -r`"
KVER="${OS}-${OSREL}"
PROCCMD=""
GUARD_TYPE="server"
STOPTIMEOUT="10"

case "${OS}" in
	sunos)
		ECHO="/usr/lib/AntiVir/echo_sunos"
		if [ ! -x "${ECHO}" ]
		then
			ECHO="echo"
		fi
		STOPTIMEOUT="20"
		;;
	*)
		ECHO="echo"
		;;
esac

startEXIT()
{
	if [ $1 -eq 0 ]
	then
		${ECHO} "."
	fi
	exit $1
}

stopEXIT()
{
	if [ $1 -ne 1 ]
	then
		${ECHO} "."
	fi
	exit $1
}

statusEXIT()
{
	${ECHO} "."
	exit $1
}

tryrestartEXIT()
{
	exit $1
}

restartEXIT()
{
	exit $1
}

forcereloadEXIT()
{
	exit $1
}

reloadEXIT()
{
	exit $1
}

probeEXIT()
{
	exit $1
}

case "${OS}" in
	linux)
		if [ "${OSREL#2.6.}" != "${OSREL}" ]; then
			OS="linux26"
		fi
		;;
esac

case "${OS}" in
	freebsd)
		KMODULE="${AVDIR}/${KVER}/${DEVNAME}.ko"
		;;
	linux26)
		if [ "`uname -a | grep \ SMP\ `" ]; then
			KVER="${KVER}-smp"
		fi
		KMODULE="${AVDIR}/${KVER}/${DEVNAME}.ko"
		;;
	sunos)
		KMODULE="${AVDIR}/${KVER}/${DEVNAME}"
		;;
	darwin)
		KVER="${OS}-`echo ${OSREL} | sed -e 's/\..*//'`"
		DEVNAME="de.antivir.avguard.driver"
		KMODULE="${AVDIR}/${KVER}/DazukoDarwin.kext"
		;;
	*)
		if [ "`uname -a | grep \ SMP\ `" ]; then
			KVER="${KVER}-smp"
		fi
		KMODULE="${AVDIR}/${KVER}/${DEVNAME}.o"
		;;
esac

testPROCCMD()
{
	$PROCCMD > /dev/null 2>&1
}

getPROCESSLIST()
{
	PROCESSLIST=""

	if [ -z "$PROCCMD" ]
	then
		PROCCMD="ps axw -o pid,command"
		testPROCCMD
		if [ $? -ne 0 ]
		then
			PROCCMD="ps -A -o pid,args"
			testPROCCMD
			if [ $? -ne 0 ]
			then
				PROCCMD="ps axw"
			fi
		fi
	fi

	for PROC in `$PROCCMD | grep ${DAEMONNAME}.*--${GUARD_TYPE} | grep -v '\-\-config' | grep -v grep`
	do
		if [ -z "`$ECHO ${PROC} | sed -e s/[0-9]//g`" ]
		then
			PROCESSLIST="${PROCESSLIST} ${PROC}"
		fi
	done
}

getDEV()
{
	case "${OS}" in
		freebsd)
			DEV=`kldstat | grep ${DEVNAME}`
			;;
		sunos)
			DEV=`modinfo | grep ${DEVNAME}`
			;;
		darwin)
			DEV=`kextstat | grep ${DEVNAME}`
			;;
		*)
			DEV=""
			if [ -f "/proc/devices" ]
			then
				DEV=`grep ${DEVNAME} /proc/devices`
			fi
			;;
	esac
}

autoloadModule()
{
	case "${OS}" in
		freebsd)
			kldload ${DEVNAME} > /dev/null 2>&1
			;;
		sunos)
			modload ${KMODULE} > /dev/null 2>&1
			sleep 3
			;;
		darwin)
			kextload ${KMODULE} > /dev/null 2>&1
			;;
		*)
			modprobe ${DEVNAME} > /dev/null 2>&1
			;;
	esac
}

insertModule()
{
	case "${OS}" in
		freebsd)
			kldload ${KMODULE} > /dev/null 2>&1
			;;
		sunos)
			modload ${KMODULE} > /dev/null 2>&1
			sleep 3
			;;
		darwin)
			kextload ${KMODULE} > /dev/null 2>&1
			;;
		*)
			insmod ${KMODULE} > /dev/null 2>&1
			;;
	esac
}

getDEVMAJOR()
{
	case "${OS}" in
		freebsd)
			DEVMAJOR=33
			;;
		*)
			set -- ${DEV}

			DEVMAJOR=${1}
			;;
	esac
}

makeNode()
{
	case "${OS}" in
		freebsd)
			mknod ${DEVFILE} c ${DEVMAJOR} 0
			;;
		sunos)
			# node created automatically for sunos
			;;
		darwin)
			# node created automatically for darwin
			;;
		*)
			mknod -m 600 ${DEVFILE} c ${DEVMAJOR} 0
			;;
	esac
}

case "$1" in
	start)
		${ECHO} -n "Starting AntiVir: avguard-${GUARD_TYPE}"

		# check if AvGuard is already running
		getPROCESSLIST
		if [ ! -z "${PROCESSLIST}" ]
		then
			${ECHO} " (FAILED)"
			${ECHO} " "
			${ECHO} "error: ${DAEMONNAME} is already running"
			${ECHO} " "
			$0 status
			startEXIT 1
		fi
  
 		# get Dazuko device information
 		getDEV
 		if [ -z "${DEV}" ]
  		then
 			# no Dazuko device information, Dazuko is not loaded
 
 			# try to load our own Dazuko module
 
 			# check if our own module is available
 			if [ -f "${KMODULE}" ]
 			then
 				# load our own module
 				insertModule
 			else
 				# try to load a system-installed module
 				autoloadModule
 			fi
 
  			# get Dazuko device information
  			getDEV
  			if [ -z "${DEV}" ]
  			then
 				# no Dazuko device information, there is a problem
  
 				${ECHO} " (FAILED)"
 				${ECHO} " "
 				${ECHO} "error: device ${DEVNAME} not loaded"
 				${ECHO} "Was Dazuko correctly installed?"
 				${ECHO} " "
				startEXIT 1
  			fi
 		fi
  
 		# at this point, Dazuko is loaded
  
 		if [ "${OS}" != "sunos" -a "${OS}" != "darwin" ]
 		then
  			# check if device node is available
  			if [ -c "${DEVFILE}" ]
  			then
				# device node is available, check if it works
				# (we grab 10 bytes because of a bug in Dazuko reading)

				env - dd if=/dev/${DEVNAME} bs=10 count=1 > /dev/null 2>&1
				if [ $? -ne 0 ]
				then
					# unable to read from device, this device node is not correct

					# remove the device node
					rm -f "${DEVFILE}"
				fi
			fi

			# check if we need to create a device node
			if [ ! -c "${DEVFILE}" ]
			then
				# there is no device node, so we need to make one

				# get device major number for Dazuko
				getDEVMAJOR

				# make the device node
				makeNode

				# set permissions on the device node
				chown 0:0 "${DEVFILE}"
				if [ $? -ne 0 ]
				then
					# unable to set permissions? there is a problem

					${ECHO} " (FAILED)"
					${ECHO} " "
					${ECHO} "error: could not create node ${DEVFILE}"
					${ECHO} "Please send a problem description to support@avira.com"
					${ECHO} "Very helpful would be the output of 'uname -a' and the name of"
					${ECHO} "your UNIX distribution."
					${ECHO} " "
					startEXIT 1
				fi
			fi

			# Dazuko is loaded and the device node has been created
		fi

		if [ ! -x "${DAEMON}" ]
		then
			# AvGuard missing

			${ECHO} " (FAILED)"
			${ECHO} " "
			${ECHO} "error: ${DAEMON} missing"
			${ECHO} " "
			startEXIT 5
		fi

		ERROR=0

		# start AvGuard
		${DAEMON} --${GUARD_TYPE}
		if [ $? -ne 0 ]
		then
			ERROR=1
		fi

		# give the AvGuard daemons a chance to "get organized"
		sleep 1

		getPROCESSLIST
		if [ ${ERROR} -ne 0 -o -z "${PROCESSLIST}" ]
		then
			# AvGuard failed to start, there is a problem

			${ECHO} " (FAILED)"
			${ECHO} " "
			${ECHO} "error: ${DAEMON} failed"
			${ECHO} "See log files for details."
			${ECHO} " "
			startEXIT 1
		fi

		startEXIT 0
		;;
	stop)
		${ECHO} -n "Stopping AntiVir: avguard-${GUARD_TYPE}"

		# get Dazuko device information
		# (if Dazuko is not loaded, AvGuard can't be running)
		getDEV
		if [ -z "${DEV}" ]
		then
			stopEXIT 7
		fi

		# Dazuko is loaded

		# find and send TERM signals to all AvGuard processes
		getPROCESSLIST
		for PROC in ${PROCESSLIST}
		do
			kill -TERM ${PROC} > /dev/null 2>&1
		done

		# give the processes a chance to shutdown
		while [ ${STOPTIMEOUT} -gt 0 ]
		do
			getPROCESSLIST
			if [ -z "${PROCESSLIST}" ]
			then
				break
			else
				sleep 1
			fi

			STOPTIMEOUT=`expr ${STOPTIMEOUT} - 1`
		done

		# all AvGuard processes should now be stopped

		# check if there are any AvGuard processes
		getPROCESSLIST
		if [ ! -z "${PROCESSLIST}" ]
		then
			# there are still processes running? this may be a problem

			${ECHO} " (FAILED)"
			${ECHO} " "
			${ECHO} "There may be processes still running."
			${ECHO} " "
			stopEXIT 1
		fi

		stopEXIT 0
		;;
	status)
		${ECHO} -n "AntiVir Status: avguard-${GUARD_TYPE} "

		# get Dazuko device information
		getDEV
		if [ -z "${DEV}" ]
		then
			# Dazuko is not loaded

			${ECHO} -n "(Dazuko unavailable, 0 daemons)"
			statusEXIT 3
		else
			# Dazuko is loaded

			# count how many AvGuard processes we find
			COUNT=0
			getPROCESSLIST
			for PROC in ${PROCESSLIST}
			do
				COUNT=`expr ${COUNT} + 1`
			done

			# display the results of what we found
			if [ ${COUNT} -ge 1 ]
			then
				${ECHO} -n "(Dazuko available, ${COUNT} daemons)"
				statusEXIT 0
			else
				${ECHO} -n "(Dazuko available, 0 daemons)"
				statusEXIT 3
			fi
		fi
		;;
	try-restart|condrestart)
		if [ "$1" = "condrestart" ]
		then
			${ECHO} "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
		fi
		$0 status
		if [ $? -eq 0 ]
		then
			$0 restart
			tryrestartEXIT $?
		else
			tryrestartEXIT 0
		fi
		;;
	restart)
		$0 stop
		$0 start
		restartEXIT $?
		;;
	force-reload)
		$0 try-restart
		forcereloadEXIT $?
		;;
	reload)
		${ECHO} "${attn} reload not available, please use restart${norm}"
		reloadEXIT 3
		;;
	probe)
		${ECHO} restart
		probeEXIT 0
		;;
	*)
		${ECHO} "usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
		exit 1
		;;
esac

