rcdelete revision 249746
1#!/bin/sh
2#-
3# Copyright (c) 2012-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#
27# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcdelete 249746 2013-04-22 05:02:34Z dteske $
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_dprintf "%s: loading includes..." "$0"
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/mustberoot.subr
36f_include $BSDCFG_SHARE/sysrc.subr
37f_include $BSDCFG_SHARE/startup/rcconf.subr
38
39BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
40f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
41
42ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
43[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
44
45############################################################ GLOBALS
46
47#
48# Global map/menu-list for the main menu
49#
50RCCONF_MAP=
51_RCCONF_MAP=
52RCCONF_MENU_LIST=
53
54#
55# Options
56#
57# Inherit SHOW_DESC value if set, otherwise default to 1
58[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
59# Selectively inherit SHOW_* value (in order of preference)
60if [ "$SHOW_DEFAULT_VALUE" ]; then
61	SHOW_DEFAULT_VALUE=1
62	SHOW_CONFIGURED=
63	SHOW_VALUE=
64elif [ "$SHOW_CONFIGURED" ]; then
65	SHOW_DEFAULT_VALUE=
66	SHOW_CONFIGURED=1
67	SHOW_VALUE=
68else
69	SHOW_DEFAULT_VALUE=
70	SHOW_CONFIGURED=
71	SHOW_VALUE=1
72fi
73
74############################################################ FUNCTIONS
75
76# dialog_menu_main
77#
78# Display the dialog(1)-based application main menu.
79#
80dialog_menu_main()
81{
82	local size
83	local hline="$hline_arrows_tab_enter"
84	local prompt=""
85
86	RCCONF_MENU_LIST="
87		'X $msg_exit_cancel'     '$msg_exit_cancel_desc'
88		            ${SHOW_DESC:+'$msg_exit_cancel_help'}
89		'> $msg_delete_selected' '$msg_delete_selected_desc'
90		            ${SHOW_DESC:+'$msg_delete_selected_help'}
91		'> $msg_all'             '$msg_all_desc'
92		            ${SHOW_DESC:+'$msg_all_help'}
93		'> $msg_none'            '$msg_none_desc'
94		            ${SHOW_DESC:+'$msg_none_help'}
95	${USE_XDIALOG:+
96		'> $msg_view_details' '$msg_view_details_desc'
97		                       ${SHOW_DESC:+'$msg_view_details_help'}
98	}
99	" # END-QUOTE
100
101	if [ ! "$_RCCONF_MAP" ]; then
102		# Genreate RCCONF_MAP of `var desc ...' per-line
103		f_dialog_info "$msg_creating_rcconf_map"
104		RCCONF_MAP=$( f_startup_rcconf_map )
105		export RCCONF_MAP
106		# Generate _${var}_desc variables from $RCCONF_MAP
107		f_startup_rcconf_map_expand
108		export _RCCONF_MAP=1
109	fi
110
111	# Show infobox for modes that take a while to calculate/display
112	[ "$SHOW_DEFAULT_VALUE" -o "$SHOW_CONFIGURED" ] &&
113		f_dialog_info "$msg_creating_menu_list"
114
115	RCCONF_MENU_LIST="$RCCONF_MENU_LIST $(
116		. "$RC_DEFAULTS" > /dev/null
117		source_rc_confs > /dev/null
118		var_list=$( f_startup_rcconf_list )
119		for var in $var_list; do
120			eval export $var
121			[ "$SHOW_DEFAULT_VALUE" ] && export \
122				_${var}_default="$( f_sysrc_get_default $var )"
123			[ "$SHOW_CONFIGURED" ] && export \
124				_${var}_file="$( f_sysrc_find $var )"
125		done
126		export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED
127		export msg_default_value
128		echo "$var_list" | awk '
129		BEGIN {
130			prefix = ""
131		}
132		{
133			cur_prefix = tolower(substr($1, 1, 1))
134			printf "'\''"
135			if ( prefix != cur_prefix )
136				prefix = cur_prefix
137			else
138				printf " "
139			var = $1
140			printf "%s'\'' '\''[", var
141			if ( ENVIRON["_" var "_delete"] )
142				printf "X"
143			else
144				printf " "
145			printf "] "
146			if ( ENVIRON["SHOW_DEFAULT_VALUE"] ) {
147				default = ENVIRON["_" var "_default"]
148				gsub(/'\''/, "'\''\\'\'\''", default)
149				value = ENVIRON[var]
150				gsub(/'\''/, "'\''\\'\'\''", value)
151				printf ENVIRON["msg_default_value"] "; %s",
152				       default, value
153			} else if ( ENVIRON["SHOW_CONFIGURED"] ) {
154				printf "%s", ENVIRON["_" var "_file"]
155			} else { # SHOW_VALUE (default behavior)
156				value = ENVIRON[var]
157				gsub(/'\''/, "'\''\\'\'\''", value)
158				printf "%s", value
159			}
160			printf "'\''"
161			if ( ENVIRON["SHOW_DESC"] ) {
162				desc = ENVIRON["_" var "_desc"]
163				gsub(/'\''/, "'\''\\'\'\''", desc)
164				printf " '\''%s'\''", desc
165			}
166			printf "\n"
167		}'
168	)"
169
170	set -f # noglob
171
172	size=$( eval f_dialog_menu_${SHOW_DESC:+with_help_}size \
173	        	\"\$DIALOG_TITLE\"     \
174	        	\"\$DIALOG_BACKTITLE\" \
175	                \"\$prompt\"           \
176	        	\"\$hline\"            \
177	        	$RCCONF_MENU_LIST      )
178
179	local dialog_menu
180	dialog_menu=$( eval $DIALOG \
181		--clear --title \"\$DIALOG_TITLE\" \
182		--backtitle \"\$DIALOG_BACKTITLE\" \
183		--hline \"\$hline\"                \
184		--ok-label \"\$msg_ok\"            \
185		--cancel-label \"\$msg_cancel\"    \
186		--help-button                      \
187		--help-label \"\$msg_details\"     \
188		${SHOW_DESC:+--item-help}          \
189		--menu \"\$prompt\" $size          \
190		$RCCONF_MENU_LIST                  \
191		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
192	)
193	local retval=$?
194	setvar DIALOG_MENU_$$ "$dialog_menu"
195	return $retval
196}
197
198# dialog_menu_delete $var1 [$var2 ...]
199#
200# Get the user's blessing to delete one or more variables.
201# if (and only-if) the user confirms (does not press ESC or Cancel/NO).
202#
203dialog_menu_delete()
204{
205	local size
206	local hline="$hline_arrows_tab_enter"
207	local prompt="$msg_are_you_sure_you_want_delete_the_following"
208	local var_list menu_list
209
210	[ $# -ge 1 ] || return $FAILURE
211
212	if [ $# -eq 1 ]; then
213		f_noyes "$msg_are_you_sure_you_want_to_delete" "$delete_vars"
214		return $?
215	fi
216
217	var_list=$( for var in $*; do echo "$var"; done | sort -u )
218	menu_list=$(
219		. "$RC_DEFAULTS"
220		source_rc_confs
221		echo "$var_list" | awk '
222		BEGIN {
223			prefix = ""
224		}
225		{
226			cur_prefix = tolower(substr($1, 1, 1))
227			printf "'\''"
228			if ( prefix != cur_prefix )
229				prefix = cur_prefix
230			else
231				printf " "
232			var = $1
233			printf "%s'\'' '\'\''\n", var
234		}'
235	)
236
237	size=$( eval f_dialog_menu_size \
238	        	\"\$DIALOG_TITLE\"     \
239	        	\"\$DIALOG_BACKTITLE\" \
240	                \"\$prompt\"           \
241	        	\"\$hline\"            \
242	        	$menu_list             )
243
244	local defaultno="defaultno"
245	[ "$USE_XDIALOG" ] && defaultno="default-no"
246
247	local dialog_menu
248	dialog_menu=$( eval $DIALOG \
249		--clear --title \"\$DIALOG_TITLE\" \
250		--backtitle \"\$DIALOG_BACKTITLE\" \
251		--hline \"\$hline\"                \
252		--$defaultno                       \
253		--ok-label \"\$msg_ok\"            \
254		--cancel-label \"\$msg_cancel\"    \
255		--menu \"\$prompt\" $size          \
256		$menu_list                         \
257		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
258	)
259	local retval=$?
260	setvar DIALOG_MENU_$$ "$dialog_menu"
261	return $retval
262}
263
264############################################################ MAIN
265
266# Incorporate rc-file if it exists
267[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
268
269#
270# Process command-line arguments
271#
272while getopts dD:hSX flag; do
273	case "$flag" in
274	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
275	esac
276done
277shift $(( $OPTIND - 1 ))
278
279#
280# Initialize
281#
282f_dialog_title "$msg_delete_startup_directives"
283f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
284f_mustberoot_init
285
286while :; do
287	dialog_menu_main
288	retval=$?
289	mtag=$( f_dialog_menutag )
290
291	if [ "$USE_XDIALOG" ]; then
292		case "$mtag" in
293		"> $msg_view_details")
294			f_dialog_input_view_details
295			continue
296		esac
297	elif [ $retval -eq 2 ]; then
298		# The ``Help'' button (labeled "Details") was pressed
299		f_dialog_input_view_details
300		continue
301	fi
302
303	[ $retval -eq 0 ] || f_die
304
305	case "$mtag" in
306	"X $msg_exit_cancel") break ;;
307	"> $msg_delete_selected")
308		delete_vars=
309		for var in $( f_startup_rcconf_list ); do
310			[ "$( eval echo \$_${var}_delete )" ] || continue
311			delete_vars="$delete_vars${delete_vars:+ }$var"
312		done
313		unset var # no longer needed
314		if dialog_menu_delete $delete_vars; then
315			f_dialog_title "$msg_info"
316			f_dialog_info "$msg_deleting_selected_directives"
317			f_dialog_title_restore
318			for var in $delete_vars; do
319				err=$( f_sysrc_delete $var 2>&1 )
320				if [ $? -ne $SUCCESS ]; then
321					f_dialog_msgbox "$err\n"
322					break
323				fi
324			done
325			unset var # no longer needed
326		fi
327		;;
328	"> $msg_all")
329		for var in $( f_startup_rcconf_list ); do
330			setvar _${var}_delete 1
331			export _${var}_delete
332		done
333		unset var # no longer needed
334		;;
335	"> $msg_none")
336		var_list=$( set | awk -F= "
337			/$STARTUP_RCCONF_REGEX/ {
338				if (\$1 ~ /^_[[:alpha:]_][[:alnum:]_]*_delete/)
339					print \$1
340			}"
341		)
342		[ "$var_list" ] && unset $var_list
343		unset var_list # no longer needed
344		;;
345	*) # Anything else is a variable to edit
346		var="${mtag# }"
347
348		# Toggle the state-variable and loop back to menu
349		if eval [ \"\${_${var}_delete+set}\" ]; then
350			unset _${var}_delete
351		else
352			setvar _${var}_delete 1
353			export _${var}_delete
354		fi
355		unset var # no longer needed
356	esac
357done
358
359exit $SUCCESS
360
361################################################################################
362# END
363################################################################################
364