#! /bin/sh
# Copyright (c) 1995-2003 SuSE Linux AG, Nuernberg, Germany
#
# init.d/named
#
### BEGIN INIT INFO
# Provides:       named
# Required-Start: $network $remote_fs $syslog
# Should-Start:   ldap
# Required-Stop:
# Default-Start:  3 5
# Default-Stop:
# Description:    Starts internet domain name server (DNS) BIND
### END INIT INFO

. /etc/rc.status
rc_reset

PATH="/sbin:/usr/sbin:/bin:/usr/bin"
SYSCONFIG_FILE="/etc/sysconfig/named"

if [ "$1" != "stop" ]; then
	for configfile in ${SYSCONFIG_FILE} /etc/named.conf; do
		if [ ! -f ${configfile} ]; then
			echo -n "Name server configuration file ${configfile} does not exist. "
			# Tell the user this has skipped
			rc_status -s
			exit 6
		fi
	done
	. /etc/sysconfig/named
fi

if [ "${NAMED_RUN_CHROOTED}" = "yes" ]; then
	CHROOT_PREFIX="/var/lib/named"
	NAMED_ARGS="${NAMED_ARGS} -t ${CHROOT_PREFIX}"
	NAMED_CHECKCONF_ARGS="-t ${CHROOT_PREFIX}"
else
	CHROOT_PREFIX=""
fi

NAMED_BIN="/usr/sbin/named"
NAMED_CHECKCONF_BIN="/usr/sbin/named-checkconf"
NAMED_CONF_META_INCLUDE_FILE_SCRIPT="/usr/share/bind/createNamedConfInclude"
NAMED_PID="${CHROOT_PREFIX}/var/run/named/named.pid"
NAMED_CONF="/etc/named.conf"
RNDC_BIN="/usr/sbin/rndc"

if [ ! -x ${NAMED_BIN} ] ; then
	echo -n "Name server, ${NAMED_BIN} not installed! "
	# Tell the user this has skipped
	rc_status -s
	exit 5
fi

# Check for NAMED_CONF_META_INCLUDE_FILE or set it to our default if we use
# the NAMED_CONF_META_INCLUDE_FILE_SCRIPT script.
if [ -z "${NAMED_CONF_META_INCLUDE_FILE}" ]; then
	BASENAME_NAMED_CONF_META_INCLUDE_FILE_SCRIPT=$( basename ${NAMED_CONF_META_INCLUDE_FILE_SCRIPT})
	for script in ${NAMED_INITIALIZE_SCRIPTS}; do
		if [ "${script}" = "${BASENAME_NAMED_CONF_META_INCLUDE_FILE_SCRIPT}" -o \
		"${script}" = "${NAMED_CONF_META_INCLUDE_FILE_SCRIPT}" ]; then
			NAMED_CONF_META_INCLUDE_FILE="/etc/named.conf.include"
			break
		fi
	done
fi

function warnMessage()
{
	tput bold
	echo -en "\nWarning: "
	tput sgr0
	echo -e $1
}

function initializeNamed
{
	rc=0
	test "${initializeNamedCalled}" = "yes" && return
	for script in ${NAMED_INITIALIZE_SCRIPTS}; do
		test "${script:0:1}" = "/" || script="/usr/share/bind/${script}"
		${script}
		test $? -ne 0 && rc=$?
	done
	# We want to start each script one time only
	export initializeNamedCalled="yes"
	return ${rc}
}

# Create destination directory in the chroot.
function makeDestDir
{
	if [ ! -d "${CHROOT_PREFIX}/${configfile%/*}" ]; then
		umask 0022
		mkdir -p "${CHROOT_PREFIX}/${configfile%/*}"
	fi
}

# Check if all needed configuration files exist and copy these files relativly
# to the chroot directory if 'named' runs chrooted.
function checkAndCopyConfigFiles
{
	test "${checkAndCopyConfigFilesCalled}" = "yes" && return
	# check for /etc/rndc.key
	if [ ! -f /etc/rndc.key ]; then
		warnMessage "File /etc/rndc.key not found. Creating it. "
		/usr/sbin/rndc-confgen -a -b 512 -r /dev/urandom
		chmod 0640 /etc/rndc.key
		chown root:named /etc/rndc.key
	fi
	# handle include files
	for configfile in "${NAMED_CONF_META_INCLUDE_FILE}" ${NAMED_CONF_INCLUDE_FILES}; do
		# prepend the default include directory if the filename is
		# relative
		test "${configfile:0:1}" = "/" || configfile="/etc/named.d/${configfile}"
		if [ ! -f "${configfile}" ]; then
			case "${configfile}" in
				"${NAMED_CONF_META_INCLUDE_FILE}")
					warnMessage "File, ${configfile} not found.  Creating it. "
					initializeNamed
					;;
				*)
					test -z "${NAMED_CONF_META_INCLUDE_FILE}" && continue
					grep -qe "^[[:space:]]*include[[:space:]]*\"${configfile}\"" "${NAMED_CONF_META_INCLUDE_FILE}" && \
						initializeNamed || \
						warnMessage "File, ${configfile} not found.  Skipping.\nPlease check the setting of NAMED_CONF_INCLUDE_FILES in /etc/sysconfig/named."
					continue
					;;
			esac
		fi
		if [ "${NAMED_RUN_CHROOTED}" = "yes" ]; then
			makeDestDir
			cp -a ${configfile} ${CHROOT_PREFIX}/${configfile%/*}
		fi
	done
	# Handle known configuration files.
	if [ "${NAMED_RUN_CHROOTED}" = "yes" ]; then
		for configfile in /etc/{localtime,named.conf,rndc.key}; do
			if [ ! -e ${configfile} ]; then
				warnMessage "File ${configfile} not found. Skipping. "
				continue
			fi
			makeDestDir
			cp -a ${configfile} ${CHROOT_PREFIX}/${configfile%/*}
		done
	fi
	export checkAndCopyConfigFilesCalled="yes"
}

# Check the syntax of our 'named' configuration.
function namedCheckConf
{
	test "${namedConfChecked}" = "yes" && return
	if ! ${NAMED_CHECKCONF_BIN} ${NAMED_CHECKCONF_ARGS} >/dev/null; then
		checkAndCopyConfigFiles
		if ! ${NAMED_CHECKCONF_BIN} ${NAMED_CHECKCONF_ARGS}; then
			rc_status -s
			rc_failed 6
			rc_exit
		fi
	fi
	export namedConfChecked="yes"
}

case "$1" in
    start)
	echo -n "Starting name server BIND "
	checkproc -p ${NAMED_PID} ${NAMED_BIN}
	case $? in
		0) echo -n "- Warning: named already running! " ;;
		1) echo -n "- Warning: ${NAMED_PID} exists! " ;;
	esac
	checkAndCopyConfigFiles
	namedCheckConf
	initializeNamed
	startproc -p ${NAMED_PID} ${NAMED_BIN} ${NAMED_ARGS} -u named
	rc_status -v
	;;
    stop)
	echo -n "Shutting down name server BIND "
	checkproc -p ${NAMED_PID} ${NAMED_BIN} || echo -n "- Warning: named not running! "
	if ${RNDC_BIN} status &>/dev/null; then
		${RNDC_BIN} stop
	else
		killproc -p ${NAMED_PID} -TERM ${NAMED_BIN}
	fi
	rc=$?

	# let's wait, because
	# 1) trying to start named before it has terminated can leave
	#    us without a running named...
	# 2) making sure that pending updates are written to zone files is good
	#    before trying to modify them externally
	first=0; timeout=30; startDate=$( date +%s)
	while checkproc -p ${NAMED_PID} ${NAMED_BIN}; do
		rc=$?
		if [ ${first} -eq 0 ]; then
			echo -n >&2 " waiting for named to shut down "
			rc_timer_on ${timeout} 63
			first=1
		fi
		if [ $(( $( date +%s) - ${startDate} )) -gt $timeout ]; then
			echo -en >&2 "\nNamed still appears to be running after $timeout seconds, sending SIGTERM"
			killproc -p ${NAMED_PID} -TERM ${NAMED_BIN}
			rc=$?
			break
		fi
		sleep 2
	done
	test ${first} -ne 0 && rc_timer_off

	rc_failed ${rc}
	rc_status -v
	;;
    try-restart)
	namedCheckConf
	$0 status >/dev/null && $0 restart
	rc_status
	;;
    restart)
	namedCheckConf
	# Some of the scripts need a running named.
	$0 status >/dev/null && initializeNamed
	$0 stop
	$0 start
	rc_status
	;;
    force-reload|reload)
	echo -n "Reloading name server BIND "
	checkproc -p ${NAMED_PID} ${NAMED_BIN} || echo "- Warning: named not running! "
	rc=$?
	if [ ${rc} -ne 0 ]; then
		echo "- Warning: named not running! "
	else
		checkAndCopyConfigFiles
		namedCheckConf
		initializeNamed
		${RNDC_BIN} status &>/dev/null
		if [ $? -ne 0 ]; then
			killproc -p ${NAMED_PID} -HUP ${NAMED_BIN}
		else
			${RNDC_BIN} reload
		fi
		rc=$?
	fi
	( exit ${rc} )
	rc_status -v
	;;
    status)
	echo -n "Checking for nameserver BIND "
	${RNDC_BIN} status &>/dev/null
	if [ $? -ne 0 ]; then
		checkproc -p ${NAMED_PID} ${NAMED_BIN}
	else
		echo ""
		${RNDC_BIN} status && echo -en "${esc}[1A"
	fi
	rc_status -v
	;;
    probe)
	rc=0
	for configfile in /etc/{localtime,named.conf,rndc.key} "${NAMED_CONF_META_INCLUDE_FILE}" ${NAMED_CONF_INCLUDE_FILES}; do
		if [ "${configfile}" -nt ${NAMED_PID} ]; then
			rc=1
			break
		fi
	done
	test ${rc} -ne 0 && echo reload
	;;
    *)
	echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
	exit 1
	;;
esac
rc_exit

