All vars should be upper case and descriptive.
[openresolv] / libc.in
1 #!/bin/sh
2 # Copyright 2007-2008 Roy Marples
3 # All rights reserved
4
5 # libc subscriber for resolvconf
6 # You could symlink /etc/resolv.conf to resolvconf/run/resolv.conf
7 # for a read only etc, if resolvconf/run is linked to /var/run/resolvconf.
8
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions
11 # are met:
12 #     * Redistributions of source code must retain the above copyright
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above
15 #       copyright notice, this list of conditions and the following
16 #       disclaimer in the documentation and/or other materials provided
17 #       with the distribution.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 RESOLVCONF=/etc/resolv.conf
32 PREFIX=
33 RESOLVCONFS="$(resolvconf -l)"
34 CONFDIR="${PREFIX}"/etc/resolvconf
35 BASE="${CONFDIR}/resolv.conf.d/base"
36
37 uniqify() {
38     local result=
39     while [ -n "$1" ]; do
40                 case " ${result} " in
41                         *" $1 "*);;
42                         *) result="${result} $1";;
43                 esac
44                 shift
45         done
46     echo "${result# *}"
47 }
48
49 OUR_NS=
50 if [ -e "${BASE}" ]; then
51         OUR_NS="$(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p' "${BASE}")"
52 fi
53 OUR_NS="$(uniqify \
54         ${OUR_NS} \
55         $(echo "${RESOLVCONFS}" \
56         | sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p') \
57 )"
58
59 # libc only allows for 3 nameservers
60 # truncate after 127 as well
61 i=0
62 NS=
63 LOCALH=false
64 for N in ${OUR_NS}; do
65         i=$((${i} + 1))
66         NS="${NS} ${N}"
67         [ "${i}" = "3" ] && break
68         case "${N}" in
69                 127.*) LOCALH=true; break;;
70         esac
71 done
72
73 # This is nasty!
74 # If we have a local nameserver then assume they are intelligent enough
75 # to be forwarding domain requests to the correct nameserver and not search
76 # ones. This means we prefer search then domain, otherwise, we use them in
77 # the order given to us.
78 OUR_SEARCH=
79 if ${LOCALH}; then
80         if [ -e "${BASE}" ]; then
81                 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' "${BASE}")"
82         fi
83         OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \
84                 | sed -n 's/^[[:space:]]*search[[:space:]]*//p')"
85         if [ -e "${BASE}" ]; then
86                 OUR_SEARCH="${OUR_SEARCH} $(sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")"
87         fi
88         OUR_SEARCH="${OUR_SEARCH} $( echo "${RESOLVCONFS}" \
89                 | sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p')"
90 else
91         if [ -e "${BASE}" ]; then
92                 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \
93                         -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")"
94         fi
95         OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \
96                 | sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \
97                         -e 's/^[[:space:]]*domain[[:space:]]*//p')"
98 fi
99
100 # libc only allows for 6 search domains 
101 i=0
102 SEARCH=
103 for S in $(uniqify ${OUR_SEARCH}); do
104         i=$((${i} + 1))
105         SEARCH="${SEARCH} ${S}"
106         [ "${i}" = "6" ] && break
107 done
108 [ -n "${SEARCH}" ] && SEARCH="search${SEARCH}"
109
110 # Hold our new resolv.conf in a variable to save on temporary files
111 NEWCONF="# Generated by resolvconf\n"
112 [ -e "${CONFDIR}"/resolv.conf.d/head ] \
113         && NEWCONF="${NEWCONF}$(cat "${CONFDIR}"/resolv.conf.d/head)\n"
114 [ -n "${SEARCH}" ] && NEWCONF="${NEWCONF}${SEARCH}\n"
115 for N in ${NS}; do
116         NEWCONF="${NEWCONF}nameserver ${N}\n"
117 done
118
119 # Now dump everything else from our resolvs
120 if [ -e "${BASE}" ]; then
121         NEWCONF="${NEWCONF}$(sed -e '/^[[:space:]]*$/d' \
122                 -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \
123                 -e '/^[[:space:]]*search[[:space:]]*.*/d' \
124                 -e '/^[[:space:]]*domain[[:space:]]*.*/d' \
125                 "${BASE}")" 
126 fi
127
128 # We don't know we're using GNU sed, so we do it like this
129 NEWCONF="${NEWCONF}$(echo "${RESOLVCONFS}" | sed -e '/^[[:space:]]*$/d' \
130         -e '/^[[:space:]]*#/d' \
131         -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \
132         -e '/^[[:space:]]*search[[:space:]]*.*/d' \
133         -e '/^[[:space:]]*domain[[:space:]]*.*/d' \
134         )"
135 [ -e "${CONFDIR}"/resolv.conf.d/tail ] \
136         && NEWCONF="${NEWCONF}$(cat "${CONFDIR}"/resolv.conf.d/tail)"
137
138 # Check if the file has actually changed or not
139 if [ -e "${RESOLVCONF}" ]; then
140         [ "$(cat "${RESOLVCONF}")" = "$(printf "${NEWCONF}")" ] && exit 0
141 fi
142
143 # Create our resolv.conf now
144 (umask 022; printf "${NEWCONF}" > "${RESOLVCONF}")
145
146 resolvconf -s nscd restart
147 retval=$?
148
149 # Notify users of the resolver
150 for x in "${CONFDIR}"/update-libc.d/*; do
151         if [ -e "${x}" ]; then
152                 "${x}" "$@"
153                 retval=$((${retval} + $?))
154         fi
155 done
156 exit ${retval}