Release openresolv-1.7.1
[openresolv] / resolvconf.in
index bb2e53d08b34d416317c069f1a77d46da0b6cc84..1512c6fd2c7bc49d5ca3fe9e7e3724950e7c844f 100755 (executable)
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ARGV0="$0"
-
-PREFIX=
-RESOLVCONF="${PREFIX}"/etc/resolvconf
-UPDATED="${RESOLVCONF}"/update.d
-VARDIR="${RESOLVCONF}"/run
+SYSCONFDIR=@SYSCONFDIR@
+VARDIR=@VARBASE@/run/resolvconf
 IFACEDIR="${VARDIR}/interfaces"
 
-error_exit() {
+error_exit()
+{
        echo "$*" >&2
        exit 1
 }
 
-usage() {
+usage()
+{
        cat <<-EOF
        Usage: ${ARGV0##*/} [options]
 
@@ -64,19 +63,74 @@ usage() {
        error_exit "$*"
 }
 
-echo_resolv() {
+echo_resolv()
+{
+       local LINE=
        [ -n "$1" -a -e "${IFACEDIR}/$1" ] || return 1
-       echo "# resolv.conf for interface $1"
-       cat "${IFACEDIR}/$1"
+       echo "# resolv.conf from $1"
+       # Our variable maker works of the fact each resolv.conf per interface
+       # is separated by blank lines.
+       # So we remove them when echoing them.
+       while read LINE; do
+               [ -n "${LINE}" ] && echo "${LINE}"
+       done < "${IFACEDIR}/$1"
        echo
 }
 
-uniqify() {
+# Parse resolv.conf's and make variables
+# for domain name servers, search name servers and global nameservers
+parse_resolv()
+{
+       local LINE= NS= DOMAIN= SEARCH= N= NEWDOMAIN= NEWSEARCH= NEWNS=
+
+       echo "NEWDOMAIN="
+       echo "NEWSEARCH="
+       echo "NEWNS="
+
+       while read LINE; do
+               case "${LINE}" in
+               "nameserver "*)
+                       case "${LINE#* }" in
+                       127.*) continue;;
+                       esac
+                       NS="${NS}${LINE#* } "
+                       ;;
+               "domain "*)
+                       [ -z "${SEARCH}" ] && DOMAIN="${LINE#* }"
+                       ;;
+               "search "*)
+                       SEARCH="${LINE#* }"
+                       DOMAIN=
+                       ;;
+               *)
+                       if [ -z "${LINE}" ]; then
+                               for N in ${NS}; do
+                                       if [ -n "${DOMAIN}" ]; then
+                                               echo "NEWDOMAIN=\"\${NEWDOMAIN} ${DOMAIN},${N}\""
+                                       elif [ -n "${SEARCH}" ]; then
+                                               for S in ${SEARCH}; do
+                                                       echo "NEWSEARCH=\"\${NEWSEARCH} ${S},${N}\""
+                                               done
+                                       else
+                                               echo "NEWNS=\"\${NEWNS} ${N}\""
+                                       fi
+                               done
+                               NS=
+                               DOMAIN=
+                               SEARCH=
+                       fi
+                       ;;
+               esac
+       done
+}
+
+uniqify()
+{
     local result=
     while [ -n "$1" ]; do
                case " ${result} " in
-                       *" $1 "*);;
-                       *) result="${result} $1";;
+               *" $1 "*);;
+               *) result="${result} $1";;
                esac
                shift
        done
@@ -86,11 +140,11 @@ uniqify() {
 FORCE=false
 while getopts a:d:fhils:uv OPT; do
        case "${OPT}" in
-               f) FORCE=true;;
-               h) usage;;
-               s) CMD=s; SERVICE="${OPTARG}";;
-               '?') exit 1;;
-               *) CMD="${OPT}"; IFACE="${OPTARG}";;
+       f) FORCE=true;;
+       h) usage;;
+       s) CMD=s; SERVICE="${OPTARG}";;
+       '?') exit 1;;
+       *) CMD="${OPT}"; IFACE="${OPTARG}";;
        esac
 done
 shift $((${OPTIND} - 1))
@@ -110,7 +164,7 @@ if [ "${CMD}" = "s" ]; then
                if [ -s /var/run/"${SERVICE}".pid ]; then
                        kill -0 $(cat /var/run/"${SERVICE}".pid) 2>/dev/null
                elif [ -s /var/run/"${SERVICE}"/"${SERVICE}".pid ]; then
-                       kill -0 $(cat /var/run/"${SERVICE}".pid) 2>/dev/null
+                       kill -0 $(cat /var/run/"${SERVICE}"/"${SERVICE}".pid) 2>/dev/null
                elif [ -s /var/run/"${SERVICE}"/pid ]; then
                        kill -0 $(cat /var/run/"${SERVICE}"/pid) 2>/dev/null
                else
@@ -149,8 +203,8 @@ if [ "${CMD}" = "l" -o "${CMD}" = "i" ]; then
        if [ -n "${ARGS}" ]; then
                LIST="${ARGS}"
                ${FORCE} || REPORT=true
-       elif [ -r "${RESOLVCONF}"/interface-order ]; then
-               LIST="$(cat "${RESOLVCONF}"/interface-order)"
+       elif [ -r "${SYSCONFDIR}"/interface-order ]; then
+               LIST="$(cat "${SYSCONFDIR}"/interface-order)"
        fi
 
        # If we don't have a list then prefer lo, tunnels, ppp
@@ -182,70 +236,38 @@ if [ "${CMD}" = "l" -o "${CMD}" = "i" ]; then
 fi
 
 if [ "${CMD}" = "v" ]; then
-       NS=
-       DOMAIN=
-       SEARCH=
-       NEWSEARCH=
-       NEWNS=
-       NEWDOMAIN=
-       LINES="$("${ARGV0}" -l "${IFACE}" |
-               sed -e "s/'/'\\\\''/g" -e "s/^/'/g" -e "s/$/'/g")"
-       eval set -- ${LINES}
-       for LINE in "$@"; do
-               case "${LINE}" in
-                       "nameserver "*)
-                               case "${LINE#* }" in
-                                       127.*) continue;;
-                               esac
-                               NS="${NS}${LINE#* } "
-                               ;;
-                       "domain "*)
-                               [ -z "${SEARCH}" ] && DOMAIN="${LINE#* }"
-                               ;;
-                       "search "*)
-                               SEARCH="${LINE#* }"
-                               DOMAIN=
-                               ;;
-                       *)
-                               if [ -z "${LINE}" ]; then
-                                       for N in ${NS}; do
-                                               if [ -n "${DOMAIN}" ]; then
-                                                       NEWDOMAIN="${NEWDOMAIN} ${DOMAIN},${N}"
-                                               elif [ -n "${SEARCH}" ]; then
-                                                       for S in ${SEARCH}; do
-                                                               NEWSEARCH="${NEWSEARCH} ${S},${N}"
-                                                       done
-                                               else
-                                                       NEWNS="${NEWNS} ${N}"
-                                               fi
-                                       done
-                                       NS=
-                                       DOMAIN=
-                                       SEARCH=
-                               fi
-                               ;;
-               esac
-       done
+       eval "$("${ARGV0}" -l "${IFACE}" | parse_resolv)"
 
        # Prefer DOMAIN nameservers over SEARCH nameservers
-       # if we are supplied both.
+       # if we are supplied both, but put them in the SEARCH list
        NEWDOMAIN="$(uniqify ${NEWDOMAIN})"
        NEWSEARCH="$(uniqify ${NEWSEARCH})"
        NEWNS="$(uniqify ${NEWNS})"
+       _NEWDOMAIN=
+       _NEWSEARCH=
        for S in ${NEWSEARCH}; do
                for DN in ${NEWDOMAIN}; do
                        if [ "${S%,*}" = "${DN%,*}" ]; then
-                               NEWSEARCH="$(echo "${NEWSEARCH}" |
-                                       sed -e "s/${S}/${DN}/g")"
-                               NEWDOMAIN="$(echo "${NEWDOMAIN}" |
-                                       sed -e "s/${DN}//g")"
+                               S="${DN}"
                                break
                        fi
                done
+               _NEWSEARCH="${_NEWSEARCH}${_NEWSEARCH:+ }${S}"
+       done
+       for DN in ${NEWDOMAIN}; do
+               for S in ${_NEWSEARCH}; do
+                       if [ "${S%,*}" = "${DN%,*}" ]; then
+                               DN=
+                               break
+                       fi
+               done
+               if [ -n "${DN}" ]; then
+                       _NEWDOMAIN="${_NEWDOMAIN}${_NEWDOMAIN:+ }${DN}"
+               fi
        done
 
-       echo "NEWDOMAIN='${NEWDOMAIN}'"
-       echo "NEWSEARCH='${NEWSEARCH}'"
+       echo "NEWDOMAIN='${_NEWDOMAIN}'"
+       echo "NEWSEARCH='${_NEWSEARCH}'"
        echo "NEWNS='${NEWNS}'"
        exit 0
 fi
@@ -262,12 +284,12 @@ fi
 if [ "${CMD}" = "a" ]; then
        for x in '/' \\ ' ' '*'; do
                case "${IFACE}" in
-                       *[${x}]*) error_exit "${x} not allowed in interface name";;
+               *[${x}]*) error_exit "${x} not allowed in interface name";;
                esac
        done
        for x in '.' '-' '~'; do
                case "${IFACE}" in
-                       [${x}]*) error_exit "${x} not allowed at start of interface name";;
+               [${x}]*) error_exit "${x} not allowed at start of interface name";;
                esac
        done
        [ "${CMD}" = "a" -a -t 0 ] && error_exit "No file given via stdin"
@@ -294,7 +316,7 @@ if [ ! -d "${IFACEDIR}" ]; then
                error_exit "Failed to create needed directory ${IFACEDIR}"
 else
        # Delete any existing information about the interface
-       if [ "${CMD}" = "a" -o "${CMD}" = "d" ]; then
+       if [ "${CMD}" = "d" ]; then
                cd "${IFACEDIR}"
                for ARG in ${ARGS}; do
                        if [ "${CMD}" = "d" -a ! -e "${ARG}" ]; then
@@ -307,12 +329,21 @@ else
 fi
 
 if [ "${CMD}" = "a" ]; then
-       # Create our resolv.conf file
-       cat >"${IFACEDIR}"/"${IFACE}" || exit $?
+       # Read resolv.conf from stdin
+       RESOLV="$(cat)\n"
+       # If what we are given matches what we have, then do nothing
+       if [ -e "${IFACEDIR}/${IFACE}" ]; then
+               if [ "$(printf "${RESOLV}")" = "$(cat "${IFACEDIR}/${IFACE}")" ]
+               then
+                       exit 0
+               fi
+               rm "${IFACEDIR}/${IFACE}"
+       fi
+       printf "${RESOLV}" >"${IFACEDIR}/${IFACE}" || exit $?
 fi
 
 RETVAL=0
-for SCRIPT in "${UPDATED}"/*; do
+for SCRIPT in "${SYSCONFDIR}"/update.d/*; do
        if [ -e "${SCRIPT}" ]; then
                "${SCRIPT}" "${CMD}" "${IFACE}"
                RETVAL=$((${RETVAL} + $?))