#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin

. /etc/init.d/functions

# for a chrooted server: "-u bind -t /var/run/named-chroot"
# Don't modify this line, change or create /etc/default/bind9.
OPTIONS=""

test -f /etc/default/rcS && . /etc/default/rcS
test -f /etc/default/bind9 && . /etc/default/bind9

# This function is here because it's possible that /var and / are on different partitions.
is_on_read_only_partition () {
    DIRECTORY=$1
    dir=`readlink -f $DIRECTORY`
    while true; do
	if [ ! -d "$dir" ]; then
	    echo "ERROR: $dir is not a directory"
	    exit 1
	else
	    for flag in `awk -v dir=$dir '{ if ($2 == dir) { print "FOUND"; split($4,FLAGS,",") } }; \
		END { for (f in FLAGS) print FLAGS[f] }' < /proc/mounts`; do
		[ "$flag" = "FOUND" ] && partition="read-write"
		[ "$flag" = "ro" ] && { partition="read-only"; break; }
	    done
	    if [ "$dir" = "/" -o -n "$partition" ]; then
		break
	    else
		dir=`dirname $dir`
	    fi
	fi
    done
    [ "$partition" = "read-only" ] && echo "yes" || echo "no"
}

bind_mount () {
    olddir=$1
    newdir=$2
    mkdir -p $olddir
    cp -a $newdir/* $olddir
    mount --bind $olddir $newdir
}

# Deal with read-only rootfs
if [ "$ROOTFS_READ_ONLY" = "yes" ]; then
    if [ "$ALLOW_ROOTFS_READ_ONLY" = "yes" ]; then
	[ "$VERBOSE" != "no" ] && echo "WARN: start bind service in read-only rootfs"
	[ `is_on_read_only_partition /etc/bind` = "yes" ] && bind_mount /var/volatile/bind/etc /etc/bind
	[ `is_on_read_only_partition /var/named` = "yes" ] && bind_mount /var/volatile/bind/named /var/named
    else
	[ "$VERBOSE" != "no" ] && echo "WARN: read-only rootfs, bind service disabled"
	exit 0
    fi
fi

test -x /usr/sbin/rndc || exit 0

if [ -n "$ROOTDIR" ]; then
    ROOTDIR=`echo $ROOTDIR | sed 's#//*#/#g;s#/$##'`;
    rdl=`/usr/bin/readlink -f $ROOTDIR`;
        if [ -n "$rdl" ]; then
            ROOTDIR="$rdl";
        fi;
fi

ROOTDIR_MOUNT='/etc/bind /var/run/named /var/run/bind /var/cache/bind
/etc/localtime /dev/random /dev/zero /dev/null'

mount_chroot_conf() {
    if [ -n "$ROOTDIR" ]; then
	for all in $ROOTDIR_MOUNT; do
            # Skip nonexistant files
	    [ -e "$all" ] || continue

            # If mount source is a file
	    if ! [ -d "$all" ]; then
                # mount it only if it is not present in chroot or it is empty
		if ! [ -e "$ROOTDIR$all" ] || [ `stat -c'%s' "$ROOTDIR$all"` -eq 0 ]; then
		    touch "$ROOTDIR$all"
		    mount --bind "$all" "$ROOTDIR$all"
		fi
	    else
                # Mount source is a directory. Mount it only if directory in chroot is
                # empty.
		if [ -e "$all" ] && [ `ls -1A $ROOTDIR$all | wc -l` -eq 0 ]; then
		    mount --bind "$all" "$ROOTDIR$all"
		fi
	    fi
	done
    fi
}

umount_chroot_conf() {
    if [ -n "$ROOTDIR" ]; then
	for all in $ROOTDIR_MOUNT; do
            # Check if file is mount target. Do not use /proc/mounts because detecting
            # of modified mounted files can fail.
	    if mount | grep -q '.* on '"$ROOTDIR$all"' .*'; then
		umount "$ROOTDIR$all"
                # Remove temporary created files
		[ -f "$ROOTDIR$all" ] && rm -f "$ROOTDIR$all"
	    fi
	done
    fi
}

rhstatus() {
  [ -x /usr/sbin/rndc ] && /usr/sbin/rndc status;
  status /usr/sbin/named;
  return $?
}

case "$1" in
    start)
	echo -n "Starting domain name service: named"

	modprobe capability >/dev/null 2>&1 || true
	if [ ! -f /etc/bind/rndc.key ]; then
	    /usr/sbin/rndc-confgen -a -b 512 -r /dev/urandom
	    chown 0640 /etc/bind/rndc.key
	    chown root:bind /etc/bind/rndc.key >/dev/null 2>&1 || true
	fi
	if [ -f /var/run/named/named.pid ]; then
	    ps `cat /var/run/named/named.pid` > /dev/null && exit 1
	fi

	if [ ! -x /usr/sbin/named ]; then
	    echo "named binary missing - not starting"
	    exit 1
	fi

	# Handle -c option for chroot jail
	previous_option='unspecified';
	for a in $OPTIONS; do
	    if [ $previous_option = '-c' ]; then
		named_conf=$a;
	    fi;
	    previous_option=$a;
	done;
	named_conf=${named_conf:-/etc/bind/named.conf};

	mount_chroot_conf

	# If named is running in the jail, we should check -c option, make sure
	# it's available for the chrooted server or return a error.  
	if [[ -n $ROOTDIR && ${named_conf:0:${#ROOTDIR}} != $ROOTDIR && \
	      ! -r $ROOTDIR$named_conf ]]; then
	    echo "Cannot find configuration file in jail, put it into $ROOTDIR."
	    exit 6;
	fi;

	if [ -n "${ROOTDIR}" -a "x${ROOTDIR}" != "x/" ]; then
	    OPTIONS="${OPTIONS} -t ${ROOTDIR}"
	fi

	if start-stop-daemon --start --quiet --exec /usr/sbin/named \
		--pidfile /var/run/named/named.pid -- $OPTIONS; then
	    if [ -x /sbin/resolvconf ] ; then
		echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo
	    fi
	fi
	echo "."	
    ;;

    stop)
	echo -n "Stopping domain name service: named"
	if [ -x /sbin/resolvconf ]; then
	    /sbin/resolvconf -d lo
	fi
	/usr/sbin/rndc stop >/dev/null 2>&1
	umount_chroot_conf
	echo "."	
    ;;

    status)
	rhstatus;
	exit $?
    ;;

    reload)
	/usr/sbin/rndc reload
    ;;

    restart|force-reload)
	$0 stop
	sleep 2
	$0 start
    ;;
    
    *)
	echo "Usage: /etc/init.d/bind {start|stop|reload|restart|status|force-reload}" >&2
	exit 1
    ;;
esac

exit 0
