#!/bin/bash
# Need bash because we use nullglob
#
# Script to update resolv.conf, the libc resolver configuration file,
# and to notify users of the libc resolver of changes
#
# Arguments:
#   -i        initialize
#   -a FOO    interface FOO was added or updated
#   -d FOO    interface FOO was deleted
#
# Assumption: On entry, PWD contains the resolv.conf-type files
#
# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL.
#
# History
# Jun2003-Jan2004: Written by Thomas Hood <jdthood@yahoo.co.uk>

set -e
# 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 -a "$(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

RSLT=""
uniquify()
{
	# Doesn't work properly if items contain whitespace
	RSLT=""
	while [ "$1" ] ; do
		for E in $RSLT ; do
			[ "$1" = "$E" ] && { shift ; continue 2 ; }
		done
		RSLT="${RSLT:+$RSLT }$1"
		shift
	done
}

### Compile ordered list of resolv.conf-type files ###
shopt -s nullglob
uniquify lo* eth* ath* wlan* ppp* *
RSLVCNFFILES="$RSLT"
[ -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[[: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
echo "search $SRCHS" >> "$TMPFILE"
[ "$RSLVCNFFILES" ] && sed -e '/^[[:space:]]*$/d' -e '/^[[:space:]]*#/d' -e '/^[[:space:]]*nameserver[[:space:]]/d' -e '/^[[:space:]]*search[[:space:]]/d' $RSLVCNFFILES >> "$TMPFILE"
[ -f "$TAILFILE" ] && cat "$TAILFILE" >> "$TMPFILE"

### Put 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"
	run-parts "${ETCRESOLVCONF}/update-libc.d"
fi

