openresolv no longer applies any semantics to resolv.conf for
[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 # Load our variables from resolvconf
32 eval "$(resolvconf -v)"
33
34 RESOLVCONF=/etc/resolv.conf
35 PREFIX=@PREFIX@
36 SYSCONFDIR=@SYSCONFDIR@
37 BASE="${SYSCONFDIR}/resolv.conf.d/base"
38
39 uniqify()
40 {
41     local result=
42     while [ -n "$1" ]; do
43                 case " ${result} " in
44                 *" $1 "*);;
45                 *) result="${result} $1";;
46                 esac
47                 shift
48         done
49     echo "${result# *}"
50 }
51
52 # sed may not be available, and this is faster on small files
53 key_get_value()
54 {
55         local key="$1" value= x= line=
56
57         shift
58         if [ $# -eq 0 ]; then
59                 while read line; do
60                         case "${line}" in
61                         "${key}"*) echo "${line##${key}}";;
62                         esac
63                 done
64         else
65                 for x; do
66                         while read line; do
67                                 case "${line}" in
68                                 "${key}"*) echo "${line##${key}}";;
69                                 esac
70                         done < "${x}"
71                 done
72         fi
73 }
74
75 NEWNS=
76 NEWSEARCH=
77 if [ -e "${BASE}" ]; then
78         NEWNS="$(key_get_value "nameserver " "${BASE}")"
79         NEWSEARCH="$(key_get_value "search " "${BASE}")"
80         if [ -z "${NEWSEARCH}" ]; then
81                 NEWSEARCH="$(key_get_value "domain " "${BASE}")"
82         fi
83 fi
84 for D in ${DOMAINS}; do
85         NEWSEARCH="${NEWSEARCH} ${D%%:*}"
86         NS="${D#*:}"
87         while [ -n "${NS}" ]; do
88                 NEWNS="${NEWNS} ${NS%%,*}"
89                 [ "${NS}" = "${NS#*,}" ] && break
90                 NS="${NS#*,}"
91         done
92 done
93 NEWSEARCH="$(uniqify ${NEWSEARCH} ${SEARCH})"
94 NEWNS="$(uniqify ${NEWNS} ${NAMESERVERS})"
95
96 # Hold our new resolv.conf in a variable to save on temporary files
97 NEWCONF=""
98 [ -e "${SYSCONFDIR}"/resolv.conf.d/head ] \
99         && NEWCONF="${NEWCONF}$(cat "${SYSCONFDIR}"/resolv.conf.d/head)\n"
100 [ -n "${NEWSEARCH}" ] && NEWCONF="${NEWCONF}search ${NEWSEARCH}\n"
101 for N in ${NEWNS}; do
102         NEWCONF="${NEWCONF}nameserver ${N}\n"
103 done
104
105 # Now get any configured options
106 OPTS=
107 if [ -e "${BASE}" ]; then
108         OPTS="$(key_get_value "options " "${BASE}")"
109 fi
110 OPTS="${OPTS}${OPTS:+ }$(resolvconf -l | key_get_value "options ")"
111 if [ -n "${OPTS}" ]; then
112         NEWCONF="${NEWCONF}options"
113         for OPT in $(uniqify ${OPTS}); do
114                 NEWCONF="${NEWCONF} ${OPT}"
115         done
116         NEWCONF="${NEWCONF}\n"
117 fi
118
119 [ -e "${SYSCONFDIR}"/resolv.conf.d/tail ] \
120         && NEWCONF="${NEWCONF}$(cat "${SYSCONFDIR}"/resolv.conf.d/tail)\n"
121
122 # Check if the file has actually changed or not
123 if [ -e "${RESOLVCONF}" ]; then
124         [ "$(cat "${RESOLVCONF}")" = "$(printf "${NEWCONF}")" ] && exit 0
125 fi
126
127 # Create our resolv.conf now
128 (umask 022; printf "${NEWCONF}" > "${RESOLVCONF}")
129
130 resolvconf -s nscd restart
131 retval=$?
132
133 # Notify users of the resolver
134 for x in "${SYSCONFDIR}"/update-libc.d/*; do
135         if [ -e "${x}" ]; then
136                 "${x}" "$@"
137                 retval=$((${retval} + $?))
138         fi
139 done
140 exit ${retval}