#!/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

       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"
}

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 $?