#!/bin/sh
#
# nsdc.sh -- a shell script to manage the beast
#
# Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
#
# See LICENSE for the license.
#
# (numbers are runlevels startpriority killpriority).

# chkconfig: 2345 45 74
# description: NSD, authoritative only high performance name server.

# configuration file default
configfile="/etc/nsd.conf"

# The directory where NSD binaries reside
sbindir="/usr/sbin"

#
# You sure heard this many times before: NO USER SERVICEABLE PARTS BELOW
#

# see if user selects a different config file, with -c <filename>
if test "x$1" = "x-c"; then
	shift
	if [ -e $1 ]; then
		configfile=$1
		shift
	else
		echo "`basename $0`: Config file "$1" does not exist."
		exit 1
	fi
fi

# locate nsd-checkconf : in sbindir, PATH, nsdc_dir or .
nsd_checkconf=""
if [ -e ${sbindir}/nsd-checkconf ]; then
	nsd_checkconf=${sbindir}/nsd-checkconf
else
	if which nsd-checkconf >/dev/null 2>&1 ; then
		if which nsd-checkconf 2>&1 | grep "^[Nn]o " >/dev/null; then
			nsd_checkconf=""
		else
			nsd_checkconf=`which nsd-checkconf`
		fi
	fi
	if [ -z "${nsd_checkconf}" -a -e `dirname $0`/nsd-checkconf ]; then
		nsd_checkconf=`dirname $0`/nsd-checkconf
	fi
	if [ -z "${nsd_checkconf}" -a -e ./nsd-checkconf ]; then
		nsd_checkconf=./nsd-checkconf
	fi
	if [ -z "${nsd_checkconf}" ]; then
		echo "`basename $0`: Could not find nsd programs" \
			"in $sbindir, in PATH=$PATH, in cwd=`pwd`," \
			"or in dir of nsdc=`dirname $0`"
		exit 1
	fi
fi

usage() {
	echo "Usage: `basename $0` [-c configfile] {start|stop|reload|restart|"
	echo "				running}"
	echo "options:"
	echo "	-c configfile	Use specified configfile (default: @nsdconfigfile@)."
	echo "commands:"
	echo "	start		Start nsd server."
	echo "	stop		Stop nsd server."
	echo "	reload		Nsd server reloads database file."
	echo "	restart		Stop the nsd server and start it again."
	echo "	running		Prints message and exit nonzero if server not running."
}

# check the config syntax before using it
${nsd_checkconf} ${configfile}
if test $? -ne 0 ; then
	usage
	exit 1
fi

# Read some settings from the config file.
pidfile=`${nsd_checkconf} -o pidfile ${configfile}`
zonesdir=`${nsd_checkconf} -o zonesdir ${configfile}`
sbindir=`dirname ${nsd_checkconf}`

# move to zonesdir (if specified), and make absolute pathnames.
if test -n "${zonesdir}"; then
       zonesdir=`dirname ${zonesdir}/.`
       if echo "${zonesdir}" | grep "^[^/]" >/dev/null; then
               zonesdir=`pwd`/${zonesdir}
       fi
       if echo "${pidfile}" | grep "^[^/]" >/dev/null; then
               pidfile=${zonesdir}/${pidfile}
       fi
fi

# for bash: -C or noclobber. For tcsh: noclobber. For bourne: -C.
noclobber_set="set -C"
# ugly check for tcsh
if echo @shell@ | grep tcsh >/dev/null; then
	noclobber_set="set noclobber"
fi

#
# useful routines
#
signal() {
	if [ -s ${pidfile} ]
	then
		kill -"$1" `cat ${pidfile}` && return 0
	else
		echo "nsd is not running"
	fi
	return 1
}

do_start() {
	if test -x ${sbindir}/nsd; then
		${sbindir}/nsd -c ${configfile}
		test $? = 0 || (echo "nsd startup failed."; exit 1)
	else
		echo "${sbindir}/nsd not an executable file, nsd startup failed."; exit 1
	fi
}

controlled_sleep() {
	if [ $1 -ge 25 ]; then
		sleep 1
	fi
}

controlled_stop() {
	pid=$1
	try=1

	while [ $try -ne 0 ]; do
		if [ ${try} -gt 50 ]; then
			echo "nsdc stop failed"
			return 1
		else
			if [ $try -eq 1 ]; then
				kill -TERM ${pid}
			else
				kill -TERM ${pid} >/dev/null 2>&1
			fi

			# really stopped?
			kill -0 ${pid} >/dev/null 2>&1
			if [ $? -eq 0 ]; then
				controlled_sleep ${try}
				try=`expr ${try} + 1`
			else
				try=0
			fi
		fi
	done
	rm -f ${pidfile}

	return 0
}

do_controlled_stop() {
	if [ -s ${pidfile} ]; then
		pid=`cat ${pidfile}`
		controlled_stop ${pid} && return 0
	else
		echo "nsd is not running, starting anyway" && return 0
	fi
	return 1
}

do_stop() {
	signal "TERM"
	rm -f ${pidfile}
}

do_reload() {
	signal "HUP"
}

case "$1" in
start)
	if test -s ${pidfile} && kill -"0" `cat ${pidfile}` 
	then
		(echo "process `cat ${pidfile}` exists, please use restart"; exit 1)
	else
		do_start
	fi
	;;
stop)
	do_stop
	;;
stats)
	signal "USR1"
	;;
reload)
	do_reload
	;;
running)
	signal "0"
	;;
restart)
	do_controlled_stop && do_start
	;;
*)
	usage
	;;
esac

exit $?
