#!/bin/sh
# Copyright 2007-2009 Roy Marples
# All rights reserved

# libc subscriber for resolvconf

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

RESOLVCONF="${RESOLVCONF:-resolvconf}"
SYSCONFDIR=/etc
LIBEXECDIR=/lib/resolvconf
VARDIR=/var/run/resolvconf
IFACEDIR="${VARDIR}/interfaces"

# sed may not be available, and this is faster on small files
key_get_value()
{
	local key="$1" value= x= line=

	shift
	if [ $# -eq 0 ]; then
		while read line; do
			case "${line}" in
			"${key}"*) echo "${line##${key}}";;
			esac
		done
	else
		for x; do
			while read line; do
				case "${line}" in
				"${key}"*) echo "${line##${key}}";;
				esac
			done < "${x}"
		done
	fi
}

# Support original resolvconf configuration layout
# as well as the openresolv config file
if [ -f "${SYSCONFDIR}"/resolvconf.conf ]; then
	. "${SYSCONFDIR}"/resolvconf.conf
elif [ -d "${SYSCONFDIR}/resolvconf" ]; then
	SYSCONFDIR="${SYSCONFDIR}/resolvconf/resolv.conf.d"
	base="${SYSCONFDIR}/resolv.conf.d/base"
	if [ -f "${BASE}" ]; then
		name_servers="$(key_get_value "nameserver " "${base}")"
		search_domains="$(key_get_value "search " "${base}")"
		if [ -z "${search_domains}" ]; then
			search_domains="$(key_get_value "domain " "${base}")"
		fi
		resolv_conf_options="$(key_get_value "options " "${base}")"
	fi
	if [ -f "${SYSCONFDIR}"/resolv.conf.d/head ]; then
		resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.d/head)"
	fi
	if [ -f "${SYSCONFDIR}"/resolv.conf.d/tail ]; then
		resolv_conf_tail="$(cat "${SYSCONFDIR}"/resolv.conf.d/tail)"
	fi
fi
resolv_conf="${resolv_conf:-/etc/resolv.conf}"

uniqify()
{
	local result=
	while [ -n "$1" ]; do
		case " ${result} " in
		*" $1 "*);;
		*) result="${result} $1";;
		esac
		shift
	done
	echo "${result# *}"
}

case "${resolv_conf_passthrough:-NO}" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
	newest=
	for conf in "${IFACEDIR}"/*; do
		if [ -z "${newest}" -o "${conf}" -nt "${newest}" ]; then
			newest="${conf}"
		fi
	done
	[ -z "${newest}" ] && exit 0
	newconf="$(cat "${newest}")\n"
	;;
*)
	eval "$(${RESOLVCONF} -v)"
	newsearch="$(uniqify ${search_domains} ${SEARCH})"
	newns="$(uniqify ${name_servers} ${NAMESERVERS})"

	# Hold our new resolv.conf in a variable to save on temporary files
	newconf="# Generated by resolvconf\n"
	if [ -n "${resolv_conf_head}" ]; then
		newconf="${newconf}${resolv_conf_head}\n"
	fi
	[ -n "${newsearch}" ] && newconf="${newconf}search ${newsearch}\n"
	for n in ${newns}; do
		newconf="${newconf}nameserver ${n}\n"
	done

	# Now get any configured options
	opts="${resolv_conf_options}${resolv_conf_options:+ }"
	opts="${opts}$(${RESOLVCONF} -l | key_get_value "options ")"
	if [ -n "${opts}" ]; then
		newconf="${newconf}options"
		for opt in $(uniqify ${opts}); do
			newconf="${newconf} ${opt}"
		done
		newconf="${newconf}\n"
	fi

	if [ -n "{resolv_conf_tail}" ]; then
		newconf="${newconf}${resolv_conf_tail}\n"
	fi
	;;
esac

# Check if the file has actually changed or not
if [ -e "${resolv_conf}" ]; then
	[ "$(cat "${resolv_conf}")" = "$(printf "${newconf}")" ] && exit 0
fi

# Create our resolv.conf now
(umask 022; printf "${newconf}" > "${resolv_conf}")

# Notify users of the resolver
run-parts /etc/hooks/resolv.conf.d

