rcdelete revision 251190
1238438Sdteske#!/bin/sh
2238438Sdteske#-
3249746Sdteske# Copyright (c) 2012-2013 Devin Teske
4238438Sdteske# All Rights Reserved.
5238438Sdteske#
6238438Sdteske# Redistribution and use in source and binary forms, with or without
7238438Sdteske# modification, are permitted provided that the following conditions
8238438Sdteske# are met:
9238438Sdteske# 1. Redistributions of source code must retain the above copyright
10238438Sdteske#    notice, this list of conditions and the following disclaimer.
11238438Sdteske# 2. Redistributions in binary form must reproduce the above copyright
12238438Sdteske#    notice, this list of conditions and the following disclaimer in the
13238438Sdteske#    documentation and/or other materials provided with the distribution.
14238438Sdteske#
15238438Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16238438Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17238438Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18238438Sdteske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19238438Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20238438Sdteske# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21238438Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22238438Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23238438Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24238438Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25238438Sdteske# SUCH DAMAGE.
26238438Sdteske#
27238438Sdteske# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcdelete 251190 2013-05-31 19:07:17Z dteske $
28238438Sdteske#
29238438Sdteske############################################################ INCLUDES
30238438Sdteske
31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig"
32240684Sdteske. $BSDCFG_SHARE/common.subr || exit 1
33244675Sdteskef_dprintf "%s: loading includes..." "$0"
34240684Sdteskef_include $BSDCFG_SHARE/dialog.subr
35240684Sdteskef_include $BSDCFG_SHARE/mustberoot.subr
36240684Sdteskef_include $BSDCFG_SHARE/sysrc.subr
37240684Sdteskef_include $BSDCFG_SHARE/startup/rcconf.subr
38238438Sdteske
39240684SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
40238438Sdteskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
41238438Sdteske
42243112Sdteskeipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
43238438Sdteske[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
44238438Sdteske
45238438Sdteske############################################################ GLOBALS
46238438Sdteske
47238438Sdteske#
48238438Sdteske# Global map/menu-list for the main menu
49238438Sdteske#
50238438SdteskeRCCONF_MAP=
51238438SdteskeRCCONF_MENU_LIST=
52238438Sdteske
53238438Sdteske#
54238438Sdteske# Options
55238438Sdteske#
56238438Sdteske# Inherit SHOW_DESC value if set, otherwise default to 1
57240798Sdteske[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
58238438Sdteske# Selectively inherit SHOW_* value (in order of preference)
59238438Sdteskeif [ "$SHOW_DEFAULT_VALUE" ]; then
60238438Sdteske	SHOW_DEFAULT_VALUE=1
61238438Sdteske	SHOW_CONFIGURED=
62238438Sdteske	SHOW_VALUE=
63238438Sdteskeelif [ "$SHOW_CONFIGURED" ]; then
64238438Sdteske	SHOW_DEFAULT_VALUE=
65238438Sdteske	SHOW_CONFIGURED=1
66238438Sdteske	SHOW_VALUE=
67238438Sdteskeelse
68238438Sdteske	SHOW_DEFAULT_VALUE=
69238438Sdteske	SHOW_CONFIGURED=
70238438Sdteske	SHOW_VALUE=1
71238438Sdteskefi
72238438Sdteske
73238438Sdteske############################################################ FUNCTIONS
74238438Sdteske
75249751Sdteske# dialog_create_main
76238438Sdteske#
77249751Sdteske# Create the dialog(1) main menu. Separated from dialog_menu_main (used to
78249751Sdteske# display the menu) to speed up execution (we only call this function when
79249751Sdteske# initializing or changing the view details).
80238438Sdteske#
81249751Sdteskedialog_create_main()
82238438Sdteske{
83238438Sdteske	# Show infobox for modes that take a while to calculate/display
84238438Sdteske	[ "$SHOW_DEFAULT_VALUE" -o "$SHOW_CONFIGURED" ] &&
85238438Sdteske		f_dialog_info "$msg_creating_menu_list"
86238438Sdteske
87249751Sdteske	RCCONF_MENU_LIST=$(
88240783Sdteske		. "$RC_DEFAULTS" > /dev/null
89240783Sdteske		source_rc_confs > /dev/null
90238438Sdteske		var_list=$( f_startup_rcconf_list )
91238438Sdteske		for var in $var_list; do
92238438Sdteske			eval export $var
93238438Sdteske			[ "$SHOW_DEFAULT_VALUE" ] && export \
94238438Sdteske				_${var}_default="$( f_sysrc_get_default $var )"
95238438Sdteske			[ "$SHOW_CONFIGURED" ] && export \
96238438Sdteske				_${var}_file="$( f_sysrc_find $var )"
97238438Sdteske		done
98238438Sdteske		export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED
99238438Sdteske		export msg_default_value
100238438Sdteske		echo "$var_list" | awk '
101238438Sdteske		BEGIN {
102238438Sdteske			prefix = ""
103238438Sdteske		}
104238438Sdteske		{
105238438Sdteske			cur_prefix = tolower(substr($1, 1, 1))
106238438Sdteske			printf "'\''"
107238438Sdteske			if ( prefix != cur_prefix )
108238438Sdteske				prefix = cur_prefix
109238438Sdteske			else
110238438Sdteske				printf " "
111238438Sdteske			var = $1
112238438Sdteske			printf "%s'\'' '\''[", var
113238438Sdteske			if ( ENVIRON["_" var "_delete"] )
114238438Sdteske				printf "X"
115238438Sdteske			else
116238438Sdteske				printf " "
117238438Sdteske			printf "] "
118238438Sdteske			if ( ENVIRON["SHOW_DEFAULT_VALUE"] ) {
119238438Sdteske				default = ENVIRON["_" var "_default"]
120238438Sdteske				gsub(/'\''/, "'\''\\'\'\''", default)
121238438Sdteske				value = ENVIRON[var]
122238438Sdteske				gsub(/'\''/, "'\''\\'\'\''", value)
123238438Sdteske				printf ENVIRON["msg_default_value"] "; %s",
124238438Sdteske				       default, value
125238438Sdteske			} else if ( ENVIRON["SHOW_CONFIGURED"] ) {
126238438Sdteske				printf "%s", ENVIRON["_" var "_file"]
127238438Sdteske			} else { # SHOW_VALUE (default behavior)
128238438Sdteske				value = ENVIRON[var]
129238438Sdteske				gsub(/'\''/, "'\''\\'\'\''", value)
130238438Sdteske				printf "%s", value
131238438Sdteske			}
132238438Sdteske			printf "'\''"
133238438Sdteske			if ( ENVIRON["SHOW_DESC"] ) {
134238438Sdteske				desc = ENVIRON["_" var "_desc"]
135238438Sdteske				gsub(/'\''/, "'\''\\'\'\''", desc)
136238438Sdteske				printf " '\''%s'\''", desc
137238438Sdteske			}
138238438Sdteske			printf "\n"
139238438Sdteske		}'
140249751Sdteske	)
141249751Sdteske}
142238438Sdteske
143249751Sdteske# dialog_menu_main
144249751Sdteske#
145249751Sdteske# Display the dialog(1)-based application main menu.
146249751Sdteske#
147249751Sdteskedialog_menu_main()
148249751Sdteske{
149249751Sdteske	local hline="$hline_arrows_tab_enter"
150249751Sdteske	local prompt=""
151238438Sdteske
152249751Sdteske	#
153249751Sdteske	# [Re-]Accent the menu list before incorporating it
154249751Sdteske	#
155249751Sdteske	local rcconf_var details help menu_buf delete
156249751Sdteske	eval set -- $RCCONF_MENU_LIST
157249751Sdteske	while [ $# -gt 0 ]; do
158249751Sdteske		rcconf_var="$1" details="$2" delete=
159249751Sdteske		f_shell_escape "$details" details
160249751Sdteske		if [ "$SHOW_DESC" ]; then
161249751Sdteske			help="$3"
162249751Sdteske			f_shell_escape "$help" help
163249751Sdteske			shift 3 # rcconf_var/details/help
164249751Sdteske		else
165249751Sdteske			shift 2 # rcconf_var/details
166249751Sdteske		fi
167249751Sdteske
168249751Sdteske		# Update mark
169249751Sdteske		f_getvar _${rcconf_var# }_delete delete
170249751Sdteske		if [ "$delete" ]; then
171249751Sdteske			details="[X]${details#???}"
172249751Sdteske		else
173249751Sdteske			details="[ ]${details#???}"
174249751Sdteske		fi
175249751Sdteske
176249751Sdteske		# Update buffer with modified elements
177249751Sdteske		menu_buf="$menu_buf
178249751Sdteske		'$rcconf_var' '$details' ${SHOW_DESC:+'$help'}" # End-Quote
179249751Sdteske	done
180249751Sdteske
181249751Sdteske	local menu_list="
182249751Sdteske		'X $msg_exit_cancel'     '$msg_exit_cancel_desc'
183249751Sdteske		            ${SHOW_DESC:+'$msg_exit_cancel_help'}
184249751Sdteske		'> $msg_delete_selected' '$msg_delete_selected_desc'
185249751Sdteske		            ${SHOW_DESC:+'$msg_delete_selected_help'}
186249751Sdteske		'> $msg_all'             '$msg_all_desc'
187249751Sdteske		            ${SHOW_DESC:+'$msg_all_help'}
188249751Sdteske		'> $msg_none'            '$msg_none_desc'
189249751Sdteske		            ${SHOW_DESC:+'$msg_none_help'}
190249751Sdteske	${USE_XDIALOG:+
191249751Sdteske		'> $msg_view_details'    '$msg_view_details_desc'
192249751Sdteske		            ${SHOW_DESC:+'$msg_view_details_help'}
193249751Sdteske	}
194249751Sdteske		$menu_buf
195249751Sdteske	" # END-QUOTE
196249751Sdteske
197249751Sdteske	set -f # noglob (descriptions in $RCCONF_MENU_LIST may contain *)
198249751Sdteske
199251190Sdteske	local height width rows
200251190Sdteske	eval f_dialog_menu${SHOW_DESC:+_with_help}_size \
201251190Sdteske		height width rows      \
202251190Sdteske		\"\$DIALOG_TITLE\"     \
203251190Sdteske		\"\$DIALOG_BACKTITLE\" \
204251190Sdteske		\"\$prompt\"           \
205251190Sdteske		\"\$hline\"            \
206251190Sdteske		$menu_list
207238438Sdteske
208240768Sdteske	local dialog_menu
209240768Sdteske	dialog_menu=$( eval $DIALOG \
210249751Sdteske		--title \"\$DIALOG_TITLE\"          \
211249751Sdteske		--backtitle \"\$DIALOG_BACKTITLE\"  \
212249751Sdteske		--hline \"\$hline\"                 \
213249751Sdteske		--keep-tite                         \
214249751Sdteske		--ok-label \"\$msg_ok\"             \
215249751Sdteske		--cancel-label \"\$msg_cancel\"     \
216249751Sdteske		--help-button                       \
217249751Sdteske		--help-label \"\$msg_details\"      \
218249751Sdteske		${SHOW_DESC:+--item-help}           \
219249751Sdteske		--default-item \"\$DEFAULTITEM_$$\" \
220251190Sdteske		--menu \"\$prompt\"                 \
221251190Sdteske		$height $width $rows                \
222249751Sdteske		$menu_list                          \
223240768Sdteske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
224240768Sdteske	)
225240768Sdteske	local retval=$?
226240768Sdteske	setvar DIALOG_MENU_$$ "$dialog_menu"
227249751Sdteske
228249751Sdteske	# Only update default-item on success
229249751Sdteske	[ $retval -eq 0 ] && setvar DEFAULTITEM_$$ "$dialog_menu"
230249751Sdteske
231240768Sdteske	return $retval
232238438Sdteske}
233238438Sdteske
234249751Sdteske# dialog_menu_confirm_delete $var1 [$var2 ...]
235238438Sdteske#
236249751Sdteske# Get the user's blessing to delete one or more variables. Returns success if
237249751Sdteske# (and only-if) the user confirms (does not press ESC or Cancel/NO). Does NOT
238249751Sdteske# return the user's menu-choice.
239238438Sdteske#
240249751Sdteskedialog_menu_confirm_delete()
241238438Sdteske{
242238438Sdteske	local hline="$hline_arrows_tab_enter"
243238438Sdteske	local prompt="$msg_are_you_sure_you_want_delete_the_following"
244238438Sdteske	local var_list menu_list
245238438Sdteske
246238438Sdteske	[ $# -ge 1 ] || return $FAILURE
247238438Sdteske
248238438Sdteske	if [ $# -eq 1 ]; then
249245402Sdteske		f_noyes "$msg_are_you_sure_you_want_to_delete" "$delete_vars"
250238438Sdteske		return $?
251238438Sdteske	fi
252238438Sdteske
253238438Sdteske	var_list=$( for var in $*; do echo "$var"; done | sort -u )
254238438Sdteske	menu_list=$(
255238438Sdteske		. "$RC_DEFAULTS"
256238438Sdteske		source_rc_confs
257238438Sdteske		echo "$var_list" | awk '
258238438Sdteske		BEGIN {
259238438Sdteske			prefix = ""
260238438Sdteske		}
261238438Sdteske		{
262238438Sdteske			cur_prefix = tolower(substr($1, 1, 1))
263238438Sdteske			printf "'\''"
264238438Sdteske			if ( prefix != cur_prefix )
265238438Sdteske				prefix = cur_prefix
266238438Sdteske			else
267238438Sdteske				printf " "
268238438Sdteske			var = $1
269238438Sdteske			printf "%s'\'' '\'\''\n", var
270238438Sdteske		}'
271238438Sdteske	)
272238438Sdteske
273251190Sdteske	local height width rows
274251190Sdteske	eval f_dialog_menu_size height width rows \
275251190Sdteske	                        \"\$DIALOG_TITLE\"     \
276251190Sdteske	                        \"\$DIALOG_BACKTITLE\" \
277251190Sdteske	                        \"\$prompt\"           \
278251190Sdteske	                        \"\$hline\"            \
279251190Sdteske	                        $menu_list
280238438Sdteske
281238438Sdteske	local defaultno="defaultno"
282238438Sdteske	[ "$USE_XDIALOG" ] && defaultno="default-no"
283238438Sdteske
284249751Sdteske	eval $DIALOG \
285249751Sdteske		--title \"\$DIALOG_TITLE\"         \
286238438Sdteske		--backtitle \"\$DIALOG_BACKTITLE\" \
287238438Sdteske		--hline \"\$hline\"                \
288238438Sdteske		--$defaultno                       \
289238438Sdteske		--ok-label \"\$msg_ok\"            \
290238438Sdteske		--cancel-label \"\$msg_cancel\"    \
291251190Sdteske		--menu \"\$prompt\"                \
292251190Sdteske		$height $width $rows               \
293238438Sdteske		$menu_list                         \
294249751Sdteske		2> /dev/null
295249954Sdteske
296249954Sdteske	# Menu choice ignored; status of above command returned
297238438Sdteske}
298238438Sdteske
299238438Sdteske############################################################ MAIN
300238438Sdteske
301238438Sdteske# Incorporate rc-file if it exists
302238438Sdteske[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
303238438Sdteske
304238438Sdteske#
305238438Sdteske# Process command-line arguments
306238438Sdteske#
307250633Sdteskewhile getopts h$GETOPTS_STDARGS flag; do
308238438Sdteske	case "$flag" in
309238438Sdteske	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
310238438Sdteske	esac
311238438Sdteskedone
312238438Sdteskeshift $(( $OPTIND - 1 ))
313238438Sdteske
314238438Sdteske#
315238438Sdteske# Initialize
316238438Sdteske#
317238438Sdteskef_dialog_title "$msg_delete_startup_directives"
318238438Sdteskef_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
319238438Sdteskef_mustberoot_init
320238438Sdteske
321249751Sdteske# Genreate $RCCONF_MAP of `var desc ...' per-line (see share/rcconf.subr)
322249751Sdteskef_dialog_info "$msg_creating_rcconf_map"
323249751Sdteskef_startup_rcconf_map RCCONF_MAP
324249751Sdteske
325249751Sdteske# Generate _${var}_desc variables from $RCCONF_MAP
326249751Sdteskef_startup_rcconf_map_expand RCCONF_MAP
327249751Sdteske
328249751Sdteske# Generate RCCONF_MENU_LIST from $RCCONF_MAP
329249751Sdteskedialog_create_main
330249751Sdteske
331238438Sdteskewhile :; do
332238438Sdteske	dialog_menu_main
333238438Sdteske	retval=$?
334238438Sdteske	mtag=$( f_dialog_menutag )
335238438Sdteske
336238438Sdteske	if [ "$USE_XDIALOG" ]; then
337249751Sdteske		case "$mtag" in "> $msg_view_details")
338249751Sdteske			f_dialog_input_view_details && dialog_create_main
339238438Sdteske			continue
340238438Sdteske		esac
341238438Sdteske	elif [ $retval -eq 2 ]; then
342238438Sdteske		# The ``Help'' button (labeled "Details") was pressed
343249751Sdteske		f_dialog_input_view_details && dialog_create_main
344238438Sdteske		continue
345238438Sdteske	fi
346238438Sdteske
347238438Sdteske	[ $retval -eq 0 ] || f_die
348238438Sdteske
349238438Sdteske	case "$mtag" in
350238438Sdteske	"X $msg_exit_cancel") break ;;
351238438Sdteske	"> $msg_delete_selected")
352238438Sdteske		delete_vars=
353238438Sdteske		for var in $( f_startup_rcconf_list ); do
354238438Sdteske			[ "$( eval echo \$_${var}_delete )" ] || continue
355238438Sdteske			delete_vars="$delete_vars${delete_vars:+ }$var"
356238438Sdteske		done
357238438Sdteske		unset var # no longer needed
358249751Sdteske		if dialog_menu_confirm_delete $delete_vars; then
359238438Sdteske			f_dialog_title "$msg_info"
360238438Sdteske			f_dialog_info "$msg_deleting_selected_directives"
361238438Sdteske			f_dialog_title_restore
362238438Sdteske			for var in $delete_vars; do
363238438Sdteske				err=$( f_sysrc_delete $var 2>&1 )
364238438Sdteske				if [ $? -ne $SUCCESS ]; then
365245437Sdteske					f_dialog_msgbox "$err\n"
366238438Sdteske					break
367238438Sdteske				fi
368238438Sdteske			done
369238438Sdteske			unset var # no longer needed
370249751Sdteske			dialog_create_main
371238438Sdteske		fi
372238438Sdteske		;;
373238438Sdteske	"> $msg_all")
374238438Sdteske		for var in $( f_startup_rcconf_list ); do
375238438Sdteske			setvar _${var}_delete 1
376238438Sdteske			export _${var}_delete
377238438Sdteske		done
378238438Sdteske		unset var # no longer needed
379238438Sdteske		;;
380238438Sdteske	"> $msg_none")
381238438Sdteske		var_list=$( set | awk -F= "
382238438Sdteske			/$STARTUP_RCCONF_REGEX/ {
383238438Sdteske				if (\$1 ~ /^_[[:alpha:]_][[:alnum:]_]*_delete/)
384238438Sdteske					print \$1
385238438Sdteske			}"
386238438Sdteske		)
387238438Sdteske		[ "$var_list" ] && unset $var_list
388238438Sdteske		unset var_list # no longer needed
389238438Sdteske		;;
390238438Sdteske	*) # Anything else is a variable to edit
391238438Sdteske		var="${mtag# }"
392238438Sdteske
393238438Sdteske		# Toggle the state-variable and loop back to menu
394250317Sdteske		if f_isset _${var}_delete; then
395238438Sdteske			unset _${var}_delete
396238438Sdteske		else
397238438Sdteske			setvar _${var}_delete 1
398238438Sdteske			export _${var}_delete
399238438Sdteske		fi
400238438Sdteske		unset var # no longer needed
401238438Sdteske	esac
402238438Sdteskedone
403238438Sdteske
404238438Sdteskeexit $SUCCESS
405238438Sdteske
406238438Sdteske################################################################################
407238438Sdteske# END
408238438Sdteske################################################################################
409