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