#!/bin/sh
#
# Script to update resolv.conf, the libc resolver configuration file,
# and to notify users of the libc resolver of changes
#
# Assumption: On entry, PWD contains the resolv.conf-type files
#
# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL.
#
# History
# June 2003 - June 2004: Written by Thomas Hood <jdthood@yahoo.co.uk>

set -e

[ -x /lib/resolvconf/list-records ] || exit 1

# Set REPORT_ALTERED_SYMLINK=no to inhibit reports that
# /etc/resolv.conf is not the original symbolic link
REPORT_ALTERED_SYMLINK=yes
PATH=/bin:/sbin
ETC=/etc
ETCRESOLVCONF="${ETC}/resolvconf"
RESOLVCONFDIR="${ETCRESOLVCONF}/resolv.conf.d"
BASEFILE="${RESOLVCONFDIR}/base"
HEADFILE="${RESOLVCONFDIR}/head"
TAILFILE="${RESOLVCONFDIR}/tail"
DYNAMICRSLVCNFFILE="${ETCRESOLVCONF}/run/resolv.conf"
TMPFILE="${DYNAMICRSLVCNFFILE}_new.$$"

report_err()
{
	echo "$0: Error: $*" >&2
}

if [ ! -L ${ETC}/resolv.conf ] || [ ! "$(readlink ${ETC}/resolv.conf)" = "$DYNAMICRSLVCNFFILE" ] ; then
	case "$REPORT_ALTERED_SYMLINK" in
		y|Y|yes|YES|Yes)
			report_err "${ETC}/resolv.conf is not a symbolic link to $DYNAMICRSLVCNFFILE"
			;;
	esac
fi

# Stores arguments (minus duplicates) in RSLT, separated by spaces
# Doesn't work properly if an argument itself contain whitespace
uniquify()
{
	RSLT=""
	while [ "$1" ] ; do
		for E in $RSLT ; do
			[ "$1" = "$E" ] && { shift ; continue 2 ; }
		done
		RSLT="${RSLT:+$RSLT }$1"
		shift
	done
}

RSLVCNFFILES="$(/lib/resolvconf/list-records)"

[ -f "$BASEFILE" ] && RSLVCNFFILES="$BASEFILE
$RSLVCNFFILES"

### Compile list of nameservers ###
NMSRVRS=""
if [ "$RSLVCNFFILES" ] ; then
	uniquify $(sed -n 's/^[[:space:]]*nameserver[[:space:]]\+//p' $RSLVCNFFILES)
	NMSRVRS="$RSLT"
fi

### Compile search list ###
SRCHS=""
if [ "$RSLVCNFFILES" ] ; then
	uniquify $(sed -n 's/^[[:space:]]*\(\(search\)\|\(domain\)\)[[:space:]]\+//p' $RSLVCNFFILES)
	SRCHS="$RSLT"
fi

clean_up() { rm -f "$TMPFILE" ; }
trap clean_up EXIT

### Make the file ###
rm -f "$TMPFILE"
: > "$TMPFILE"
[ -f "$HEADFILE" ] && cat "$HEADFILE" >> "$TMPFILE"
for N in $NMSRVRS ; do echo "nameserver $N" >> "$TMPFILE" ; done
[ "$SRCHS" ] && echo "search $SRCHS" >> "$TMPFILE"
[ "$RSLVCNFFILES" ] && sed -e '/^[[:space:]]*$/d' -e '/^[[:space:]]*#/d' -e '/^[[:space:]]*\(\(nameserver\)\|\(search\)\|\(domain\)\)[[:space:]]/d' $RSLVCNFFILES >> "$TMPFILE" 2>/dev/null
[ -f "$TAILFILE" ] && cat "$TAILFILE" >> "$TMPFILE"

### Put the file in place ###
# On init, just put it in place
if [ "$1" = "-i" ] ; then
	mv -f "$TMPFILE" "$DYNAMICRSLVCNFFILE"
	exit 0
fi

# Otherwise update resolv.conf and notify libc resolver users of changes if any
if [ -f "$DYNAMICRSLVCNFFILE" ] && [ "$(cat $TMPFILE)" = "$(cat $DYNAMICRSLVCNFFILE)" ] ; then
	rm -f "$TMPFILE"
else
	mv -f "$TMPFILE" "$DYNAMICRSLVCNFFILE"
	NSCD_RESTARTED=""
	if \
		[ -x /usr/sbin/nscd ] \
		&& [ -x /etc/init.d/nscd ] \
		&& [ -s /etc/nscd.conf ] \
		&& grep -q '[[:space:]]*enable-cache[[:space:]]\+hosts[[:space:]]\+yes' /etc/nscd.conf \
		&& start-stop-daemon --stop --quiet --pidfile=/var/run/nscd.pid --exec /usr/sbin/nscd --retry=TERM/3/HUP/5 \
		&& start-stop-daemon --stop --quiet --oknodo --exec /usr/sbin/nscd --retry=0/5
	then
		/etc/init.d/nscd start && { sleep 0.1 ; NSCD_RESTARTED=yes ; }
	fi
	run-parts ${NSCD_RESTARTED:+--arg="--nscd"} "${ETCRESOLVCONF}/update-libc.d"
fi

