Re-license as 3 clause BSD as I'm the author. The Gentoo Trustees have been notified...
[openresolv] / libc
1 #!/bin/sh
2 # Copyright 2006 Gentoo Foundation
3 # Copyright 2007 Roy Marples
4 # Distributed under the terms of the GNU General Public License v2
5
6 # libc resolv.conf updater
7
8 # Written by Roy Marples (uberlord@gentoo.org)
9 # Heavily based on Debian resolvconf by Thomas Hood
10
11 PREFIX=
12 RESOLVCONF="${PREFIX}"/etc/resolvconf
13 RESOLVCONFS="$(resolvconf -l)"
14 BASE="${RESOLVCONF}/resolv.conf.d/base"
15
16 uniqify() {
17     local result=
18     while [ -n "$1" ]; do
19                 case " ${result} " in
20                         *" $1 "*) ;;
21                         *) result="${result} $1" ;;
22                 esac
23                 shift
24         done
25     echo "${result# *}"
26 }
27
28 OUR_NS=
29 if [ -e "${BASE}" ]; then
30         OUR_NS="$(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p' "${BASE}")"
31 fi
32 OUR_NS="$(uniqify \
33         ${OUR_NS} \
34         $(echo "${RESOLVCONFS}" \
35         | sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p') \
36 )"
37
38 # libc only allows for 3 nameservers
39 # truncate after 127 as well
40 i=0
41 NS=
42 LOCALH=false
43 for N in ${OUR_NS}; do
44         i=$((${i} + 1))
45         NS="${NS} ${N}"
46         [ "${i}" = "3" ] && break
47         case "${N}" in
48                 127.*) LOCALH=true; break ;;
49         esac
50 done
51
52 # This is nasty!
53 # If we have a local nameserver then assume they are intelligent enough
54 # to be forwarding domain requests to the correct nameserver and not search
55 # ones. This means we prefer search then domain, otherwise, we use them in
56 # the order given to us.
57 OUR_SEARCH=
58 if ${LOCALH} ; then
59         if [ -e "${BASE}" ]; then
60                 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' "${BASE}")"
61         fi
62         OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \
63                 | sed -n 's/^[[:space:]]*search[[:space:]]*//p')"
64         if [ -e "${BASE}" ]; then
65                 OUR_SEARCH="${OUR_SEARCH} $(sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")"
66         fi
67         OUR_SEARCH="${OUR_SEARCH} $( echo "${RESOLVCONFS}" \
68                 | sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p')"
69 else
70         if [ -e "${BASE}" ]; then
71                 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \
72                         -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")"
73         fi
74         OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \
75                 | sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \
76                         -e 's/^[[:space:]]*domain[[:space:]]*//p')"
77 fi
78
79 # libc only allows for 6 search domains 
80 i=0
81 SEARCH=
82 for S in $(uniqify ${OUR_SEARCH}); do
83         i=$((${i} + 1))
84         SEARCH="${SEARCH} ${S}"
85         [ "${i}" = "6" ] && break
86 done
87 [ -n "${SEARCH}" ] && SEARCH="search${SEARCH}"
88
89 # Hold our new resolv.conf in a variable to save on temporary files
90 NEWCONF="# Generated by resolvconf\n"
91 [ -e "${RESOLVCONF}"/resolv.conf.d/head ] \
92         && NEWCONF="${NEWCONF}$(cat "${RESOLVCONF}"/resolv.conf.d/head)\n"
93 [ -n "${SEARCH}" ] && NEWCONF="${NEWCONF}${SEARCH}\n"
94 for N in ${NS}; do
95         NEWCONF="${NEWCONF}nameserver ${N}\n"
96 done
97
98 # Now dump everything else from our resolvs
99 if [ -e "${BASE}" ]; then
100         NEWCONF="${NEWCONF}$(sed -e '/^[[:space:]]*$/d' \
101                 -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \
102                 -e '/^[[:space:]]*search[[:space:]]*.*/d' \
103                 -e '/^[[:space:]]*domain[[:space:]]*.*/d' \
104                 "${BASE}")" 
105 fi
106
107 # We don't know we're using GNU sed, so we do it like this
108 NEWCONF="${NEWCONF}$(echo "${RESOLVCONFS}" | sed -e '/^[[:space:]]*$/d' \
109         -e '/^[[:space:]]*#/d' \
110         -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \
111         -e '/^[[:space:]]*search[[:space:]]*.*/d' \
112         -e '/^[[:space:]]*domain[[:space:]]*.*/d' \
113         )"
114 [ -e "${RESOLVCONF}"/resolv.conf.d/tail ] \
115         && NEWCONF="${NEWCONF}$(cat "${RESOLVCONF}"/resolv.conf.d/tail)"
116
117 # Check if the file has actually changed or not
118 if [ -e "${RESOLVCONF}"/run/resolv.conf ]; then
119         [ "$(cat "${RESOLVCONF}"/run/resolv.conf)" = "$(printf "${NEWCONF}")" ] && exit 0
120 fi
121
122 # Create our resolv.conf now
123 printf "${NEWCONF}" > "${RESOLVCONF}"/run/resolv.conf
124
125 # Restart nscd if it's running
126 if [ -x /etc/init.d/nscd ]; then
127         /etc/init.d/nscd --nodeps --quiet conditionalrestart
128 fi
129 if [ -x /etc/rc.d/nscd ]; then
130         /etc/rc.d/nscd restart
131 fi
132
133 # Notify users of the resolver
134 for x in "${REVOLVCONF}"/update-libc.d/*; do
135         [ -e "${x}" ] && "${x}" "$@"
136 done
137
138 # vim: ts=4 :