#!/bin/sh

# PROVIDE: vkernel
# REQUIRE: LOGIN

. /etc/rc.subr

name="vkernel"
rcvar=`set_rcvar`

start_cmd="vkernel_start"
stop_cmd="vkernel_stop"

vkernel_start()
{
	echo -n 'Starting virtual kernels:'
	for _vkernel in ${vkernel_list}
	do
		# Start with a clean set of variables
		unset pidfile bin memsize rootimgs ifaces logfile flags
		unset vkuser vkgroup memimg

		# Configure user to run vkernel
		eval vkuser=\"\${vkernel_${_vkernel}_user}\"
		if [ -z "${vkuser}" ]; then
		    vkuser="root"
		    vkgroup="wheel"
		else
		    vkgroup=$(id -ng ${vkuser})
		fi

		# Check if already running
		eval pidfile="/var/run/vkernel.${_vkernel}.pid"
		if [ -f "${pidfile}" ]; then
			eval pid=`cat ${pidfile}`
			if [ ! -z "${pid}" -a ! -z "`ps axwwp ${pid} | grep -wE "^[ ]*${pid}" | grep -v grep | awk '{print $1}'`" ]; then
				echo
				warn "vkernel ${_vkernel} already running? (check ${pidfile})"
				continue
			fi
		else
			# Regular users do not have write access in /var/run
			install -c -o ${vkuser} -g ${vkgroup} /dev/null ${pidfile}
		fi

		# Configure vkernel binary
		eval _bin=\"\${vkernel_${_vkernel}_bin}\"
		if [ -z "${_bin}" -o ! -x "${_bin}" ]; then
			eval _bin=\"\${vkernel_bin}\"
			if [ -z "${_bin}" -o ! -x "${_bin}" ]; then
				echo
				warn "Missing or undefined binary for vkernel '${_vkernel}'. Skipping."
				continue
			fi
		fi
		bin=${_bin}

		# Configure vkernel memory
		eval _memsize=\"\$vkernel_${_vkernel}_memsize\"
		if [ -z "${_memsize}" ]; then
			echo
			warn "No memsize has been defined for vkernel '${_vkernel}'. Skipping."
			continue
		else
			memsize="-m ${_memsize}"
		fi

		# Configure vkernel memory image file
		eval _memimg=\"\${vkernel_${_vkernel}_memimg}\"
		if [ -z "${_memimg}" ]; then
			mkdir -m 1777 -p /var/vkernel

			for n in $(seq 0 999999)
			do
				eval _memf=$(printf "/var/vkernel/memimg.%06s" ${n})
				if [ ! -f "${_memf}" ]
				then
					memimg=" -i ${_memf}"
					break
				else
					if lockf -kst 0 ${_memf} echo >/dev/null
					then
						# Test if memimg is writable by vkuser
						su - ${vkuser} -c "test -w ${_memf}"
						if [ $? -eq 0 ]
						then
							memimg="-i ${_memf}"
							break
						fi
					fi
				fi
			done
		else
			memimg="-i ${_memimg}"
		fi

		# Configure vkernel root image(s)
		eval _rootimgs=\"\${vkernel_${_vkernel}_rootimg_list}\"
		if [ -z "${_rootimgs}" ]; then
			echo
			warn "No root image has been defined for vkernel '${_vkernel}'."
		else
			for _rootimg in ${_rootimgs}
			do
				eval rootimgs=\"${rootimgs} -r ${_rootimg}\"
			done
		fi

		# Configure optional vkernel network interface(s)
		eval _ifaces=\"\${vkernel_${_vkernel}_iface_list}\"
		if [ -n "${_ifaces}" ]; then
			for _iface in ${_ifaces}
			do
				eval ifaces=\"${ifaces} -I ${_iface}\"
			done
		fi

		# Configure optional console logfile
		eval logfile=\"\${vkernel_${_vkernel}_logfile}\"
		[ -z "${logfile}" ] && logfile="/dev/null"

		# Configure optional flags
		eval flags=\"\${vkernel_${_vkernel}_flags}\"

		eval "daemon -u ${vkuser} ${bin} ${memsize} ${rootimgs} " \
		     "${memimg} ${ifaces} ${flags} -p ${pidfile}" \
		     ">>${logfile} 2>&1 </dev/null"
		echo -n " ${_vkernel}"
	done
	echo '.'
}

vkernel_stop()
{
	for _vkernel in ${vkernel_list}
	do
		eval pidfile="/var/run/vkernel.${_vkernel}.pid"
		if [ -f "${pidfile}" ]; then
			eval pid=`cat ${pidfile}`
		fi
		if [ -z "${pid}" ]; then
			warn "vkernel '${_vkernel}' not running?"
			continue
		fi
		eval kill -TERM ${pid}

		eval _kill_timeout=\"\${vkernel_${_vkernel}_kill_timeout}\"
		if [ -z "${_kill_timeout}" ]; then
			eval _kill_timeout=\"\${vkernel_kill_timeout}\"
			if [ -z "${_kill_timeout}" ]; then
				_kill_timeout=60
			fi
		fi

		# Check that the vkernel ended properly
		cnt=1
		eval temp_pid=`ps axwwp ${pid} | grep -wE "^[ ]*${pid}" | grep -v grep | awk '{print $1}'`
		while [ ! -z "${temp_pid}" -a "${cnt}" -lt "${_kill_timeout}" ]; do
			eval temp_pid=`ps axwwp ${pid} | grep -wE "^[ ]*${pid}" | grep -v grep | awk '{print $1}'`
			cnt=`expr $cnt + 1`
			sleep 1
		done

		if [ ! -z "${temp_pid}" ]; then
			eval kill -KILL ${pid}
			warn "'${_vkernel}' had to be forcefully killed."
		fi
	done
}

load_rc_config $name
run_rc_command "$1"
