1ab2043b8SDevin Teskeif [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
2ab2043b8SDevin Teske#
37323adacSDevin Teske# Copyright (c) 2006-2013 Devin Teske
4f8ea072aSDevin Teske# All rights reserved.
5ab2043b8SDevin Teske#
6ab2043b8SDevin Teske# Redistribution and use in source and binary forms, with or without
7ab2043b8SDevin Teske# modification, are permitted provided that the following conditions
8ab2043b8SDevin Teske# are met:
9ab2043b8SDevin Teske# 1. Redistributions of source code must retain the above copyright
10ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer.
11ab2043b8SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
12ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer in the
13ab2043b8SDevin Teske#    documentation and/or other materials provided with the distribution.
14ab2043b8SDevin Teske#
15ab2043b8SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
168e37a7c8SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17ab2043b8SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ab2043b8SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ab2043b8SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208e37a7c8SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21ab2043b8SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ab2043b8SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ab2043b8SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ab2043b8SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ab2043b8SDevin Teske# SUCH DAMAGE.
26ab2043b8SDevin Teske#
27ab2043b8SDevin Teske#
28ab2043b8SDevin Teske############################################################ INCLUDES
29ab2043b8SDevin Teske
30ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
31ab2043b8SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3256961fd7SDevin Teskef_dprintf "%s: loading includes..." networking/resolv.subr
33ab2043b8SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
347323adacSDevin Teskef_include $BSDCFG_SHARE/media/tcpip.subr
35ab2043b8SDevin Teskef_include $BSDCFG_SHARE/networking/common.subr
36ab2043b8SDevin Teskef_include $BSDCFG_SHARE/networking/ipaddr.subr
371de60ff0SDevin Teskef_include $BSDCFG_SHARE/strings.subr
38ab2043b8SDevin Teske
39ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
40ab2043b8SDevin Teskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
41ab2043b8SDevin Teske
42ab2043b8SDevin Teske############################################################ CONFIGURATION
43ab2043b8SDevin Teske
44ab2043b8SDevin Teske#
45ab2043b8SDevin Teske# When updating resolv.conf(5), should we populate the `search' directive with
46ab2043b8SDevin Teske# all possible sub-domains? In example, if the domain is "sub.domain.com", when
47ab2043b8SDevin Teske# the below option is set to 1, include both "sub.domain.com" and "domain.com"
48ab2043b8SDevin Teske# in the `search' directive, otherwise use only "sub.domain.com".
49ab2043b8SDevin Teske#
50ab2043b8SDevin Teske# When enabled (set to 1), specify the minimum number of dots required for each
51ab2043b8SDevin Teske# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'.
52ab2043b8SDevin Teske#
53ab2043b8SDevin Teske: ${RESOLVER_SEARCH_DOMAINS_ALL:=1}
54ab2043b8SDevin Teske: ${RESOLVER_SEARCH_NDOTS:=1}
55ab2043b8SDevin Teske
56ab2043b8SDevin Teske############################################################ FUNCTIONS
57ab2043b8SDevin Teske
58ab2043b8SDevin Teske# f_resolv_conf_domain
59ab2043b8SDevin Teske#
60ab2043b8SDevin Teske# Returns the domain configured in resolv.conf(5).
61ab2043b8SDevin Teske#
62ab2043b8SDevin Teskef_resolv_conf_domain()
63ab2043b8SDevin Teske{
64fb7d723eSDevin Teske	tail -r "$RESOLV_CONF" 2> /dev/null | awk \
65ab2043b8SDevin Teske	'
66ab2043b8SDevin Teske		BEGIN { found = 0 }
67ab2043b8SDevin Teske		( tolower($1) == "domain" ) \
68ab2043b8SDevin Teske		{
69ab2043b8SDevin Teske			print $2
70ab2043b8SDevin Teske			found = 1
71ab2043b8SDevin Teske			exit
72ab2043b8SDevin Teske		}
73ab2043b8SDevin Teske		END { exit ! found }
74ab2043b8SDevin Teske	'
75ab2043b8SDevin Teske}
76ab2043b8SDevin Teske
77ab2043b8SDevin Teske# f_resolv_conf_search
78ab2043b8SDevin Teske#
79ab2043b8SDevin Teske# Returns the search configured in resolv.conf(5).
80ab2043b8SDevin Teske#
81ab2043b8SDevin Teskef_resolv_conf_search()
82ab2043b8SDevin Teske{
83fb7d723eSDevin Teske	tail -r "$RESOLV_CONF" 2> /dev/null | awk \
84ab2043b8SDevin Teske	'
85ab2043b8SDevin Teske		BEGIN { found = 0 }
86ab2043b8SDevin Teske		{
87ab2043b8SDevin Teske			tl0 = tolower($0)
88ab2043b8SDevin Teske			if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) {
89ab2043b8SDevin Teske				search = substr($0, RLENGTH + 1)
90ab2043b8SDevin Teske				sub(/[[:space:]]*#.*$/, "", search)
91ab2043b8SDevin Teske				gsub(/[[:space:]]+/, " ", search)
92ab2043b8SDevin Teske				print search
93ab2043b8SDevin Teske				found = 1
94ab2043b8SDevin Teske				exit
95ab2043b8SDevin Teske			}
96ab2043b8SDevin Teske		}
97ab2043b8SDevin Teske		END { exit ! found }
98ab2043b8SDevin Teske	'
99ab2043b8SDevin Teske}
100ab2043b8SDevin Teske
101ab2043b8SDevin Teske# f_dialog_resolv_conf_update $hostname
102ab2043b8SDevin Teske#
103ab2043b8SDevin Teske# Updates the search/domain directives in resolv.conf(5) given a valid fully-
104ab2043b8SDevin Teske# qualified hostname.
105ab2043b8SDevin Teske#
106ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
107ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
108ab2043b8SDevin Teske#
109ab2043b8SDevin Teskef_dialog_resolv_conf_update_awk='
110ab2043b8SDevin Teske# Variables that should be defined on the invocation line:
111ab2043b8SDevin Teske# 	-v domain="domain"
112ab2043b8SDevin Teske# 	-v search_all="0|1"
113ab2043b8SDevin Teske# 	-v search_ndots="1+"
114ab2043b8SDevin Teske#
115ab2043b8SDevin TeskeBEGIN {
116ab2043b8SDevin Teske	domain_found = search_found = 0
117ab2043b8SDevin Teske
118ab2043b8SDevin Teske	if ( search_all ) {
119ab2043b8SDevin Teske		search = ""
120ab2043b8SDevin Teske		subdomain = domain
121ab2043b8SDevin Teske		if ( search_ndots < 1 )
122ab2043b8SDevin Teske			search_ndots = 1
123ab2043b8SDevin Teske
124ab2043b8SDevin Teske		ndots = split(subdomain, labels, ".") - 1
125ab2043b8SDevin Teske		while ( ndots-- >= search_ndots ) {
126ab2043b8SDevin Teske			if ( length(search) ) search = search " "
127ab2043b8SDevin Teske			search = search subdomain
128ab2043b8SDevin Teske			sub(/[^.]*\./, "", subdomain)
129ab2043b8SDevin Teske		}
130ab2043b8SDevin Teske	}
131ab2043b8SDevin Teske	else search = domain
132ab2043b8SDevin Teske}
133ab2043b8SDevin Teske{
134ab2043b8SDevin Teske	if ( domain_found && search_found ) { print; next }
135ab2043b8SDevin Teske
136ab2043b8SDevin Teske	tl0 = tolower($0)
137ab2043b8SDevin Teske	if ( ! domain_found && \
138ab2043b8SDevin Teske	     match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \
139ab2043b8SDevin Teske	{
140ab2043b8SDevin Teske		if ( length(domain) ) {
141ab2043b8SDevin Teske			printf "%s%s\n", substr($0, 0, RLENGTH), domain
142ab2043b8SDevin Teske			domain_found = 1
143ab2043b8SDevin Teske		}
144ab2043b8SDevin Teske	}
145ab2043b8SDevin Teske	else if ( ! search_found && \
146ab2043b8SDevin Teske	          match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \
147ab2043b8SDevin Teske	{
148ab2043b8SDevin Teske		if ( length(search) ) {
149ab2043b8SDevin Teske			printf "%s%s\n", substr($0, 0, RLENGTH), search
150ab2043b8SDevin Teske			search_found = 1
151ab2043b8SDevin Teske		}
152ab2043b8SDevin Teske	}
153ab2043b8SDevin Teske	else print
154ab2043b8SDevin Teske}
155ab2043b8SDevin TeskeEND {
156ab2043b8SDevin Teske	if ( ! search_found && length(search) )
157ab2043b8SDevin Teske		printf "search\t%s\n", search
158ab2043b8SDevin Teske	if ( ! domain_found && length(domain) )
159ab2043b8SDevin Teske		printf "domain\t%s\n", domain
160ab2043b8SDevin Teske}
161ab2043b8SDevin Teske'
162ab2043b8SDevin Teskef_dialog_resolv_conf_update()
163ab2043b8SDevin Teske{
164d4ae33f0SDevin Teske	local funcname=f_dialog_resolv_conf_update
165ab2043b8SDevin Teske	local hostname="$1"
166ab2043b8SDevin Teske
167ab2043b8SDevin Teske	#
168ab2043b8SDevin Teske	# Extrapolate the desired domain search parameter for resolv.conf(5)
169ab2043b8SDevin Teske	#
170d4ae33f0SDevin Teske	local search nfields ndots domain="${hostname#*.}"
171ab2043b8SDevin Teske	if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
172d4ae33f0SDevin Teske		search=
173d4ae33f0SDevin Teske		IFS=. f_count_ifs nfields "$domain"
174d4ae33f0SDevin Teske		ndots=$(( $nfields - 1 ))
175ab2043b8SDevin Teske		while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
176d4ae33f0SDevin Teske			search="$search $domain"
177ab2043b8SDevin Teske			domain="${domain#*.}"
178ab2043b8SDevin Teske			ndots=$(( $ndots - 1 ))
179ab2043b8SDevin Teske		done
180d4ae33f0SDevin Teske		search="${search# }"
181ab2043b8SDevin Teske		domain="${hostname#*.}"
182ab2043b8SDevin Teske	else
183ab2043b8SDevin Teske		search="$domain"
184ab2043b8SDevin Teske	fi
185ab2043b8SDevin Teske
186ab2043b8SDevin Teske	#
187ab2043b8SDevin Teske	# Save domain/search information only if different from resolv.conf(5)
188ab2043b8SDevin Teske	#
189ab2043b8SDevin Teske	if [ "$domain" != "$( f_resolv_conf_domain )" -o \
190ab2043b8SDevin Teske	     "$search" != "$( f_resolv_conf_search )" ]
191ab2043b8SDevin Teske	then
192ab2043b8SDevin Teske		f_dialog_info "Saving new domain/search settings" \
193ab2043b8SDevin Teske		              "to resolv.conf(5)..."
194ab2043b8SDevin Teske
195ab2043b8SDevin Teske		#
196ab2043b8SDevin Teske		# Create a new temporary file to write our resolv.conf(5)
197ab2043b8SDevin Teske		# update with our new `domain' and `search' directives.
198ab2043b8SDevin Teske		#
199d4ae33f0SDevin Teske		local tmpfile
200d4ae33f0SDevin Teske		f_eval_catch -dk tmpfile $funcname mktemp \
201d4ae33f0SDevin Teske			'mktemp -t "%s"' "$tmpfile" || return $DIALOG_CANCEL
202ab2043b8SDevin Teske
203ab2043b8SDevin Teske		#
204ab2043b8SDevin Teske		# Fixup permissions and ownership (mktemp(1) creates the
205ab2043b8SDevin Teske		# temporary file with 0600 permissions -- change the
206ab2043b8SDevin Teske		# permissions and ownership to match resolv.conf(5) before
207ab2043b8SDevin Teske		# we write it out and mv(1) it into place).
208ab2043b8SDevin Teske		#
209d4ae33f0SDevin Teske		local mode owner
210d4ae33f0SDevin Teske		f_eval_catch -dk mode $funcname stat \
211d4ae33f0SDevin Teske			'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
212d4ae33f0SDevin Teske		f_eval_catch -dk owner $funcname stat \
213d4ae33f0SDevin Teske			'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
214d4ae33f0SDevin Teske			owner="root:wheel"
215d4ae33f0SDevin Teske		f_eval_catch -d $funcname chmod \
216d4ae33f0SDevin Teske			'chmod "%s" "%s"' "$mode" "$tmpfile"
217d4ae33f0SDevin Teske		f_eval_catch -d $funcname chown \
218d4ae33f0SDevin Teske			'chown "%s" "%s"' "$owner" "$tmpfile"
219ab2043b8SDevin Teske
220ab2043b8SDevin Teske		#
221ab2043b8SDevin Teske		# Operate on resolv.conf(5), replacing only the last
222ab2043b8SDevin Teske		# occurrences of `domain' and `search' directives (or add
223ab2043b8SDevin Teske		# them to the top if not found), in strict-adherence to the
224ab2043b8SDevin Teske		# following entry in resolver(5):
225ab2043b8SDevin Teske		#
226ab2043b8SDevin Teske		# 	The domain and search keywords are mutually exclusive.
227ab2043b8SDevin Teske		# 	If more than one instance of these keywords is present,
228ab2043b8SDevin Teske		# 	the last instance will override.
229ab2043b8SDevin Teske		#
230ab2043b8SDevin Teske		# NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the
231ab2043b8SDevin Teske		# environment, all sub-domains will be added to the `search'
232ab2043b8SDevin Teske		# directive, not just the FQDN.
233ab2043b8SDevin Teske		#
234ab2043b8SDevin Teske		local domain="${hostname#*.}" new_contents
235ab2043b8SDevin Teske		[ "$domain" = "$hostname" ] && domain=
236fb7d723eSDevin Teske		new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null )
237ab2043b8SDevin Teske		new_contents=$( echo "$new_contents" | awk \
238ab2043b8SDevin Teske			-v domain="$domain" \
239ab2043b8SDevin Teske			-v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \
240ab2043b8SDevin Teske			-v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \
241ab2043b8SDevin Teske			"$f_dialog_resolv_conf_update_awk" )
242ab2043b8SDevin Teske
243ab2043b8SDevin Teske		#
244ab2043b8SDevin Teske		# Write the temporary file contents and move the temporary
245ab2043b8SDevin Teske		# file into place.
246ab2043b8SDevin Teske		#
247f677a9e2SDevin Teske		echo "$new_contents" | tail -r > "$tmpfile" ||
248f677a9e2SDevin Teske			return $DIALOG_CANCEL
249d4ae33f0SDevin Teske		f_eval_catch -d $funcname mv \
250d4ae33f0SDevin Teske			'mv "%s" "%s"' "$tmpfile" "$RESOLV_CONF"
251ab2043b8SDevin Teske
252ab2043b8SDevin Teske	fi
253ab2043b8SDevin Teske}
254ab2043b8SDevin Teske
255ab2043b8SDevin Teske# f_dialog_input_nameserver [ $n $nameserver ]
256ab2043b8SDevin Teske#
257ab2043b8SDevin Teske# Allows the user to edit a given nameserver. The first argument is the
258ab2043b8SDevin Teske# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one
259ab2043b8SDevin Teske# if editing the first nameserver instance, two if editing the second, three if
260ab2043b8SDevin Teske# the third, ad nauseum. If this argument is zero, null, or missing, the value
261ab2043b8SDevin Teske# entered by the user (if non-null) will be added to resolv.conf(5) as a new
262ab2043b8SDevin Teske# `nameserver' entry. The second argument is the IPv4 address of the nameserver
263ab2043b8SDevin Teske# to be edited -- this will be displayed as the initial value during the edit.
264ab2043b8SDevin Teske#
265ab2043b8SDevin Teske# Taint-checking is performed when editing an existing entry (when the second
266ab2043b8SDevin Teske# argument is one or higher) in that the first argument must match the current
267ab2043b8SDevin Teske# value of the Nth `nameserver' instance in resolv.conf(5) else an error is
268ab2043b8SDevin Teske# generated discarding any/all changes.
269ab2043b8SDevin Teske#
270ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
271ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
272ab2043b8SDevin Teske#
273ab2043b8SDevin Teskef_dialog_input_nameserver_edit_awk='
274ab2043b8SDevin Teske# Variables that should be defined on the invocation line:
275ab2043b8SDevin Teske# 	-v nsindex="1+"
276ab2043b8SDevin Teske# 	-v old_value="..."
277ab2043b8SDevin Teske# 	-v new_value="..."
278ab2043b8SDevin Teske#
279ab2043b8SDevin TeskeBEGIN {
280ab2043b8SDevin Teske	if ( nsindex < 1 ) exit 1
281ab2043b8SDevin Teske	found = n = 0
282ab2043b8SDevin Teske}
283ab2043b8SDevin Teske{
284ab2043b8SDevin Teske	if ( found ) { print; next }
285ab2043b8SDevin Teske
286ab2043b8SDevin Teske	if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) {
287ab2043b8SDevin Teske		if ( ++n == nsindex ) {
288ab2043b8SDevin Teske			if ( $2 != old_value ) exit 2
289ab2043b8SDevin Teske			if ( new_value != "" ) printf "%s%s\n", \
290ab2043b8SDevin Teske				substr($0, 0, RLENGTH), new_value
291ab2043b8SDevin Teske			found = 1
292ab2043b8SDevin Teske		}
293ab2043b8SDevin Teske		else print
294ab2043b8SDevin Teske	}
295ab2043b8SDevin Teske	else print
296ab2043b8SDevin Teske}
297ab2043b8SDevin TeskeEND { if ( ! found ) exit 3 }
298ab2043b8SDevin Teske'
299ab2043b8SDevin Teskef_dialog_input_nameserver()
300ab2043b8SDevin Teske{
301d4ae33f0SDevin Teske	local funcname=f_dialog_input_nameserver
302ab2043b8SDevin Teske	local index="${1:-0}" old_ns="$2" new_ns
303ab2043b8SDevin Teske	local ns="$old_ns"
304ab2043b8SDevin Teske
305ab2043b8SDevin Teske	#
306ab2043b8SDevin Teske	# Perform sanity checks
307ab2043b8SDevin Teske	#
308f677a9e2SDevin Teske	f_isinteger "$index" || return $DIALOG_CANCEL
309f677a9e2SDevin Teske	[ $index -ge 0 ] || return $DIALOG_CANCEL
310ab2043b8SDevin Teske
311ab2043b8SDevin Teske	local msg
312ab2043b8SDevin Teske	if [ $index -gt 0 ]; then
313ab2043b8SDevin Teske		if [ "$USE_XDIALOG" ]; then
314ab2043b8SDevin Teske			msg="$xmsg_please_enter_nameserver_existing"
315ab2043b8SDevin Teske		else
316ab2043b8SDevin Teske			msg="$msg_please_enter_nameserver_existing"
317ab2043b8SDevin Teske		fi
318ab2043b8SDevin Teske	else
319ab2043b8SDevin Teske		msg="$msg_please_enter_nameserver"
320ab2043b8SDevin Teske	fi
321ab2043b8SDevin Teske
322ab2043b8SDevin Teske	#
323ab2043b8SDevin Teske	# Loop until the user provides taint-free input.
324ab2043b8SDevin Teske	#
325ab2043b8SDevin Teske	while :; do
326ec7120b5SDevin Teske		f_dialog_input new_ns "$msg" "$ns" \
327f677a9e2SDevin Teske		               "$hline_num_punc_tab_enter" || return $?
328ab2043b8SDevin Teske
329ab2043b8SDevin Teske		# Take only the first "word" of the user's input
330ab2043b8SDevin Teske		new_ns="${new_ns%%[$IFS]*}"
331ab2043b8SDevin Teske
332ab2043b8SDevin Teske		# Taint-check the user's input
333ab2043b8SDevin Teske		[ "$new_ns" ] || break
334ab2043b8SDevin Teske		f_dialog_validate_ipaddr "$new_ns" && break
335ab2043b8SDevin Teske
336ab2043b8SDevin Teske		# Update prompt to allow user to re-edit previous entry
337ab2043b8SDevin Teske		ns="$new_ns"
338ab2043b8SDevin Teske	done
339ab2043b8SDevin Teske
340ab2043b8SDevin Teske	#
341ab2043b8SDevin Teske	# Save only if the user changed the nameserver.
342ab2043b8SDevin Teske	#
343ab2043b8SDevin Teske	if [ $index -eq "0" -a "$new_ns" ]; then
344ab2043b8SDevin Teske		f_dialog_info "$msg_saving_nameserver"
345ab2043b8SDevin Teske		printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF"
346f677a9e2SDevin Teske		return $DIALOG_OK
347ab2043b8SDevin Teske	elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then
348ab2043b8SDevin Teske		if [ "$new_ns" ]; then
349ab2043b8SDevin Teske			msg="$msg_saving_nameserver_existing"
350ab2043b8SDevin Teske		else
351ab2043b8SDevin Teske			msg="$msg_removing_nameserver"
352ab2043b8SDevin Teske		fi
353ab2043b8SDevin Teske		f_dialog_info "$msg"
354ab2043b8SDevin Teske
355ab2043b8SDevin Teske		#
356ab2043b8SDevin Teske		# Create a new temporary file to write our new resolv.conf(5)
357ab2043b8SDevin Teske		#
358d4ae33f0SDevin Teske		local tmpfile
359d4ae33f0SDevin Teske		f_eval_catch -dk tmpfile $funcname mktemp \
360d4ae33f0SDevin Teske			'mktemp -t "%s"' "$pgm" || return $DIALOG_CANCEL
361ab2043b8SDevin Teske
362ab2043b8SDevin Teske		#
363ab2043b8SDevin Teske		# Quietly fixup permissions and ownership
364ab2043b8SDevin Teske		#
365ab2043b8SDevin Teske		local mode owner
366d4ae33f0SDevin Teske		f_eval_catch -dk mode $funcname stat \
367d4ae33f0SDevin Teske			'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
368d4ae33f0SDevin Teske		f_eval_catch -dk owner $funcname stat \
369d4ae33f0SDevin Teske			'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
370d4ae33f0SDevin Teske			owner="root:wheel"
371d4ae33f0SDevin Teske		f_eval_catch -d $funcname chmod \
372d4ae33f0SDevin Teske			'chmod "%s" "%s"' "$mode" "$tmpfile"
373d4ae33f0SDevin Teske		f_eval_catch -d $funcname chown \
374d4ae33f0SDevin Teske			'chown "%s" "%s"' "$owner" "$tmpfile"
375ab2043b8SDevin Teske
376ab2043b8SDevin Teske		#
377ab2043b8SDevin Teske		# Operate on resolv.conf(5)
378ab2043b8SDevin Teske		#
379ab2043b8SDevin Teske		local new_contents
380ab2043b8SDevin Teske		new_contents=$( awk -v nsindex="$index"    \
381ab2043b8SDevin Teske		                    -v old_value="$old_ns" \
382ab2043b8SDevin Teske		                    -v new_value="$new_ns" \
383ab2043b8SDevin Teske		                    "$f_dialog_input_nameserver_edit_awk" \
384ab2043b8SDevin Teske		                    "$RESOLV_CONF" )
385ab2043b8SDevin Teske
386ab2043b8SDevin Teske		#
387ab2043b8SDevin Teske		# Produce an appropriate error message if necessary.
388ab2043b8SDevin Teske		#
389ab2043b8SDevin Teske		local retval=$?
390ab2043b8SDevin Teske		case $retval in
391ab2043b8SDevin Teske		1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex" ;;
3927079fc4eSDevin Teske		2) f_show_msg "$msg_resolv_conf_changed_while_editing"
393ab2043b8SDevin Teske		   return $retval ;;
3947079fc4eSDevin Teske		3) f_show_msg "$msg_resolv_conf_entry_no_longer_exists"
395ab2043b8SDevin Teske		   return $retval ;;
396ab2043b8SDevin Teske		esac
397ab2043b8SDevin Teske
398ab2043b8SDevin Teske		#
399ab2043b8SDevin Teske		# Write the temporary file contents and move the temporary
400ab2043b8SDevin Teske		# file into place.
401ab2043b8SDevin Teske		#
402f677a9e2SDevin Teske		echo "$new_contents" > "$tmpfile" || return $DIALOG_CANCEL
403d4ae33f0SDevin Teske		f_eval_catch -d $funcname mv \
404d4ae33f0SDevin Teske			'mv "%s" "%s"' "$tmpfile" "$RESOLV_CONF"
405ab2043b8SDevin Teske	fi
406ab2043b8SDevin Teske}
407ab2043b8SDevin Teske
408ab2043b8SDevin Teske# f_dialog_menu_nameservers
409ab2043b8SDevin Teske#
410ab2043b8SDevin Teske# Edit the nameservers in resolv.conf(5).
411ab2043b8SDevin Teske#
412ab2043b8SDevin Teskef_dialog_menu_nameservers()
413ab2043b8SDevin Teske{
414052f8969SDevin Teske	local prompt="$msg_dns_configuration"
415052f8969SDevin Teske	local menu_list # Calculated below
416052f8969SDevin Teske	local hline="$hline_arrows_tab_enter"
417052f8969SDevin Teske	local defaultitem=
41874036c4dSDevin Teske
41974036c4dSDevin Teske	local height width rows
420ab2043b8SDevin Teske	local opt_exit="$msg_return_to_previous_menu"
421ab2043b8SDevin Teske	local opt_add="$msg_add_nameserver"
422ab2043b8SDevin Teske
423ab2043b8SDevin Teske	#
424ab2043b8SDevin Teske	# Loop forever until the user has finished configuring nameservers
425ab2043b8SDevin Teske	#
426ab2043b8SDevin Teske	while :; do
427ab2043b8SDevin Teske		#
428ab2043b8SDevin Teske		# Re/Build list of nameservers
429ab2043b8SDevin Teske		#
430d4ae33f0SDevin Teske		local nameservers
431d4ae33f0SDevin Teske		f_resolv_conf_nameservers nameservers
432052f8969SDevin Teske		menu_list=$(
433ab2043b8SDevin Teske			index=1
434ab2043b8SDevin Teske
435ab2043b8SDevin Teske			echo "'X $msg_exit' '$opt_exit'"
436ab2043b8SDevin Teske			index=$(( $index + 1 ))
437ab2043b8SDevin Teske
438ab2043b8SDevin Teske			echo "'A $msg_add'  '$opt_add'"
439ab2043b8SDevin Teske			index=$(( $index + 1 ))
440ab2043b8SDevin Teske
441ab2043b8SDevin Teske			for ns in $nameservers; do
442ab2043b8SDevin Teske				[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
443d356ca0cSDevin Teske				f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
444ab2043b8SDevin Teske				echo "'$tag nameserver' '$ns'"
445ab2043b8SDevin Teske				index=$(( $index + 1 ))
446ab2043b8SDevin Teske			done
447052f8969SDevin Teske		)
448ab2043b8SDevin Teske
449ab2043b8SDevin Teske		#
450ab2043b8SDevin Teske		# Display configuration-edit menu
451ab2043b8SDevin Teske		#
45274036c4dSDevin Teske		eval f_dialog_menu_size height width rows \
453ab2043b8SDevin Teske		                        \"\$DIALOG_TITLE\"     \
454ab2043b8SDevin Teske		                        \"\$DIALOG_BACKTITLE\" \
455ab2043b8SDevin Teske		                        \"\$prompt\"           \
456ab2043b8SDevin Teske		                        \"\$hline\"            \
45774036c4dSDevin Teske		                        $menu_list
458fd962ac6SDevin Teske		local tag
459fd962ac6SDevin Teske		tag=$( eval $DIALOG \
460d3a0f918SDevin Teske			--title \"\$DIALOG_TITLE\"         \
461ab2043b8SDevin Teske			--backtitle \"\$DIALOG_BACKTITLE\" \
462ab2043b8SDevin Teske			--hline \"\$hline\"                \
463ab2043b8SDevin Teske			--ok-label \"\$msg_ok\"            \
464ab2043b8SDevin Teske			--cancel-label \"\$msg_cancel\"    \
465d3a0f918SDevin Teske			--default-item \"\$defaultitem\"   \
46674036c4dSDevin Teske			--menu \"\$prompt\"                \
46774036c4dSDevin Teske			$height $width $rows               \
468ab2043b8SDevin Teske			$menu_list                         \
46989498fdfSDevin Teske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
47089498fdfSDevin Teske		)
471ab2043b8SDevin Teske		local retval=$?
472fd962ac6SDevin Teske		f_dialog_data_sanitize tag
473ab2043b8SDevin Teske
474ab2043b8SDevin Teske		# Return if "Cancel" was chosen (-1) or ESC was pressed (255)
475f677a9e2SDevin Teske		if [ $retval -ne $DIALOG_OK ]; then
476d3a0f918SDevin Teske			return $retval
477d3a0f918SDevin Teske		else
478d3a0f918SDevin Teske			# Only update default-item on success
479d3a0f918SDevin Teske			defaultitem="$tag"
480d3a0f918SDevin Teske		fi
481ab2043b8SDevin Teske
482ab2043b8SDevin Teske		case "$tag" in
483ab2043b8SDevin Teske		"X $msg_exit") break ;;
484ab2043b8SDevin Teske		"A $msg_add")
485ab2043b8SDevin Teske			f_dialog_input_nameserver
486ab2043b8SDevin Teske			;;
487ab2043b8SDevin Teske		*)
488fd962ac6SDevin Teske			local n ns
489ab2043b8SDevin Teske			n=$( eval f_dialog_menutag2index \"\$tag\" $menu_list )
490ab2043b8SDevin Teske			ns=$( eval f_dialog_menutag2item \"\$tag\" $menu_list )
491ab2043b8SDevin Teske			f_dialog_input_nameserver $(( $n - 2 )) "$ns"
492ab2043b8SDevin Teske			;;
493ab2043b8SDevin Teske		esac
494ab2043b8SDevin Teske	done
495ab2043b8SDevin Teske}
496ab2043b8SDevin Teske
49756961fd7SDevin Teske############################################################ MAIN
49856961fd7SDevin Teske
49956961fd7SDevin Teskef_dprintf "%s: Successfully loaded." networking/resolv.subr
50056961fd7SDevin Teske
501ab2043b8SDevin Teskefi # ! $_NETWORKING_RESOLV_SUBR
502