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