1if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1 2# 3# Copyright (c) 2006-2013 Devin Teske 4# All Rights Reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26#
| 1if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1 2# 3# Copyright (c) 2006-2013 Devin Teske 4# All Rights Reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26#
|
28# 29############################################################ INCLUDES 30 31BSDCFG_SHARE="/usr/share/bsdconfig" 32. $BSDCFG_SHARE/common.subr || exit 1 33f_dprintf "%s: loading includes..." networking/resolv.subr 34f_include $BSDCFG_SHARE/dialog.subr 35f_include $BSDCFG_SHARE/strings.subr 36f_include $BSDCFG_SHARE/media/tcpip.subr 37f_include $BSDCFG_SHARE/networking/common.subr 38f_include $BSDCFG_SHARE/networking/ipaddr.subr 39 40BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking" 41f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr 42 43############################################################ CONFIGURATION 44 45# 46# When updating resolv.conf(5), should we populate the `search' directive with 47# all possible sub-domains? In example, if the domain is "sub.domain.com", when 48# the below option is set to 1, include both "sub.domain.com" and "domain.com" 49# in the `search' directive, otherwise use only "sub.domain.com". 50# 51# When enabled (set to 1), specify the minimum number of dots required for each 52# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'. 53# 54: ${RESOLVER_SEARCH_DOMAINS_ALL:=1} 55: ${RESOLVER_SEARCH_NDOTS:=1} 56 57############################################################ FUNCTIONS 58 59# f_resolv_conf_domain 60# 61# Returns the domain configured in resolv.conf(5). 62# 63f_resolv_conf_domain() 64{ 65 tail -r "$RESOLV_CONF" 2> /dev/null | awk \ 66 ' 67 BEGIN { found = 0 } 68 ( tolower($1) == "domain" ) \ 69 { 70 print $2 71 found = 1 72 exit 73 } 74 END { exit ! found } 75 ' 76} 77 78# f_resolv_conf_search 79# 80# Returns the search configured in resolv.conf(5). 81# 82f_resolv_conf_search() 83{ 84 tail -r "$RESOLV_CONF" 2> /dev/null | awk \ 85 ' 86 BEGIN { found = 0 } 87 { 88 tl0 = tolower($0) 89 if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) { 90 search = substr($0, RLENGTH + 1) 91 sub(/[[:space:]]*#.*$/, "", search) 92 gsub(/[[:space:]]+/, " ", search) 93 print search 94 found = 1 95 exit 96 } 97 } 98 END { exit ! found } 99 ' 100} 101 102# f_dialog_resolv_conf_update $hostname 103# 104# Updates the search/domain directives in resolv.conf(5) given a valid fully- 105# qualified hostname. 106# 107# This function is a two-parter. Below is the awk(1) portion of the function, 108# afterward is the sh(1) function which utilizes the below awk script. 109# 110f_dialog_resolv_conf_update_awk=' 111# Variables that should be defined on the invocation line: 112# -v domain="domain" 113# -v search_all="0|1" 114# -v search_ndots="1+" 115# 116BEGIN { 117 domain_found = search_found = 0 118 119 if ( search_all ) { 120 search = "" 121 subdomain = domain 122 if ( search_ndots < 1 ) 123 search_ndots = 1 124 125 ndots = split(subdomain, labels, ".") - 1 126 while ( ndots-- >= search_ndots ) { 127 if ( length(search) ) search = search " " 128 search = search subdomain 129 sub(/[^.]*\./, "", subdomain) 130 } 131 } 132 else search = domain 133} 134{ 135 if ( domain_found && search_found ) { print; next } 136 137 tl0 = tolower($0) 138 if ( ! domain_found && \ 139 match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \ 140 { 141 if ( length(domain) ) { 142 printf "%s%s\n", substr($0, 0, RLENGTH), domain 143 domain_found = 1 144 } 145 } 146 else if ( ! search_found && \ 147 match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \ 148 { 149 if ( length(search) ) { 150 printf "%s%s\n", substr($0, 0, RLENGTH), search 151 search_found = 1 152 } 153 } 154 else print 155} 156END { 157 if ( ! search_found && length(search) ) 158 printf "search\t%s\n", search 159 if ( ! domain_found && length(domain) ) 160 printf "domain\t%s\n", domain 161} 162' 163f_dialog_resolv_conf_update() 164{ 165 local hostname="$1" 166 167 # 168 # Extrapolate the desired domain search parameter for resolv.conf(5) 169 # 170 local search ndots domain="${hostname#*.}" 171 if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then 172 search="" 173 ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) ) 174 while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do 175 search="$search${search:+ }$domain" 176 domain="${domain#*.}" 177 ndots=$(( $ndots - 1 )) 178 done 179 domain="${hostname#*.}" 180 else 181 search="$domain" 182 fi 183 184 # 185 # Save domain/search information only if different from resolv.conf(5) 186 # 187 if [ "$domain" != "$( f_resolv_conf_domain )" -o \ 188 "$search" != "$( f_resolv_conf_search )" ] 189 then 190 f_dialog_info "Saving new domain/search settings" \ 191 "to resolv.conf(5)..." 192 193 # 194 # Create a new temporary file to write our resolv.conf(5) 195 # update with our new `domain' and `search' directives. 196 # 197 local tmpfile="$( mktemp -t "$pgm" )" 198 [ "$tmpfile" ] || return $FAILURE 199 200 # 201 # Fixup permissions and ownership (mktemp(1) creates the 202 # temporary file with 0600 permissions -- change the 203 # permissions and ownership to match resolv.conf(5) before 204 # we write it out and mv(1) it into place). 205 # 206 local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )" 207 local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )" 208 f_quietly chmod "${mode:-0644}" "$tmpfile" 209 f_quietly chown "${owner:-root:wheel}" "$tmpfile" 210 211 # 212 # Operate on resolv.conf(5), replacing only the last 213 # occurrences of `domain' and `search' directives (or add 214 # them to the top if not found), in strict-adherence to the 215 # following entry in resolver(5): 216 # 217 # The domain and search keywords are mutually exclusive. 218 # If more than one instance of these keywords is present, 219 # the last instance will override. 220 # 221 # NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the 222 # environment, all sub-domains will be added to the `search' 223 # directive, not just the FQDN. 224 # 225 local domain="${hostname#*.}" new_contents 226 [ "$domain" = "$hostname" ] && domain= 227 new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null ) 228 new_contents=$( echo "$new_contents" | awk \ 229 -v domain="$domain" \ 230 -v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \ 231 -v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \ 232 "$f_dialog_resolv_conf_update_awk" ) 233 234 # 235 # Write the temporary file contents and move the temporary 236 # file into place. 237 # 238 echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 239 f_quietly mv "$tmpfile" "$RESOLV_CONF" 240 241 fi 242} 243 244# f_dialog_input_nameserver [ $n $nameserver ] 245# 246# Allows the user to edit a given nameserver. The first argument is the 247# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one 248# if editing the first nameserver instance, two if editing the second, three if 249# the third, ad nauseum. If this argument is zero, null, or missing, the value 250# entered by the user (if non-null) will be added to resolv.conf(5) as a new 251# `nameserver' entry. The second argument is the IPv4 address of the nameserver 252# to be edited -- this will be displayed as the initial value during the edit. 253# 254# Taint-checking is performed when editing an existing entry (when the second 255# argument is one or higher) in that the first argument must match the current 256# value of the Nth `nameserver' instance in resolv.conf(5) else an error is 257# generated discarding any/all changes. 258# 259# This function is a two-parter. Below is the awk(1) portion of the function, 260# afterward is the sh(1) function which utilizes the below awk script. 261# 262f_dialog_input_nameserver_edit_awk=' 263# Variables that should be defined on the invocation line: 264# -v nsindex="1+" 265# -v old_value="..." 266# -v new_value="..." 267# 268BEGIN { 269 if ( nsindex < 1 ) exit 1 270 found = n = 0 271} 272{ 273 if ( found ) { print; next } 274 275 if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) { 276 if ( ++n == nsindex ) { 277 if ( $2 != old_value ) exit 2 278 if ( new_value != "" ) printf "%s%s\n", \ 279 substr($0, 0, RLENGTH), new_value 280 found = 1 281 } 282 else print 283 } 284 else print 285} 286END { if ( ! found ) exit 3 } 287' 288f_dialog_input_nameserver() 289{ 290 local index="${1:-0}" old_ns="$2" new_ns 291 local ns="$old_ns" 292 293 # 294 # Perform sanity checks 295 # 296 f_isinteger "$index" || return $FAILURE 297 [ $index -ge 0 ] || return $FAILURE 298 299 local msg 300 if [ $index -gt 0 ]; then 301 if [ "$USE_XDIALOG" ]; then 302 msg="$xmsg_please_enter_nameserver_existing" 303 else 304 msg="$msg_please_enter_nameserver_existing" 305 fi 306 else 307 msg="$msg_please_enter_nameserver" 308 fi 309 310 # 311 # Loop until the user provides taint-free input. 312 # 313 while :; do 314 f_dialog_input new_ns "$msg" "$ns" \ 315 "$hline_num_punc_tab_enter" || return 316 317 # Take only the first "word" of the user's input 318 new_ns="${new_ns%%[$IFS]*}" 319 320 # Taint-check the user's input 321 [ "$new_ns" ] || break 322 f_dialog_validate_ipaddr "$new_ns" && break 323 324 # Update prompt to allow user to re-edit previous entry 325 ns="$new_ns" 326 done 327 328 # 329 # Save only if the user changed the nameserver. 330 # 331 if [ $index -eq "0" -a "$new_ns" ]; then 332 f_dialog_info "$msg_saving_nameserver" 333 printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF" 334 return $SUCCESS 335 elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then 336 if [ "$new_ns" ]; then 337 msg="$msg_saving_nameserver_existing" 338 else 339 msg="$msg_removing_nameserver" 340 fi 341 f_dialog_info "$msg" 342 343 # 344 # Create a new temporary file to write our new resolv.conf(5) 345 # 346 local tmpfile="$( mktemp -t "$pgm" )" 347 [ "$tmpfile" ] || return $FAILURE 348 349 # 350 # Quietly fixup permissions and ownership 351 # 352 local mode owner 353 mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null ) 354 owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null ) 355 f_quietly chmod "${mode:-0644}" "$tmpfile" 356 f_quietly chown "${owner:-root:wheel}" "$tmpfile" 357 358 # 359 # Operate on resolv.conf(5) 360 # 361 local new_contents 362 new_contents=$( awk -v nsindex="$index" \ 363 -v old_value="$old_ns" \ 364 -v new_value="$new_ns" \ 365 "$f_dialog_input_nameserver_edit_awk" \ 366 "$RESOLV_CONF" ) 367 368 # 369 # Produce an appropriate error message if necessary. 370 # 371 local retval=$? 372 case $retval in 373 1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex";; 374 2) f_dialog_msgbox "$msg_resolv_conf_changed_while_editing" 375 return $retval;; 376 3) f_dialog_msgbox "$msg_resolv_conf_entry_no_longer_exists" 377 return $retval;; 378 esac 379 380 # 381 # Write the temporary file contents and move the temporary 382 # file into place. 383 # 384 echo "$new_contents" > "$tmpfile" || return $FAILURE 385 f_quietly mv "$tmpfile" "$RESOLV_CONF" 386 fi 387} 388 389# f_dialog_menu_nameservers 390# 391# Edit the nameservers in resolv.conf(5). 392# 393f_dialog_menu_nameservers() 394{
| 28# 29############################################################ INCLUDES 30 31BSDCFG_SHARE="/usr/share/bsdconfig" 32. $BSDCFG_SHARE/common.subr || exit 1 33f_dprintf "%s: loading includes..." networking/resolv.subr 34f_include $BSDCFG_SHARE/dialog.subr 35f_include $BSDCFG_SHARE/strings.subr 36f_include $BSDCFG_SHARE/media/tcpip.subr 37f_include $BSDCFG_SHARE/networking/common.subr 38f_include $BSDCFG_SHARE/networking/ipaddr.subr 39 40BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking" 41f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr 42 43############################################################ CONFIGURATION 44 45# 46# When updating resolv.conf(5), should we populate the `search' directive with 47# all possible sub-domains? In example, if the domain is "sub.domain.com", when 48# the below option is set to 1, include both "sub.domain.com" and "domain.com" 49# in the `search' directive, otherwise use only "sub.domain.com". 50# 51# When enabled (set to 1), specify the minimum number of dots required for each 52# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'. 53# 54: ${RESOLVER_SEARCH_DOMAINS_ALL:=1} 55: ${RESOLVER_SEARCH_NDOTS:=1} 56 57############################################################ FUNCTIONS 58 59# f_resolv_conf_domain 60# 61# Returns the domain configured in resolv.conf(5). 62# 63f_resolv_conf_domain() 64{ 65 tail -r "$RESOLV_CONF" 2> /dev/null | awk \ 66 ' 67 BEGIN { found = 0 } 68 ( tolower($1) == "domain" ) \ 69 { 70 print $2 71 found = 1 72 exit 73 } 74 END { exit ! found } 75 ' 76} 77 78# f_resolv_conf_search 79# 80# Returns the search configured in resolv.conf(5). 81# 82f_resolv_conf_search() 83{ 84 tail -r "$RESOLV_CONF" 2> /dev/null | awk \ 85 ' 86 BEGIN { found = 0 } 87 { 88 tl0 = tolower($0) 89 if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) { 90 search = substr($0, RLENGTH + 1) 91 sub(/[[:space:]]*#.*$/, "", search) 92 gsub(/[[:space:]]+/, " ", search) 93 print search 94 found = 1 95 exit 96 } 97 } 98 END { exit ! found } 99 ' 100} 101 102# f_dialog_resolv_conf_update $hostname 103# 104# Updates the search/domain directives in resolv.conf(5) given a valid fully- 105# qualified hostname. 106# 107# This function is a two-parter. Below is the awk(1) portion of the function, 108# afterward is the sh(1) function which utilizes the below awk script. 109# 110f_dialog_resolv_conf_update_awk=' 111# Variables that should be defined on the invocation line: 112# -v domain="domain" 113# -v search_all="0|1" 114# -v search_ndots="1+" 115# 116BEGIN { 117 domain_found = search_found = 0 118 119 if ( search_all ) { 120 search = "" 121 subdomain = domain 122 if ( search_ndots < 1 ) 123 search_ndots = 1 124 125 ndots = split(subdomain, labels, ".") - 1 126 while ( ndots-- >= search_ndots ) { 127 if ( length(search) ) search = search " " 128 search = search subdomain 129 sub(/[^.]*\./, "", subdomain) 130 } 131 } 132 else search = domain 133} 134{ 135 if ( domain_found && search_found ) { print; next } 136 137 tl0 = tolower($0) 138 if ( ! domain_found && \ 139 match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \ 140 { 141 if ( length(domain) ) { 142 printf "%s%s\n", substr($0, 0, RLENGTH), domain 143 domain_found = 1 144 } 145 } 146 else if ( ! search_found && \ 147 match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \ 148 { 149 if ( length(search) ) { 150 printf "%s%s\n", substr($0, 0, RLENGTH), search 151 search_found = 1 152 } 153 } 154 else print 155} 156END { 157 if ( ! search_found && length(search) ) 158 printf "search\t%s\n", search 159 if ( ! domain_found && length(domain) ) 160 printf "domain\t%s\n", domain 161} 162' 163f_dialog_resolv_conf_update() 164{ 165 local hostname="$1" 166 167 # 168 # Extrapolate the desired domain search parameter for resolv.conf(5) 169 # 170 local search ndots domain="${hostname#*.}" 171 if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then 172 search="" 173 ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) ) 174 while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do 175 search="$search${search:+ }$domain" 176 domain="${domain#*.}" 177 ndots=$(( $ndots - 1 )) 178 done 179 domain="${hostname#*.}" 180 else 181 search="$domain" 182 fi 183 184 # 185 # Save domain/search information only if different from resolv.conf(5) 186 # 187 if [ "$domain" != "$( f_resolv_conf_domain )" -o \ 188 "$search" != "$( f_resolv_conf_search )" ] 189 then 190 f_dialog_info "Saving new domain/search settings" \ 191 "to resolv.conf(5)..." 192 193 # 194 # Create a new temporary file to write our resolv.conf(5) 195 # update with our new `domain' and `search' directives. 196 # 197 local tmpfile="$( mktemp -t "$pgm" )" 198 [ "$tmpfile" ] || return $FAILURE 199 200 # 201 # Fixup permissions and ownership (mktemp(1) creates the 202 # temporary file with 0600 permissions -- change the 203 # permissions and ownership to match resolv.conf(5) before 204 # we write it out and mv(1) it into place). 205 # 206 local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )" 207 local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )" 208 f_quietly chmod "${mode:-0644}" "$tmpfile" 209 f_quietly chown "${owner:-root:wheel}" "$tmpfile" 210 211 # 212 # Operate on resolv.conf(5), replacing only the last 213 # occurrences of `domain' and `search' directives (or add 214 # them to the top if not found), in strict-adherence to the 215 # following entry in resolver(5): 216 # 217 # The domain and search keywords are mutually exclusive. 218 # If more than one instance of these keywords is present, 219 # the last instance will override. 220 # 221 # NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the 222 # environment, all sub-domains will be added to the `search' 223 # directive, not just the FQDN. 224 # 225 local domain="${hostname#*.}" new_contents 226 [ "$domain" = "$hostname" ] && domain= 227 new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null ) 228 new_contents=$( echo "$new_contents" | awk \ 229 -v domain="$domain" \ 230 -v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \ 231 -v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \ 232 "$f_dialog_resolv_conf_update_awk" ) 233 234 # 235 # Write the temporary file contents and move the temporary 236 # file into place. 237 # 238 echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 239 f_quietly mv "$tmpfile" "$RESOLV_CONF" 240 241 fi 242} 243 244# f_dialog_input_nameserver [ $n $nameserver ] 245# 246# Allows the user to edit a given nameserver. The first argument is the 247# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one 248# if editing the first nameserver instance, two if editing the second, three if 249# the third, ad nauseum. If this argument is zero, null, or missing, the value 250# entered by the user (if non-null) will be added to resolv.conf(5) as a new 251# `nameserver' entry. The second argument is the IPv4 address of the nameserver 252# to be edited -- this will be displayed as the initial value during the edit. 253# 254# Taint-checking is performed when editing an existing entry (when the second 255# argument is one or higher) in that the first argument must match the current 256# value of the Nth `nameserver' instance in resolv.conf(5) else an error is 257# generated discarding any/all changes. 258# 259# This function is a two-parter. Below is the awk(1) portion of the function, 260# afterward is the sh(1) function which utilizes the below awk script. 261# 262f_dialog_input_nameserver_edit_awk=' 263# Variables that should be defined on the invocation line: 264# -v nsindex="1+" 265# -v old_value="..." 266# -v new_value="..." 267# 268BEGIN { 269 if ( nsindex < 1 ) exit 1 270 found = n = 0 271} 272{ 273 if ( found ) { print; next } 274 275 if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) { 276 if ( ++n == nsindex ) { 277 if ( $2 != old_value ) exit 2 278 if ( new_value != "" ) printf "%s%s\n", \ 279 substr($0, 0, RLENGTH), new_value 280 found = 1 281 } 282 else print 283 } 284 else print 285} 286END { if ( ! found ) exit 3 } 287' 288f_dialog_input_nameserver() 289{ 290 local index="${1:-0}" old_ns="$2" new_ns 291 local ns="$old_ns" 292 293 # 294 # Perform sanity checks 295 # 296 f_isinteger "$index" || return $FAILURE 297 [ $index -ge 0 ] || return $FAILURE 298 299 local msg 300 if [ $index -gt 0 ]; then 301 if [ "$USE_XDIALOG" ]; then 302 msg="$xmsg_please_enter_nameserver_existing" 303 else 304 msg="$msg_please_enter_nameserver_existing" 305 fi 306 else 307 msg="$msg_please_enter_nameserver" 308 fi 309 310 # 311 # Loop until the user provides taint-free input. 312 # 313 while :; do 314 f_dialog_input new_ns "$msg" "$ns" \ 315 "$hline_num_punc_tab_enter" || return 316 317 # Take only the first "word" of the user's input 318 new_ns="${new_ns%%[$IFS]*}" 319 320 # Taint-check the user's input 321 [ "$new_ns" ] || break 322 f_dialog_validate_ipaddr "$new_ns" && break 323 324 # Update prompt to allow user to re-edit previous entry 325 ns="$new_ns" 326 done 327 328 # 329 # Save only if the user changed the nameserver. 330 # 331 if [ $index -eq "0" -a "$new_ns" ]; then 332 f_dialog_info "$msg_saving_nameserver" 333 printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF" 334 return $SUCCESS 335 elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then 336 if [ "$new_ns" ]; then 337 msg="$msg_saving_nameserver_existing" 338 else 339 msg="$msg_removing_nameserver" 340 fi 341 f_dialog_info "$msg" 342 343 # 344 # Create a new temporary file to write our new resolv.conf(5) 345 # 346 local tmpfile="$( mktemp -t "$pgm" )" 347 [ "$tmpfile" ] || return $FAILURE 348 349 # 350 # Quietly fixup permissions and ownership 351 # 352 local mode owner 353 mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null ) 354 owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null ) 355 f_quietly chmod "${mode:-0644}" "$tmpfile" 356 f_quietly chown "${owner:-root:wheel}" "$tmpfile" 357 358 # 359 # Operate on resolv.conf(5) 360 # 361 local new_contents 362 new_contents=$( awk -v nsindex="$index" \ 363 -v old_value="$old_ns" \ 364 -v new_value="$new_ns" \ 365 "$f_dialog_input_nameserver_edit_awk" \ 366 "$RESOLV_CONF" ) 367 368 # 369 # Produce an appropriate error message if necessary. 370 # 371 local retval=$? 372 case $retval in 373 1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex";; 374 2) f_dialog_msgbox "$msg_resolv_conf_changed_while_editing" 375 return $retval;; 376 3) f_dialog_msgbox "$msg_resolv_conf_entry_no_longer_exists" 377 return $retval;; 378 esac 379 380 # 381 # Write the temporary file contents and move the temporary 382 # file into place. 383 # 384 echo "$new_contents" > "$tmpfile" || return $FAILURE 385 f_quietly mv "$tmpfile" "$RESOLV_CONF" 386 fi 387} 388 389# f_dialog_menu_nameservers 390# 391# Edit the nameservers in resolv.conf(5). 392# 393f_dialog_menu_nameservers() 394{
|