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

# Optional configuration file for nsdc
configfile="/etc/nsd/nsdc.conf"

#
# Default values in absense of ${configfile} (Usually ``/etc/nsd/nsdc.conf'')
#
prefix="/usr/local"
exec_prefix="/usr/local"

sbindir="/usr/local/sbin"
zonesdir="/var/nsd"
flags=""
dbfile="/var/nsd/nsd.db"
zonesfile="/etc/nsd/nsd.zones"
keysdir="/etc/nsd/keys"
notify="/usr/local/sbin/nsd-notify"
nsdxfer="/usr/local/sbin/nsd-xfer"
pidfile="/var/run/nsd.pid"

ZONEC_VERBOSE=-v

#
# Read in configuration file if any
#
if [ -f ${configfile} ]
then
	. ${configfile}
fi

#
# You sure heard this many times before: NO USER SERVICEABLE PARTS BELOW
#
signal() {
	if [ -s ${pidfile} ]
	then
		kill -"$1" `cat ${pidfile}` && return 0
	else
		echo "nsd is not running"
	fi
	return 1
}

case "$1" in
start)
	[ -x ${sbindir}/nsd ] && ${sbindir}/nsd -f ${dbfile} -P ${pidfile} ${flags}
	$0 notify
	;;
stop)
	signal "TERM"
	;;
stats)
	signal "USR1"
	;;
reload)
	signal "HUP"
	$0 notify
	;;
running)
	signal "0"
	;;
rebuild)
	${sbindir}/zonec ${ZONEC_VERBOSE} -d ${zonesdir} -f ${dbfile}.$$ ${zonesfile} && mv ${dbfile}.$$ ${dbfile}
	result=$?
	[ $result != 0 ] && echo "${dbfile} is unmodified"
	rm -f ${dbfile}.$$
	exit ${result}
	;;
update)
	#
	if [ ! -x "${nsdxfer}" ]
	then
		echo "named-xfer program is not available, aborting..."
		exit 1
	fi

	# read the nsd.zones file
	while read zonekw zone file masterskw masters
	do	
		if [ "X$zonekw" = "Xzone" -a "X$masterskw" = "Xmasters" ]
		then
			# now get the serial number
			serial=''
			if [ -e ${zonesdir}/$file ]; then
				serial=`awk '/.*IN[ \t]+SOA.*\($/ { getline; print $1; exit }' ${zonesdir}/$file`
			fi
			serial=${serial:-0}

 			# take care of tsig info file if any
			# See bug #91 - move to ${zone} but be backward
			# compatible
 			unset tsiginfoarg
 			if [ -f "${keysdir}/${masters}.tsiginfo" ]
 			then
 				ln "${keysdir}/${masters}.tsiginfo" "${keysdir}/${masters}.tsiginfo.$$"
 				tsiginfoarg="-T ${keysdir}/${masters}.tsiginfo.$$"
			else 
				if [ -f "${keysdir}/${zone}.tsiginfo" ]
				then
					# the new way of doing things
					ln "${keysdir}/${zone}.tsiginfo" "${keysdir}/${zone}.tsiginfo.$$"
					tsiginfoarg="-T ${keysdir}/${zone}.tsiginfo.$$"
				fi
			fi

			# AXFR to a temp file $file.axfr
			$nsdxfer -z $zone -f ${zonesdir}/$file.axfr ${tsiginfoarg} -s $serial $masters
			if [ $? -eq 1 ]
			then
				if [ -f ${zonesdir}/$file.axfr ]
				then
					# axfr succeeded
					# test compile the zone to see what happens
					${sbindir}/zonec -o ${zone} -f ${zonesdir}/$file.axfr.db - < ${zonesdir}/$file.axfr 2>/dev/null
					if [ $? -eq 1 ]
					then
						echo "Warning: AXFR of $zone did not compile"
						rm -f ${zonesdir}/$file.axfr
					else
						# we succeed
						mv -f ${zonesdir}/$file.axfr ${zonesdir}/$file
					fi
					rm -f ${zonesdir}/$file.axfr.db
			        else
					echo "Warning: AXFR for $zone failed"
				fi
			fi

			# Do we need to rebuild the database?
			if [ ${zonesdir}/$file -nt ${dbfile} ]
			then
				echo "zone $zone needs rebuilding..."
				rebuild="yes"
				export $rebuild
			fi

			# clean up
			rm -f -- "${keysdir}"/*.tsiginfo.*
		fi
	done < $zonesfile

	# Wait for everybody to terminate
	wait

	# Rebuild and reload?
	if [ ! -f ${dbfile} -o "x$rebuild" = "xyes" ]
	then
		echo "rebuilding the database...."
		sh $0 rebuild && sh $0 reload
	fi
	;;
notify)
	if [ ! -x "${notify}" ]
	then
		echo "nsd-notify was not installed on this system"
		exit 1
	fi

	# read the nsd.zones file
	while read zonekw zone file notifykw slaves
	do	
		if [ "X$zonekw" = "Xzone" -a "X$notifykw" = "Xnotify" ]
		then
			$notify -z "$zone" $slaves
		fi
	done < $zonesfile
	;;
restart)
	sh $0 stop && sleep 1 && sh $0 start
	;;
*)
	echo "Usage: `basename $0` {start|stop|reload|rebuild|restart|running|update|notify}" >&2
	;;
esac

exit $?
