xref: /freebsd-src/usr.sbin/bsdconfig/share/packages/packages.subr (revision 6d3c0798ccbe7f6d3b677eed31206efc1227be50)
187c16275SDevin Teskeif [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_SUBR=1
287c16275SDevin Teske#
322fc0210SDevin Teske# Copyright (c) 2013-2016 Devin Teske
4f8ea072aSDevin Teske# All rights reserved.
587c16275SDevin Teske#
687c16275SDevin Teske# Redistribution and use in source and binary forms, with or without
787c16275SDevin Teske# modification, are permitted provided that the following conditions
887c16275SDevin Teske# are met:
987c16275SDevin Teske# 1. Redistributions of source code must retain the above copyright
1087c16275SDevin Teske#    notice, this list of conditions and the following disclaimer.
1187c16275SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
1287c16275SDevin Teske#    notice, this list of conditions and the following disclaimer in the
1387c16275SDevin Teske#    documentation and/or other materials provided with the distribution.
1487c16275SDevin Teske#
1587c16275SDevin 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
1787c16275SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1887c16275SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1987c16275SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208e37a7c8SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2187c16275SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2287c16275SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2387c16275SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2487c16275SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2587c16275SDevin Teske# SUCH DAMAGE.
2687c16275SDevin Teske#
2787c16275SDevin Teske#
2887c16275SDevin Teske############################################################ INCLUDES
2987c16275SDevin Teske
3087c16275SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
3187c16275SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3287c16275SDevin Teskef_dprintf "%s: loading includes..." "$0"
3387c16275SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
3431185df0SDevin Teskef_include $BSDCFG_SHARE/device.subr
3531185df0SDevin Teskef_include $BSDCFG_SHARE/media/common.subr
3687c16275SDevin Teskef_include $BSDCFG_SHARE/packages/categories.subr
3787c16275SDevin Teskef_include $BSDCFG_SHARE/packages/index.subr
3895d45410SDevin Teskef_include $BSDCFG_SHARE/packages/musthavepkg.subr
391de60ff0SDevin Teskef_include $BSDCFG_SHARE/strings.subr
4087c16275SDevin Teske
4187c16275SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig"
4287c16275SDevin Teskef_include_lang $BSDCFG_LIBE/include/messages.subr
4387c16275SDevin Teske
4487c16275SDevin Teske############################################################ CONFIGURATION
4587c16275SDevin Teske
4687c16275SDevin Teske#
4787c16275SDevin Teske# How many packages to display (maximum) per dialog menubox.
4887c16275SDevin Teske#
4987c16275SDevin Teske: ${PACKAGE_MENU_PAGESIZE:=2000}
5087c16275SDevin Teske
5187c16275SDevin Teske############################################################ GLOBALS
5287c16275SDevin Teske
53996caf21SDevin Teske#
5431185df0SDevin Teske# Package extensions to try
5531185df0SDevin Teske#
56632d9a08SDevin TeskePACKAGE_EXTENSIONS=".txz .tbz .tbz2 .tgz"
5731185df0SDevin Teske
5831185df0SDevin Teske#
59996caf21SDevin Teske# Variables used to track runtime states
60996caf21SDevin Teske#
6131185df0SDevin TeskePACKAGES_DETECTED=	# Boolean (NULL/non-NULL); detected installed packages?
62996caf21SDevin TeskePACKAGE_CATEGORIES=	# List of package categories parsed from INDEX
63996caf21SDevin TeskeSELECTED_PACKAGES=	# Packages selected by user in [X]dialog(1) interface
6487c16275SDevin Teske
6587c16275SDevin Teske#
6687c16275SDevin Teske# Options
6787c16275SDevin Teske#
6887c16275SDevin Teske[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
6987c16275SDevin Teske
7087c16275SDevin Teske############################################################ FUNCTIONS
7187c16275SDevin Teske
7287c16275SDevin Teske# eval f_package_accent_category_menu $var_to_set $CATEGORY_MENU_LIST
7387c16275SDevin Teske#
7487c16275SDevin Teske# Accent the CATEGORY_MENU_LIST produced by f_index_read() (see
7587c16275SDevin Teske# packages/index.subr). Accented information includes adding an asterisk to the
7687c16275SDevin Teske# category name if its index has been cached, adding the number of installed
7787c16275SDevin Teske# packages for each category, and adding the number _selected_ packages for
7887c16275SDevin Teske# each category.
7987c16275SDevin Teske#
8087c16275SDevin Teske# NOTE: The reason `eval' is recommended/shown for the syntax above is because
8187c16275SDevin Teske# the $CATEGORY_MENU_LIST generated by f_index_read() is meant to be expanded
8287c16275SDevin Teske# prior to execution (it contains a series of pre-quoted strings which act as
8387c16275SDevin Teske# the interpolated command arguments).
8487c16275SDevin Teske#
8587c16275SDevin Teskef_package_accent_category_menu()
8687c16275SDevin Teske{
87b87d5f1fSDevin Teske	local var_to_set="$1" category cat desc help varcat menu_buf n
8887c16275SDevin Teske	shift 1 # var_to_set
8987c16275SDevin Teske	while [ $# -gt 0 ]; do
90b87d5f1fSDevin Teske		category="${1%\*}" desc="${2%%; *}" help="$3"
9187c16275SDevin Teske		shift 3 # cat/desc/help
9287c16275SDevin Teske
93b87d5f1fSDevin Teske		cat="${category# }" # Trim lead space inserted by sort-method
945cf9b06bSDevin Teske		f_str2varname "$cat" varcat
9587c16275SDevin Teske
9687c16275SDevin Teske		# Add number of installed packages for this category (if any)
9787c16275SDevin Teske		n=0
985cf9b06bSDevin Teske		case "$cat" in
995cf9b06bSDevin Teske		"$msg_all") debug= f_getvar "_All_ninstalled" n ;;
1005cf9b06bSDevin Teske		         *) debug= f_getvar "_${varcat}_ninstalled" n ;;
1015cf9b06bSDevin Teske		esac &&
1025cf9b06bSDevin Teske		[ $n -ge 1 ] && desc="$desc; $n $msg_installed_lc"
10387c16275SDevin Teske
10487c16275SDevin Teske		# Add number of selected packages for this category (if any)
10587c16275SDevin Teske		n=0
1065cf9b06bSDevin Teske		case "$cat" in
1075cf9b06bSDevin Teske		"$msg_all") debug= f_getvar "_All_nselected" n ;;
1085cf9b06bSDevin Teske		         *) debug= f_getvar "_${varcat}_nselected" n ;;
1095cf9b06bSDevin Teske		esac &&
1105cf9b06bSDevin Teske		[ $n -ge 1 ] && desc="$desc; $n $msg_selected"
1115cf9b06bSDevin Teske
112fe9ef40cSDevin Teske		# Re-Add asterisk to the category if its index has been cached
113b87d5f1fSDevin Teske		f_isset _index_page_${varcat}_1 && category="$category*"
11487c16275SDevin Teske
11587c16275SDevin Teske		# Update buffer with modified elements
11687c16275SDevin Teske		menu_buf="$menu_buf
117b87d5f1fSDevin Teske		'$category' '$desc' '$help'" # End-Quote
11887c16275SDevin Teske	done
11987c16275SDevin Teske	setvar "$var_to_set" "$menu_buf" # return our buffer
12087c16275SDevin Teske}
12187c16275SDevin Teske
12287c16275SDevin Teske# f_package_select $package ...
12387c16275SDevin Teske#
12487c16275SDevin Teske# Add $package to the list of tracked/selected packages. If $package is already
12587c16275SDevin Teske# being tracked (already apears in $SELECTED_PACKAGES), this function amounts
12687c16275SDevin Teske# to having no effect.
12787c16275SDevin Teske#
12887c16275SDevin Teskef_package_select()
12987c16275SDevin Teske{
13087c16275SDevin Teske	local package pkgsel
13187c16275SDevin Teske	while [ $# -gt 0 ]; do
13287c16275SDevin Teske		package="$1"
13387c16275SDevin Teske		shift 1 # package
13487c16275SDevin Teske		for pkgsel in $SELECTED_PACKAGES; do
135f677a9e2SDevin Teske			[ "$package" = "$pkgsel" ] && return $SUCCESS
13687c16275SDevin Teske		done
13787c16275SDevin Teske		SELECTED_PACKAGES="$SELECTED_PACKAGES $package"
13802af913fSDevin Teske		f_dprintf "Added %s to selection list" "$package"
13987c16275SDevin Teske	done
14087c16275SDevin Teske	SELECTED_PACKAGES="${SELECTED_PACKAGES# }" # Trim leading space
14187c16275SDevin Teske}
14287c16275SDevin Teske
14387c16275SDevin Teske# f_package_deselect $package ...
14487c16275SDevin Teske#
145ec65e4f8SPedro F. Giffuni# Remove $package from the list of tracked/selected packages. If $package is
14687c16275SDevin Teske# not being tracked (doesn't appear in $SELECTED_PACKAGES), this function
14787c16275SDevin Teske# amounts to having no effet.
14887c16275SDevin Teske#
14987c16275SDevin Teskef_package_deselect()
15087c16275SDevin Teske{
15187c16275SDevin Teske	local package pkgsel
15287c16275SDevin Teske	while [ $# -gt 1 ]; do
15387c16275SDevin Teske		local new_list=""
15487c16275SDevin Teske		package="$1"
15587c16275SDevin Teske		shift 1 # package
15687c16275SDevin Teske		for pkgsel in $SELECTED_PACKAGES; do
15787c16275SDevin Teske			[ "$pkgsel" = "$package" ] && continue
15887c16275SDevin Teske			new_list="$new_list${new_list:+ }$pkgsel"
15987c16275SDevin Teske		done
16087c16275SDevin Teske		SELECTED_PACKAGES="$new_list"
16102af913fSDevin Teske		f_dprintf "Removed %s from selection list" "$package"
16287c16275SDevin Teske	done
16387c16275SDevin Teske}
16487c16275SDevin Teske
16587c16275SDevin Teske# f_package_detect_installed
16687c16275SDevin Teske#
167632d9a08SDevin Teske# Detect installed packages. Currently this uses pkg-query(8) for querying
16887c16275SDevin Teske# entries and marks each entry as an installed/selected package.
16987c16275SDevin Teske#
17087c16275SDevin Teskef_package_detect_installed()
17187c16275SDevin Teske{
172632d9a08SDevin Teske	local package varpkg
173632d9a08SDevin Teske	for package in $( pkg query "%n-%v" ); do
17487c16275SDevin Teske		f_str2varname $package varpkg
17587c16275SDevin Teske		export _mark_$varpkg=X # exported for awk(1) ENVIRON[]
17687c16275SDevin Teske		f_package_select $package
17787c16275SDevin Teske	done
17887c16275SDevin Teske}
17987c16275SDevin Teske
18087c16275SDevin Teske# f_package_calculate_totals
18187c16275SDevin Teske#
18287c16275SDevin Teske# Calculate number of installed/selected packages for each category listed in
18387c16275SDevin Teske# $PACKAGE_CATEGORIES (the number of installed packages for $category is stored
18487c16275SDevin Teske# as $_${varcat}_ninstalled -- where $varcat is the product of `f_str2varname
18587c16275SDevin Teske# $category varcat' -- and number selected packages as $_${varcat}_nselected).
18687c16275SDevin Teske# Also calculates the total number of installed/selected packages stored as
18787c16275SDevin Teske# $_All_ninstalled and $_All_nselected.
18887c16275SDevin Teske#
189ec65e4f8SPedro F. Giffuni# Calculations are performed by checking "marks". A "mark" is stored as
19087c16275SDevin Teske# $_mark_$varpkg -- where $varpkg is the product of `f_str2varname $package
19187c16275SDevin Teske# varpkg'. A mark can be "X" for an installed package, `I' for a package that
19287c16275SDevin Teske# is marked for installation, "R" for a package that is marked for re-install,
19387c16275SDevin Teske# and "U" for a package that is marked for uninstallation. If a package mark is
19487c16275SDevin Teske# NULL or a single space (e.g., " "), the package is considered to be NOT
19587c16275SDevin Teske# selected (and therefore does not increment the counts calculated herein).
19687c16275SDevin Teske#
19787c16275SDevin Teskef_package_calculate_totals()
19887c16275SDevin Teske{
19987c16275SDevin Teske	local pkg varpkg mark cat varcat pkgcat n tselected=0 tinstalled=0
20087c16275SDevin Teske	for cat in $PACKAGE_CATEGORIES; do
20187c16275SDevin Teske		f_str2varname $cat varcat
20287c16275SDevin Teske		setvar _${varcat}_ninstalled=0
20387c16275SDevin Teske		setvar _${varcat}_nselected=0
20487c16275SDevin Teske	done
20587c16275SDevin Teske	for pkg in $SELECTED_PACKAGES; do
20687c16275SDevin Teske		f_str2varname $pkg varpkg
20787c16275SDevin Teske		mark=
20887c16275SDevin Teske		f_getvar _mark_$varpkg mark
20987c16275SDevin Teske		case "$mark" in
21087c16275SDevin Teske		""|" ") : ;;
21187c16275SDevin Teske		X) tinstalled=$(( $tinstalled + 1 )) ;;
21287c16275SDevin Teske		*) tselected=$(( $tselected + 1 ))
21387c16275SDevin Teske		esac
21487c16275SDevin Teske		f_getvar _categories_$varpkg pkgcat
21587c16275SDevin Teske		for cat in $pkgcat; do
21687c16275SDevin Teske			f_str2varname $cat varcat
21787c16275SDevin Teske			case "$mark" in
21887c16275SDevin Teske			""|" ") : ;;
21987c16275SDevin Teske			X) debug= f_getvar _${varcat}_ninstalled n
22087c16275SDevin Teske			   setvar _${varcat}_ninstalled $(( $n + 1 )) ;;
22187c16275SDevin Teske			*) debug= f_getvar _${varcat}_nselected n
22287c16275SDevin Teske			   setvar _${varcat}_nselected $(( $n + 1 ))
22387c16275SDevin Teske			esac
22487c16275SDevin Teske		done
22587c16275SDevin Teske	done
22687c16275SDevin Teske	_All_nselected=$tselected
22787c16275SDevin Teske	_All_ninstalled=$tinstalled
22887c16275SDevin Teske}
22987c16275SDevin Teske
23087c16275SDevin Teske# f_package_calculate_rundeps
23187c16275SDevin Teske#
23287c16275SDevin Teske# Update package dependencies by first unmarking all dependencies and then
23387c16275SDevin Teske# re-marking all dependencies of packages marked for either install ("I") or
23487c16275SDevin Teske# re-install ("R").
23587c16275SDevin Teske#
23687c16275SDevin Teskef_package_calculate_rundeps()
23787c16275SDevin Teske{
23887c16275SDevin Teske	local pkg varpkg mark rundeps dep vardep
23987c16275SDevin Teske
24087c16275SDevin Teske	#
24187c16275SDevin Teske	# First unmark all the existing run-dependencies
24287c16275SDevin Teske	#
24387c16275SDevin Teske	f_dprintf "Unselecting package run-dependencies..."
24487c16275SDevin Teske	for pkg in $SELECTED_PACKAGES; do
24587c16275SDevin Teske		f_str2varname $pkg varpkg
24687c16275SDevin Teske		mark=
24787c16275SDevin Teske		debug= f_getvar _mark_$varpkg mark
24887c16275SDevin Teske		# Only unmark if it's marked as a Dependency
24987c16275SDevin Teske		if [ "$mark" = "D" ]; then
25087c16275SDevin Teske			f_dprintf "%s unselected" $pkg
25187c16275SDevin Teske			unset _mark_$varpkg
25287c16275SDevin Teske			f_package_deselect $pkg
25387c16275SDevin Teske		fi
25487c16275SDevin Teske	done
25587c16275SDevin Teske
25687c16275SDevin Teske	#
25787c16275SDevin Teske	# Processes selected packages, adding dependencies
25887c16275SDevin Teske	#
25987c16275SDevin Teske	f_dprintf "Re-selecting package run-dependencies..."
26087c16275SDevin Teske	for pkg in $SELECTED_PACKAGES; do
26187c16275SDevin Teske		f_str2varname $pkg varpkg
26287c16275SDevin Teske		mark=
26387c16275SDevin Teske		debug= f_getvar _mark_$varpkg mark
26487c16275SDevin Teske		# Skip pkg unless marked for [Re-]Install
26587c16275SDevin Teske		[ "$mark" = "I" -o "$mark" = "R" ] || continue
26687c16275SDevin Teske		f_getvar _rundeps_$varpkg rundeps
26787c16275SDevin Teske		for dep in $rundeps; do
26887c16275SDevin Teske			f_str2varname $dep vardep
26987c16275SDevin Teske			mark=
27087c16275SDevin Teske			debug= f_getvar _mark_$vardep mark
27187c16275SDevin Teske			# Skip dep if already marked
27287c16275SDevin Teske			[ "${mark:- }" = " " ] || continue
27387c16275SDevin Teske			export _mark_$vardep="D"
27487c16275SDevin Teske			f_package_select $dep
27587c16275SDevin Teske		done
27687c16275SDevin Teske	done
27787c16275SDevin Teske
27887c16275SDevin Teske	f_dprintf "Finished recalculating dependencies."
27987c16275SDevin Teske}
28087c16275SDevin Teske
28187c16275SDevin Teske# f_package_menu_categories $var_to_set $defaultitem
28287c16275SDevin Teske#
28387c16275SDevin Teske# Dislay the menu of package categories, complete with package counts for each
28487c16275SDevin Teske# category, accents, and other miscellany. If $defaultitem is non-NULL and
28587c16275SDevin Teske# matches one of the existing menu-items, it will be pre-highlighted in the
286fd962ac6SDevin Teske# menu dialog (HINT: Use f_dialog_menutag_fetch() to populate a local variable
287fd962ac6SDevin Teske# that is passed as $defaultitem to highlight the user's last selection).
28887c16275SDevin Teske#
28987c16275SDevin Teskef_package_menu_categories()
29087c16275SDevin Teske{
291052f8969SDevin Teske	local var_to_get="$1" defaultitem="$2"
292052f8969SDevin Teske	local prompt="$msg_please_select_a_category_to_display"
293052f8969SDevin Teske	local menu_list="
294052f8969SDevin Teske		'> $msg_review' '$msg_review_desc' '$msg_review_help'
295052f8969SDevin Teske	" # End-Quote
296052f8969SDevin Teske	local hline=
29787c16275SDevin Teske
29887c16275SDevin Teske	f_package_calculate_rundeps
29987c16275SDevin Teske		# updates package mark variables and SELECTED_PACKAGES
30087c16275SDevin Teske	f_package_calculate_totals
30187c16275SDevin Teske		# creates _{varcat}_ninstalled and _{varcat}_nselected
30287c16275SDevin Teske
303052f8969SDevin Teske	local category_list
304f677a9e2SDevin Teske	debug= f_getvar "$var_to_get" category_list || return $DIALOG_CANCEL
30587c16275SDevin Teske
30687c16275SDevin Teske	# Accent the category menu list with ninstalled/nselected
30787c16275SDevin Teske	eval f_package_accent_category_menu category_list $category_list
30887c16275SDevin Teske
309052f8969SDevin Teske	# Add list of categories to menu list
310052f8969SDevin Teske	menu_list="$menu_list $category_list"
31187c16275SDevin Teske
312fd962ac6SDevin Teske	local height width rows
313367a23a7SDevin Teske	eval f_dialog_menu_with_help_size height width rows \
31487c16275SDevin Teske	                                  \"\$DIALOG_TITLE\"     \
31587c16275SDevin Teske	                                  \"\$DIALOG_BACKTITLE\" \
31687c16275SDevin Teske	                                  \"\$prompt\"           \
31787c16275SDevin Teske	                                  \"\$hline\"            \
318367a23a7SDevin Teske	                                  $menu_list
319fd962ac6SDevin Teske	local menu_choice
320fd962ac6SDevin Teske	menu_choice=$( eval $DIALOG \
32187c16275SDevin Teske		--title \"\$DIALOG_TITLE\"         \
32287c16275SDevin Teske		--backtitle \"\$DIALOG_BACKTITLE\" \
32387c16275SDevin Teske		--hline \"\$hline\"                \
32487c16275SDevin Teske		--item-help                        \
32587c16275SDevin Teske		--default-item \"\$defaultitem\"   \
32687c16275SDevin Teske		--ok-label \"$msg_select\"         \
32787c16275SDevin Teske		--cancel-label \"$msg_cancel\"     \
328367a23a7SDevin Teske		--menu \"\$prompt\"                \
329367a23a7SDevin Teske		$height $width $rows               \
33087c16275SDevin Teske		$menu_list                         \
33187c16275SDevin Teske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
33287c16275SDevin Teske	)
33387c16275SDevin Teske	local retval=$?
334fd962ac6SDevin Teske	f_dialog_menutag_store -s "$menu_choice"
33587c16275SDevin Teske	return $retval
33687c16275SDevin Teske}
33787c16275SDevin Teske
33887c16275SDevin Teske# f_package_index_get_page $category $page [$var_to_set [$var_to_get]]
33987c16275SDevin Teske#
34087c16275SDevin Teske# Obtain a [potentially cached] page of the INDEX file for a given $category.
34187c16275SDevin Teske# If $page is 1 and the cache has not yet been generated, the cache-generating
34287c16275SDevin Teske# function f_index_extract_pages() (above) is called to generate all pages
34387c16275SDevin Teske# (not just the requested page) in cache before returning the requested page.
34487c16275SDevin Teske# If $page is not 1 and there is no cached page, failure status is returned.
34587c16275SDevin Teske#
34687c16275SDevin Teskef_package_index_get_page()
34787c16275SDevin Teske{
34887c16275SDevin Teske	local category="$1" page="$2" var_to_set="$3" var_to_get="$4" varcat
34987c16275SDevin Teske	f_str2varname "$category" varcat
35087c16275SDevin Teske	if ! debug= f_getvar "_index_page_${varcat}_$page" $var_to_set &&
35187c16275SDevin Teske	   [ "$page" = "1" ]
35287c16275SDevin Teske	then
35387c16275SDevin Teske		f_show_info "$msg_building_package_menus"
35487c16275SDevin Teske		local pagesize="$PACKAGE_MENU_PAGESIZE"
35587c16275SDevin Teske		f_index_extract_pages "${var_to_get:-PACKAGE_INDEX}" \
35687c16275SDevin Teske			_index_page_${varcat} "$pagesize" "$category"
35787c16275SDevin Teske		debug= f_getvar _index_page_${varcat}_$page $var_to_set
35887c16275SDevin Teske
35987c16275SDevin Teske		# Update category default-item because now we're cached
36087c16275SDevin Teske		[ $page -eq 1 ] &&
36187c16275SDevin Teske		    category_defaultitem="${category_defaultitem%\*}*"
36287c16275SDevin Teske	else
36387c16275SDevin Teske		return $FAILURE
36487c16275SDevin Teske	fi
36587c16275SDevin Teske}
36687c16275SDevin Teske
36787c16275SDevin Teske# f_package_menu_select $category [$page [$defaultitem]]
36887c16275SDevin Teske#
36987c16275SDevin Teske# Display list of packages for $category, optionally $page N and with a default
37087c16275SDevin Teske# item selected. If $page is omitted, the first page is displayed (but this
37187c16275SDevin Teske# only matters if there are multiple pages; which is determined by the global
37287c16275SDevin Teske# maximum $PACKAGE_MENU_PAGESIZE).
37387c16275SDevin Teske#
374b5bd0bacSDevin Teske# On success, if the user doesn't press ESC or choose Cancel, use
375b5bd0bacSDevin Teske# f_dialog_menuitem_fetch() to populate a local variable with the item (not
376b5bd0bacSDevin Teske# tag) corresponding to the user's selection. The tag portion of the user's
377b5bd0bacSDevin Teske# selection is available through f_dialog_menutag_fetch().
37887c16275SDevin Teske#
37987c16275SDevin Teskef_package_menu_select()
38087c16275SDevin Teske{
381*6d3c0798SBaptiste Daroussin	local __funcname=f_package_menu_deselect
382052f8969SDevin Teske	local category="$1" page="${2:-1}"
383052f8969SDevin Teske	local prompt= # Calculated below
384052f8969SDevin Teske	local menu_list # Calculated below
385052f8969SDevin Teske	local defaultitem="$3"
386052f8969SDevin Teske	local hline="$hline_arrows_tab_punc_enter"
38787c16275SDevin Teske
388f677a9e2SDevin Teske	f_isinteger "$page" || return $DIALOG_CANCEL
38987c16275SDevin Teske
390052f8969SDevin Teske	local varcat
39187c16275SDevin Teske	f_str2varname "$category" varcat
39287c16275SDevin Teske
39387c16275SDevin Teske	# Get number of packages for this category
394052f8969SDevin Teske	local npkgs=0
39587c16275SDevin Teske	case "$category" in
3965cf9b06bSDevin Teske	"$msg_all"|"") npkgs="${_npkgs:-0}" ;;
39787c16275SDevin Teske	*) f_getvar _npkgs_$varcat npkgs
39887c16275SDevin Teske	esac
39987c16275SDevin Teske
40087c16275SDevin Teske	# Calculate number of pages
401052f8969SDevin Teske	local npages=$(( ${npkgs:=0} / $PACKAGE_MENU_PAGESIZE ))
40287c16275SDevin Teske
40387c16275SDevin Teske	# Add a page to the pagecount if not evenly divisible
40487c16275SDevin Teske	[ $(( $npages * $PACKAGE_MENU_PAGESIZE )) -lt $npkgs ] &&
40587c16275SDevin Teske		npages=$(( $npages + 1 ))
40687c16275SDevin Teske
40787c16275SDevin Teske	# Print some debugging information
40887c16275SDevin Teske	f_dprintf "f_package_menu_select: category=[%s] npkgs=%u npages=%u" \
40987c16275SDevin Teske	          "$category" "$npkgs" "$npages"
41087c16275SDevin Teske
41187c16275SDevin Teske	local add_prev="" add_next=""
41287c16275SDevin Teske	local previous_page="$msg_previous_page" next_page="$msg_next_page"
41387c16275SDevin Teske	if [ $page -gt 1 ]; then
41487c16275SDevin Teske		add_prev=1
41587c16275SDevin Teske		# Accent the `Previous Page' item with an asterisk
41687c16275SDevin Teske		# if the page-before-previous is loaded/cached
41787c16275SDevin Teske		f_isset _index_page_${varcat}_$(( $page - 1 )) &&
41887c16275SDevin Teske			previous_page="$previous_page*"
41987c16275SDevin Teske	fi
42087c16275SDevin Teske	if [ $page -lt $npages ]; then
42187c16275SDevin Teske		add_next=1
42287c16275SDevin Teske		# Accent the `Next Page' item with an asterisk
42387c16275SDevin Teske		# if the page-after-next is loaded/cached
42487c16275SDevin Teske		f_isset _index_page_${varcat}_$(( $page + 1 )) &&
42587c16275SDevin Teske			next_page="$next_page*"
42687c16275SDevin Teske	fi
42787c16275SDevin Teske
428*6d3c0798SBaptiste Daroussin	local index_page __index
429*6d3c0798SBaptiste Daroussin	if [ "$category" = "$msg_all" ]; then
430*6d3c0798SBaptiste Daroussin		f_eval_catch -k __index $__funcname pkg \
431*6d3c0798SBaptiste Daroussin			"pkg rquery -a '%s'"  "%n|%o||%c"
432*6d3c0798SBaptiste Daroussin	else
433*6d3c0798SBaptiste Daroussin		f_eval_catch -k __index $__funcname pkg \
434*6d3c0798SBaptiste Daroussin			"pkg rquery -g '%s' '%s/\*'"  "%n|%o||%c" "$category"
435*6d3c0798SBaptiste Daroussin	fi
436*6d3c0798SBaptiste Daroussin	f_package_index_get_page "$category" $page index_page __index
437052f8969SDevin Teske
43887c16275SDevin Teske	menu_list="
43987c16275SDevin Teske		${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}}
44087c16275SDevin Teske		${add_next:+'> $next_page' '' ${SHOW_DESC:+''}}
44187c16275SDevin Teske	$(
44287c16275SDevin Teske		export SHOW_DESC
44387c16275SDevin Teske		export VALID_VARNAME_CHARS
44487c16275SDevin Teske		echo "$index_page" | awk -F'|' -v view="port" '
44587c16275SDevin Teske		BEGIN {
44687c16275SDevin Teske			valid_chars = ENVIRON["VALID_VARNAME_CHARS"]
44787c16275SDevin Teske			prefix = ""
44887c16275SDevin Teske		}
44987c16275SDevin Teske		{
45087c16275SDevin Teske			cur_prefix = tolower(substr($1, 1, 1))
45187c16275SDevin Teske			printf "'\''"
45287c16275SDevin Teske			if ( prefix != cur_prefix )
45387c16275SDevin Teske				prefix = cur_prefix
45487c16275SDevin Teske			else
45587c16275SDevin Teske				printf " "
45687c16275SDevin Teske			package = $1
45787c16275SDevin Teske			if ( view == "port" )
45887c16275SDevin Teske				desc = $2
45987c16275SDevin Teske			varpkg = package
46087c16275SDevin Teske			gsub("[^" valid_chars "]", "_", varpkg)
46187c16275SDevin Teske			mark = ENVIRON["_mark_" varpkg]
46287c16275SDevin Teske			if ( ! mark ) mark = " "
46387c16275SDevin Teske			printf "%s'\'' '\''[%c] %s'\''",
46487c16275SDevin Teske			       package, mark, desc
46587c16275SDevin Teske			if ( ENVIRON["SHOW_DESC"] ) {
46687c16275SDevin Teske				help = $4
46787c16275SDevin Teske				gsub(/'\''/, "'\''\\'\'\''", help)
46887c16275SDevin Teske				printf " '\''%s'\''", help
46987c16275SDevin Teske			}
47087c16275SDevin Teske			printf "\n"
47187c16275SDevin Teske		}'
47287c16275SDevin Teske	)
47387c16275SDevin Teske		${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}}
47487c16275SDevin Teske		${add_next:+'> $next_page' '' ${SHOW_DESC:+''}}
47587c16275SDevin Teske	" # End-Quote
47687c16275SDevin Teske
4775cf9b06bSDevin Teske	# Accept/Translate i18n "All" but other category names must
4785cf9b06bSDevin Teske	# match tree definitions from INDEX, ports, FTP, etc.
4795cf9b06bSDevin Teske	case "$category" in
4805cf9b06bSDevin Teske	"$msg_all"|"") f_category_desc_get "All" prompt ;;
4815cf9b06bSDevin Teske	            *) f_category_desc_get "$category" prompt ;;
4825cf9b06bSDevin Teske	esac
483d4ae33f0SDevin Teske	f_sprintf prompt "%s $msg_page_of_npages" "$prompt" "$page" "$npages"
48487c16275SDevin Teske
485367a23a7SDevin Teske	local mheight mwidth mrows
48683822902SDevin Teske	eval f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \
487367a23a7SDevin Teske	        	\"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \
488367a23a7SDevin Teske	        	\"\$prompt\" \"\$hline\" $menu_list
489367a23a7SDevin Teske	local iheight iwidth
490367a23a7SDevin Teske	f_dialog_infobox_size iheight iwidth \
491367a23a7SDevin Teske	         	"$DIALOG_TITLE" "$DIALOG_BACKTITLE" \
492367a23a7SDevin Teske	         	"$msg_processing_selection"
493fd962ac6SDevin Teske
494fd962ac6SDevin Teske	local menu_choice
495fd962ac6SDevin Teske	menu_choice=$( eval $DIALOG \
49687c16275SDevin Teske		--title \"\$DIALOG_TITLE\"         \
49787c16275SDevin Teske		--backtitle \"\$DIALOG_BACKTITLE\" \
49887c16275SDevin Teske		--hline \"\$hline\"                \
49987c16275SDevin Teske		--keep-tite                        \
50087c16275SDevin Teske		--ok-label \"$msg_select\"         \
50187c16275SDevin Teske		--cancel-label \"$msg_back\"       \
50287c16275SDevin Teske		${SHOW_DESC:+--item-help}          \
50387c16275SDevin Teske		--default-item \"\$defaultitem\"   \
504367a23a7SDevin Teske		--menu \"\$prompt\"                \
505367a23a7SDevin Teske		$mheight $mwidth $mrows            \
50687c16275SDevin Teske		$menu_list                         \
50787c16275SDevin Teske		--and-widget                       \
50887c16275SDevin Teske		${USE_XDIALOG:+--no-buttons}       \
509367a23a7SDevin Teske		--infobox \"\$msg_processing_selection\" \
510367a23a7SDevin Teske		$iheight $iwidth                   \
51187c16275SDevin Teske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
51287c16275SDevin Teske	)
51387c16275SDevin Teske	local retval=$?
514fd962ac6SDevin Teske	f_dialog_data_sanitize menu_choice
515fd962ac6SDevin Teske	f_dialog_menutag_store "$menu_choice"
51687c16275SDevin Teske
517f677a9e2SDevin Teske	if [ $retval -eq $DIALOG_OK ]; then
518fd962ac6SDevin Teske		local item
51987c16275SDevin Teske		item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \
520fd962ac6SDevin Teske		             	\"\$menu_choice\" $menu_list )
521b5bd0bacSDevin Teske		f_dialog_menuitem_store "$item"
52287c16275SDevin Teske	fi
52387c16275SDevin Teske
52487c16275SDevin Teske	return $retval
52587c16275SDevin Teske}
52687c16275SDevin Teske
52787c16275SDevin Teske# f_package_menu_deselect $package
52887c16275SDevin Teske#
52987c16275SDevin Teske# Display a menu, asking the user what they would like to do with $package
53087c16275SDevin Teske# with regard to "deselecting" an already installed package. Choices include
53187c16275SDevin Teske# uninstall, re-install, or cancel (leave $package marked as installed).
53287c16275SDevin Teske# Returns success if the user does not press ESC or choose Cnacel. Use the
533fd962ac6SDevin Teske# f_dialog_menutag_fetch() function upon success to retrieve the user's choice.
53487c16275SDevin Teske#
53587c16275SDevin Teskef_package_menu_deselect()
53687c16275SDevin Teske{
537052f8969SDevin Teske	local package="$1"
538052f8969SDevin Teske	local prompt # Calculated below
539052f8969SDevin Teske	local menu_list="
54087c16275SDevin Teske		'X $msg_installed' '$msg_installed_desc'
54187c16275SDevin Teske		'R $msg_reinstall' '$msg_reinstall_desc'
54287c16275SDevin Teske		'U $msg_uninstall' '$msg_uninstall_desc'
54387c16275SDevin Teske	" # End-Quote
544052f8969SDevin Teske	local hline="$hline_alnum_arrows_punc_tab_enter"
545052f8969SDevin Teske
546d4ae33f0SDevin Teske	f_sprintf prompt "$msg_what_would_you_like_to_do_with" "$package"
547367a23a7SDevin Teske
548367a23a7SDevin Teske	local height width rows
549367a23a7SDevin Teske	eval f_dialog_menu_size height width rows \
55087c16275SDevin Teske	                        \"\$DIALOG_TITLE\"     \
55187c16275SDevin Teske	                        \"\$DIALOG_BACKTITLE\" \
55287c16275SDevin Teske	                        \"\$prompt\"           \
55387c16275SDevin Teske	                        \"\$hline\"            \
554367a23a7SDevin Teske	                        $menu_list
555fd962ac6SDevin Teske	local menu_choice
556fd962ac6SDevin Teske	menu_choice=$( eval $DIALOG \
55787c16275SDevin Teske		--title \"\$DIALOG_TITLE\"         \
55887c16275SDevin Teske		--backtitle \"\$DIALOG_BACKTITLE\" \
55987c16275SDevin Teske		--hline \"\$hline\"                \
56087c16275SDevin Teske		--ok-label \"$msg_select\"         \
56187c16275SDevin Teske		--cancel-label \"$msg_cancel\"     \
562367a23a7SDevin Teske		--menu \"\$prompt\"                \
563367a23a7SDevin Teske		$height $width $rows               \
56487c16275SDevin Teske		$menu_list                         \
56587c16275SDevin Teske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
56687c16275SDevin Teske	)
56787c16275SDevin Teske	local retval=$?
568fd962ac6SDevin Teske	f_dialog_menutag_store -s "$menu_choice"
56987c16275SDevin Teske	return $retval
57087c16275SDevin Teske}
57187c16275SDevin Teske
57287c16275SDevin Teske# f_package_review
57387c16275SDevin Teske#
57487c16275SDevin Teske# Display a review screen, showing selected packages and what they are marked
57587c16275SDevin Teske# for, before proceeding (if the user does not press ESC or choose Cancel) to
57687c16275SDevin Teske# operate on each selection. Returns error if no packages have been selected,
57787c16275SDevin Teske# or the user has pressed ESC, or if they have chosen Cancel.
57887c16275SDevin Teske#
57987c16275SDevin Teskef_package_review()
58087c16275SDevin Teske{
58184873facSDevin Teske	local funcname=f_package_review
582052f8969SDevin Teske	local prompt # Calculated below
583052f8969SDevin Teske	local menu_list # Calculated below
58487c16275SDevin Teske	local hline="$hline_alnum_arrows_punc_tab_enter"
585052f8969SDevin Teske
58684873facSDevin Teske	f_dprintf "$funcname: SELECTED_PACKAGES=[%s]" "$SELECTED_PACKAGES"
587052f8969SDevin Teske
588d4ae33f0SDevin Teske	f_sprintf prompt "$msg_reviewing_selected_packages" "$_All_nselected"
589052f8969SDevin Teske
590052f8969SDevin Teske	local package varpkg mark
59187c16275SDevin Teske	for package in $SELECTED_PACKAGES; do
59287c16275SDevin Teske		mark=
59387c16275SDevin Teske		f_str2varname "$package" varpkg
59487c16275SDevin Teske		f_getvar _mark_$varpkg mark
59587c16275SDevin Teske		[ "$mark" -a ! "${mark#[IRUD]}" ] || continue
59687c16275SDevin Teske		menu_list="$menu_list
59787c16275SDevin Teske			'$mark' '$package'
59887c16275SDevin Teske		" # End-Quote
59987c16275SDevin Teske	done
60087c16275SDevin Teske	if [ ! "$menu_list" ]; then
60187c16275SDevin Teske		f_show_msg "$msg_no_packages_were_selected_for_extraction"
602f677a9e2SDevin Teske		return $DIALOG_CANCEL # Might have selected this by accident
60387c16275SDevin Teske	fi
60487c16275SDevin Teske	menu_list=$( echo "$menu_list" | sort )
605367a23a7SDevin Teske
606367a23a7SDevin Teske	local height width rows
607367a23a7SDevin Teske	eval f_dialog_menu_size height width rows \
60887c16275SDevin Teske	                        \"\$DIALOG_TITLE\"     \
60987c16275SDevin Teske	                        \"\$DIALOG_BACKTITLE\" \
61087c16275SDevin Teske	                        \"\$prompt\"           \
61187c16275SDevin Teske	                        \"\$hline\"            \
612367a23a7SDevin Teske	                        $menu_list
613367a23a7SDevin Teske
614fd962ac6SDevin Teske	# Show the review menu (ignore menu choice)
615fd962ac6SDevin Teske	eval $DIALOG \
61687c16275SDevin Teske		--title \"\$DIALOG_TITLE\"         \
61787c16275SDevin Teske		--backtitle \"\$DIALOG_BACKTITLE\" \
61887c16275SDevin Teske		--hline \"\$hline\"                \
61987c16275SDevin Teske		--ok-label \"\$msg_proceed\"       \
62087c16275SDevin Teske		--cancel-label \"\$msg_cancel\"    \
621367a23a7SDevin Teske		--menu \"\$prompt\"                \
622367a23a7SDevin Teske		$height $width $rows               \
62387c16275SDevin Teske		$menu_list                         \
624c6f73e30SDevin Teske		2> /dev/null || return $?
625c6f73e30SDevin Teske			# Return if the user pressed ESC or chose Cancel/No
62687c16275SDevin Teske
62787c16275SDevin Teske	#
628c6f73e30SDevin Teske	# Process each of the selected packages:
629dbc750a5SDevin Teske	# + First, process packages marked for Install.
630dbc750a5SDevin Teske	# + Second, process packages marked for Re-install.
631c6f73e30SDevin Teske	# + Finally, process packages marked for Uninstall.
63287c16275SDevin Teske	#
633c6f73e30SDevin Teske	for package in $SELECTED_PACKAGES; do
634c6f73e30SDevin Teske		mark=
635c6f73e30SDevin Teske		f_str2varname "$package" varpkg
63602af913fSDevin Teske		debug= f_getvar _mark_$varpkg mark
637c6f73e30SDevin Teske		[ "$mark" = "I" ] || continue
63884873facSDevin Teske		f_dprintf "$funcname: Installing %s package" "$package"
6394254e87dSDevin Teske		f_package_add "$package"
640c6f73e30SDevin Teske	done
641c6f73e30SDevin Teske	for package in $SELECTED_PACKAGES; do
642c6f73e30SDevin Teske		mark=
643c6f73e30SDevin Teske		f_str2varname "$package" varpkg
64402af913fSDevin Teske		debug= f_getvar _mark_$varpkg mark
645c6f73e30SDevin Teske		[ "$mark" = "R" ] || continue
64684873facSDevin Teske		f_dprintf "$funcname: Reinstalling %s package" "$package"
64752d41f91SDevin Teske		f_package_reinstall "$package"
648c6f73e30SDevin Teske	done
649c6f73e30SDevin Teske	for package in $SELECTED_PACKAGES; do
650c6f73e30SDevin Teske		mark=
651c6f73e30SDevin Teske		f_str2varname "$package" varpkg
65202af913fSDevin Teske		debug= f_getvar _mark_$varpkg mark
653c6f73e30SDevin Teske		[ "$mark" = "U" ] || continue
65484873facSDevin Teske		f_dprintf "$funcname: Uninstalling %s package" "$package"
655542dd84bSDevin Teske		f_package_delete "$package" || continue
656c6f73e30SDevin Teske		f_package_deselect "$package"
657c6f73e30SDevin Teske	done
658c6f73e30SDevin Teske
659f677a9e2SDevin Teske	return $DIALOG_OK
66087c16275SDevin Teske}
66187c16275SDevin Teske
66287c16275SDevin Teske# f_package_config
66387c16275SDevin Teske#
66487c16275SDevin Teske# Allow the user to configure packages and install them. Initially, a list of
66587c16275SDevin Teske# package categories is loaded/displayed. When the user selects a category,
66687c16275SDevin Teske# the menus for that category are built (unlike sysinstall which built all
66787c16275SDevin Teske# category menus up-front -- which also took forever, despite the fact that
66887c16275SDevin Teske# few people visit more than a couple of categories each time).
66987c16275SDevin Teske#
67087c16275SDevin Teskef_package_config()
67187c16275SDevin Teske{
67287c16275SDevin Teske	# Did we get an INDEX?
67395d45410SDevin Teske	f_index_initialize || return $FAILURE
67487c16275SDevin Teske		# Creates following variables (indirectly via f_index_read())
67587c16275SDevin Teske		#   CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
67687c16275SDevin Teske		#   PACKAGE_CATEGORIES _npkgs
67787c16275SDevin Teske
67822fc0210SDevin Teske	f_show_info "$msg_building_package_main_menu"
67922fc0210SDevin Teske
68087c16275SDevin Teske	# Detect installed packages (updates marks/SELECTED_PACKAGES)
68187c16275SDevin Teske	f_package_detect_installed
682384190f2SDevin Teske	export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
68387c16275SDevin Teske
68487c16275SDevin Teske	local retval category varcat defaultitem category_defaultitem=""
68587c16275SDevin Teske	while :; do
68687c16275SDevin Teske		# Display the list of package categories
68787c16275SDevin Teske		f_package_menu_categories \
68887c16275SDevin Teske			CATEGORY_MENU_LIST "$category_defaultitem"
68987c16275SDevin Teske		retval=$?
690fd962ac6SDevin Teske		f_dialog_menutag_fetch category
69187c16275SDevin Teske		f_dprintf "retval=%u mtag=[%s]" $retval "$category"
69287c16275SDevin Teske		category_defaultitem="$category"
69387c16275SDevin Teske
694f677a9e2SDevin Teske		[ $retval -eq $DIALOG_OK ] || break
69587c16275SDevin Teske
69687c16275SDevin Teske		# Maybe the user chose an action (like `Review')
69787c16275SDevin Teske		case "$category" in
69887c16275SDevin Teske		"> $msg_review")
69987c16275SDevin Teske			f_package_review && break
70087c16275SDevin Teske			continue ;;
70187c16275SDevin Teske		"> "*)
70287c16275SDevin Teske			continue
70387c16275SDevin Teske		esac
70487c16275SDevin Teske
70587c16275SDevin Teske		# Anything else is a package category
70687c16275SDevin Teske
70787c16275SDevin Teske		category=${category# } # Trim leading space if present
70887c16275SDevin Teske		category=${category%\*} # Trim trailing asterisk if present
70987c16275SDevin Teske
71087c16275SDevin Teske		f_str2varname "$category" varcat
71187c16275SDevin Teske
712fd962ac6SDevin Teske		local page package varpkg mark menu_choice
71387c16275SDevin Teske		while :; do
71487c16275SDevin Teske			# Display the list of packages for selected category
71587c16275SDevin Teske			page=1 defaultitem=""
71687c16275SDevin Teske			f_getvar _defaultitem_$varcat defaultitem
71787c16275SDevin Teske			f_getvar _defaultpage_$varcat page
71887c16275SDevin Teske			f_package_menu_select \
71987c16275SDevin Teske				"$category" "${page:=1}" "$defaultitem"
72087c16275SDevin Teske			retval=$?
721fd962ac6SDevin Teske			f_dialog_menutag_fetch menu_choice
722fd962ac6SDevin Teske			f_dprintf "retval=%u mtag=[%s]" $retval "$menu_choice"
72387c16275SDevin Teske
72487c16275SDevin Teske			# NOTE: When --and-widget is used only ESC will cause
72587c16275SDevin Teske			# dialog(1) to return without going to the next widget.
72687c16275SDevin Teske			# This is alright in our case as we can still detect
72787c16275SDevin Teske			# the Cancel button because stdout will be NULL.
72887c16275SDevin Teske			# Alternatively, Xdialog(1) will terminate with 1
72987c16275SDevin Teske			# if/when Cancel is chosen on any widget.
730f677a9e2SDevin Teske			if [ $retval -eq $DIALOG_ESC -o ! "$menu_choice" ]
731f677a9e2SDevin Teske			then
73287c16275SDevin Teske				break
733f677a9e2SDevin Teske			elif [ $retval -eq $DIALOG_CANCEL ]; then
73487c16275SDevin Teske				# Using X11, Xdialog(1) returned 1 for Cancel
735fd962ac6SDevin Teske				f_show_msg "%s" "$menu_choice"
73687c16275SDevin Teske				break
737f677a9e2SDevin Teske			elif [ $retval -ne $DIALOG_OK ]; then
73887c16275SDevin Teske				# X11-related error occurred using Xdialog(1)
739fd962ac6SDevin Teske				f_show_msg "%s" "$menu_choice"
74087c16275SDevin Teske				break
74187c16275SDevin Teske			fi
74287c16275SDevin Teske
743fd962ac6SDevin Teske			defaultitem="$menu_choice"
74487c16275SDevin Teske
74587c16275SDevin Teske			# NOTE: f_package_menu_select() does not show the
74687c16275SDevin Teske			# `Previous Page' or `Next Page' items unless needed
747fd962ac6SDevin Teske			case "$menu_choice" in
74887c16275SDevin Teske			"> $msg_previous_page"|"> $msg_previous_page*")
74987c16275SDevin Teske				page=$(( $page - 1 ))
75087c16275SDevin Teske				setvar _defaultpage_$varcat $page
75187c16275SDevin Teske				# Update default-item to match accent that will
75287c16275SDevin Teske				# be applied by f_package_menu_select(); if the
75387c16275SDevin Teske				# page-before-prev is cached, add an asterisk.
75487c16275SDevin Teske				if f_isset \
75587c16275SDevin Teske					_index_page_${varcat}_$(( $page - 1 ))
75687c16275SDevin Teske				then
75787c16275SDevin Teske					defaultitem="${defaultitem%\*}*"
75887c16275SDevin Teske				else
75987c16275SDevin Teske					defaultitem="${defaultitem%\*}"
76087c16275SDevin Teske				fi
76187c16275SDevin Teske				setvar _defaultitem_$varcat "$defaultitem"
76287c16275SDevin Teske				continue ;;
76387c16275SDevin Teske			"> $msg_next_page"|"> $msg_next_page*")
76487c16275SDevin Teske				page=$(( $page + 1 ))
76587c16275SDevin Teske				setvar _defaultpage_$varcat $page
76687c16275SDevin Teske				# Update default-item to match accent that will
76787c16275SDevin Teske				# be applied by f_package_menu_select(); if the
76887c16275SDevin Teske				# page-after-next is cached, add an asterisk.
76987c16275SDevin Teske				if f_isset \
77087c16275SDevin Teske					_index_page_${varcat}_$(( $page + 1 ))
77187c16275SDevin Teske				then
77287c16275SDevin Teske					defaultitem="${defaultitem%\*}*"
77387c16275SDevin Teske				else
77487c16275SDevin Teske					defaultitem="${defaultitem%\*}"
77587c16275SDevin Teske				fi
77687c16275SDevin Teske				setvar _defaultitem_$varcat "$defaultitem"
77787c16275SDevin Teske				continue ;;
77887c16275SDevin Teske			"> "*) # Unknown navigation/action item
77987c16275SDevin Teske				setvar _defaultpage_$varcat $page
78087c16275SDevin Teske				continue ;; # Do not treat as a package
78187c16275SDevin Teske			*)
78287c16275SDevin Teske				setvar _defaultitem_$varcat "$defaultitem"
78387c16275SDevin Teske			esac
78487c16275SDevin Teske
78587c16275SDevin Teske			# Treat any other selection as a package
786fd962ac6SDevin Teske			package="${menu_choice# }" # Trim leading space
78787c16275SDevin Teske			f_str2varname $package varpkg
788b5bd0bacSDevin Teske			f_dialog_menuitem_fetch mark
78987c16275SDevin Teske			mark="${mark#?}"
79087c16275SDevin Teske			mark="${mark%%\] *}"
79187c16275SDevin Teske			case "$mark" in
79287c16275SDevin Teske			"I")
79387c16275SDevin Teske				mark=" "
79487c16275SDevin Teske				f_package_deselect $package
79587c16275SDevin Teske				;;
79687c16275SDevin Teske			" "|"D")
79787c16275SDevin Teske				mark="I"
79887c16275SDevin Teske				f_package_select $package
79987c16275SDevin Teske				;;
80087c16275SDevin Teske			"X"|"R"|"U")
80187c16275SDevin Teske				f_package_menu_deselect $package || continue
802fd962ac6SDevin Teske				f_dialog_menutag_fetch menu_choice
803fd962ac6SDevin Teske				case "$menu_choice" in
80487c16275SDevin Teske				"X $msg_installed")
80587c16275SDevin Teske					f_package_deselect "$package"
80687c16275SDevin Teske					mark="X"
80787c16275SDevin Teske					;;
80887c16275SDevin Teske				"R $msg_reinstall")
80987c16275SDevin Teske					f_package_select "$package"
81087c16275SDevin Teske					mark="R"
81187c16275SDevin Teske					;;
81287c16275SDevin Teske				"U $msg_uninstall")
81387c16275SDevin Teske					f_package_select "$package"
81487c16275SDevin Teske					mark="U"
81587c16275SDevin Teske					;;
81687c16275SDevin Teske				esac
81787c16275SDevin Teske				;;
81887c16275SDevin Teske			esac
81987c16275SDevin Teske			export _mark_$varpkg="$mark"
82087c16275SDevin Teske				# NOTE: exported for awk(1) ENVIRON[]
82187c16275SDevin Teske		done
82287c16275SDevin Teske	done
82387c16275SDevin Teske}
82487c16275SDevin Teske
82531185df0SDevin Teske# f_package_add $package_name [$depended]
82631185df0SDevin Teske#
82731185df0SDevin Teske# Like f_package_extract(), but assumes current media device and chases deps.
82831185df0SDevin Teske# Note that $package_name should not contain the archive suffix (e.g., `.tbz').
82931185df0SDevin Teske# If $depended is present and non-NULL, the package is treated as a dependency
83031185df0SDevin Teske# (in this function, dependencies are not handled any differently, but the
83131185df0SDevin Teske# f_package_extract() function is passed this value and it displays a different
83231185df0SDevin Teske# message when installing a dependency versus non-dependency).
83331185df0SDevin Teske#
83431185df0SDevin Teskef_package_add()
83531185df0SDevin Teske{
83631185df0SDevin Teske	local name="$1" depended="$2" status=$SUCCESS retval
83731185df0SDevin Teske
83831185df0SDevin Teske	local alert=f_show_msg no_confirm=
83931185df0SDevin Teske	f_getvar $VAR_NO_CONFIRM no_confirm
84031185df0SDevin Teske	[ "$no_confirm" ] && alert=f_show_info
84131185df0SDevin Teske
84231185df0SDevin Teske	if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
84331185df0SDevin Teske	then
84431185df0SDevin Teske		f_dprintf "packageAdd: %s" \
84531185df0SDevin Teske		          "$msg_no_package_name_passed_in_package_variable"
84631185df0SDevin Teske		return $FAILURE
84731185df0SDevin Teske	fi
84831185df0SDevin Teske
84931185df0SDevin Teske	{ # Verify and initialize device media if-defined
85031185df0SDevin Teske		f_media_verify &&
8519ecd54f2SDevin Teske		f_device_init device_media &&
85295d45410SDevin Teske		f_index_initialize
85331185df0SDevin Teske	} || return $FAILURE
85431185df0SDevin Teske
85531185df0SDevin Teske	# Now we have (indirectly via f_index_read()):
85631185df0SDevin Teske	#   CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
85731185df0SDevin Teske	#   PACKAGE_CATEGORIES _npkgs
85831185df0SDevin Teske
85931185df0SDevin Teske	local varpkg
86031185df0SDevin Teske	f_str2varname "$name" varpkg
86131185df0SDevin Teske
86231185df0SDevin Teske	# Just as-in the user-interface (opposed to scripted-use), only allow
86331185df0SDevin Teske	# packages with at least one category to be recognized.
86431185df0SDevin Teske	#
86531185df0SDevin Teske	local pkgcat=
86631185df0SDevin Teske	if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then
86731185df0SDevin Teske		# $pkg may be a partial name, search the index (this is slow)
86831185df0SDevin Teske		f_index_search PACKAGE_INDEX $name name
86931185df0SDevin Teske		if [ ! "$name" ]; then
87031185df0SDevin Teske			f_show_msg \
87131185df0SDevin Teske			    "$msg_sorry_package_was_not_found_in_the_index" \
87231185df0SDevin Teske			    "$name"
87331185df0SDevin Teske			return $FAILURE
87431185df0SDevin Teske		fi
87531185df0SDevin Teske		f_str2varname "$name" varpkg
87631185df0SDevin Teske	fi
87731185df0SDevin Teske
87831185df0SDevin Teske	# If invoked through the scripted interface, we likely have not yet
87931185df0SDevin Teske	# detected the installed packages -- something we should do only once.
88031185df0SDevin Teske	#
88131185df0SDevin Teske	if [ ! "$PACKAGES_DETECTED" ]; then
88212a9a520SDevin Teske		f_dprintf "f_package_add: Detecting installed packages"
88331185df0SDevin Teske		f_package_detect_installed
88431185df0SDevin Teske		export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
88531185df0SDevin Teske	fi
88631185df0SDevin Teske	# Now we have: _mark_{varpkg}=X for all installed packages
88731185df0SDevin Teske
88831185df0SDevin Teske	#
88931185df0SDevin Teske	# Since we're maintaining data structures for installed packages,
89031185df0SDevin Teske	# short-circuit the package dependency checks if the package is already
89131185df0SDevin Teske	# installed. This prevents wasted cycles, minor delays between package
89231185df0SDevin Teske	# extractions, and worst-case an infinite loop with a certain faulty
89331185df0SDevin Teske	# INDEX file.
89431185df0SDevin Teske	#
89531185df0SDevin Teske	local mark=
89631185df0SDevin Teske	f_getvar _mark_$varpkg mark && [ "$mark" = "X" ] && return $SUCCESS
89731185df0SDevin Teske
89831185df0SDevin Teske	local dep vardep rundeps=
89931185df0SDevin Teske	f_getvar _rundeps_$varpkg rundeps
90031185df0SDevin Teske	for dep in $rundeps; do
90131185df0SDevin Teske		f_str2varname "$dep" vardep
90231185df0SDevin Teske
90331185df0SDevin Teske		# Skip dependency if already installed
90431185df0SDevin Teske		mark=
90531185df0SDevin Teske		f_getvar _mark_$vardep mark && [ "$mark" = "X" ] && continue
90631185df0SDevin Teske
90731185df0SDevin Teske		# Just as-in the user-interface (opposed to scripted-use), only
90831185df0SDevin Teske		# allow packages with at least one category to be recognized.
90931185df0SDevin Teske		#
91031185df0SDevin Teske		local depcat=
91131185df0SDevin Teske		if ! f_getvar _categories_$vardep depcat || [ ! "$depcat" ]
91231185df0SDevin Teske		then
91331185df0SDevin Teske			$alert "$msg_required_package_not_found" "$dep"
91431185df0SDevin Teske			[ "$no_confirm" ] && sleep 2
91531185df0SDevin Teske		fi
91631185df0SDevin Teske
91731185df0SDevin Teske		f_package_add "$dep"
91831185df0SDevin Teske		retval=$?
91931185df0SDevin Teske		if [ $retval -ne $SUCCESS ]; then
92031185df0SDevin Teske			status=$(( $status | $retval ))
92131185df0SDevin Teske
92231185df0SDevin Teske			# XXX package could be on a future disc volume
92331185df0SDevin Teske			# XXX (not supporting multiple disc volumes yet)
92431185df0SDevin Teske
92531185df0SDevin Teske			$alert "$msg_loading_of_dependent_package_failed" \
92631185df0SDevin Teske			       "$dep"
92731185df0SDevin Teske			[ "$no_confirm" ] && sleep 2
92831185df0SDevin Teske		fi
92931185df0SDevin Teske	done
93031185df0SDevin Teske	[ $status -eq $SUCCESS ] || return $status
93131185df0SDevin Teske
93231185df0SDevin Teske	#
93331185df0SDevin Teske	# Done with the deps? Try to load the real m'coy.
93431185df0SDevin Teske	#
93531185df0SDevin Teske
9369ecd54f2SDevin Teske	f_package_extract device_media "$name" "$depended"
93731185df0SDevin Teske	retval=$?
93831185df0SDevin Teske	if [ $retval -ne $SUCCESS ]; then
93931185df0SDevin Teske		status=$(( $status | $retval ))
94031185df0SDevin Teske	else
94131185df0SDevin Teske		setvar _mark_$varpkg X
94231185df0SDevin Teske	fi
94331185df0SDevin Teske
94431185df0SDevin Teske	return $status
94531185df0SDevin Teske}
94631185df0SDevin Teske
94731185df0SDevin Teske# f_package_extract $device $name [$depended]
94831185df0SDevin Teske#
94931185df0SDevin Teske# Extract a package based on a namespec and media device. If $depended is
95031185df0SDevin Teske# present and non-NULL, the notification displayed while installing the package
95131185df0SDevin Teske# has "as a dependency" appended.
95231185df0SDevin Teske#
95331185df0SDevin Teskef_package_extract()
95431185df0SDevin Teske{
95584873facSDevin Teske	local funcname=f_package_extract
95631185df0SDevin Teske	local device="$1" name="$2" depended="$3"
9579ecd54f2SDevin Teske	local devname=
95831185df0SDevin Teske
95995d45410SDevin Teske	f_musthavepkg_init # Make sure we have a usable pkg(8) with $PKG_ABI
96095d45410SDevin Teske
9619ecd54f2SDevin Teske	$device get name devname
96284873facSDevin Teske	f_dprintf "$funcname: device=[%s] name=[%s] depended=[%s]" \
9639ecd54f2SDevin Teske	          "$devname" "$name" "$depended"
96402af913fSDevin Teske
96531185df0SDevin Teske	# Check to make sure it's not already there
96631185df0SDevin Teske	local varpkg mark=
96731185df0SDevin Teske	f_str2varname "$name" varpkg
96831185df0SDevin Teske	f_getvar _mark_$varpkg mark
96931185df0SDevin Teske	[ "$mark" = "X" ] && return $SUCCESS
97031185df0SDevin Teske
97131185df0SDevin Teske	if ! f_device_init $device; then
97231185df0SDevin Teske		f_show_msg \
97331185df0SDevin Teske		    "$msg_unable_to_initialize_media_type_for_package_extract"
97431185df0SDevin Teske		return $FAILURE
97531185df0SDevin Teske	fi
97631185df0SDevin Teske
97731185df0SDevin Teske	# If necessary, initialize the ldconfig hints
97831185df0SDevin Teske	[ -f "/var/run/ld-elf.so.hints" ] ||
97931185df0SDevin Teske		f_quietly ldconfig /usr/lib /usr/lib/compat /usr/local/lib
98031185df0SDevin Teske
98131185df0SDevin Teske	# Make a couple paranoid locations for temp
98231185df0SDevin Teske	# files to live if user specified none
98331185df0SDevin Teske	local tmpdir
98431185df0SDevin Teske	f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir
98531185df0SDevin Teske	f_quietly mkdir -p -m 1777 "$tmpdir"
98631185df0SDevin Teske
987ebd672f5SDevin Teske	local path device_type
9889ecd54f2SDevin Teske	$device get type device_type
98931185df0SDevin Teske	case "$name" in
99031185df0SDevin Teske	*/*) path="$name" ;;
991ebd672f5SDevin Teske	*)
992ebd672f5SDevin Teske		if [ "$device_type" = "$DEVICE_TYPE_HTTP" ]; then
993ebd672f5SDevin Teske			path="$PKG_ABI/latest/All/$name"
994ebd672f5SDevin Teske		else
995ebd672f5SDevin Teske			path="packages/$PKG_ABI/All/$name"
996ebd672f5SDevin Teske		fi
99731185df0SDevin Teske	esac
99831185df0SDevin Teske
999632d9a08SDevin Teske	# We have a path, call the device strategy routine to check the file
1000dde7be41SDevin Teske	local pkg_ext found=
100131185df0SDevin Teske	for pkg_ext in "" $PACKAGE_EXTENSIONS; do
1002dde7be41SDevin Teske		if f_device_get $device "$path$pkg_ext" $PROBE_EXIST; then
100331185df0SDevin Teske			path="$path$pkg_ext"
1004ebd672f5SDevin Teske			found=1
1005ebd672f5SDevin Teske			break
1006ebd672f5SDevin Teske		elif [ "$device_type" = "$DEVICE_TYPE_HTTP" ] &&
1007ebd672f5SDevin Teske		     f_device_get $device \
1008ebd672f5SDevin Teske			"packages/$PKG_ABI/All/$name$pkg_ext" $PROBE_EXIST
1009ebd672f5SDevin Teske		then
1010ebd672f5SDevin Teske			# Mirroring physical media over HTTP
1011ebd672f5SDevin Teske			path="packages/$PKG_ABI/All/$name$pkg_ext"
101231185df0SDevin Teske			found=1
101331185df0SDevin Teske			break
101431185df0SDevin Teske		fi
101531185df0SDevin Teske	done
1016ebd672f5SDevin Teske	[ "$found" ] && f_dprintf "$funcname: found path=[%s] dev=[%s]" \
10179ecd54f2SDevin Teske	                          "$path" "$devname"
101831185df0SDevin Teske
101931185df0SDevin Teske	local alert=f_show_msg no_confirm=
102031185df0SDevin Teske	f_getvar $VAR_NO_CONFIRM no_confirm
102131185df0SDevin Teske	[ "$no_confirm" ] && alert=f_show_info
102231185df0SDevin Teske
102331185df0SDevin Teske	if [ ! "$found" ]; then
102484873facSDevin Teske		f_dprintf "$funcname: No such %s file on %s device" \
10259ecd54f2SDevin Teske	                  "$path" "$devname"
102631185df0SDevin Teske		$alert "$msg_unable_to_fetch_package_from_selected_media" \
102731185df0SDevin Teske		       "$name"
102831185df0SDevin Teske		[ "$no_confirm" ] && sleep 2
102931185df0SDevin Teske		return $FAILURE
103031185df0SDevin Teske	fi
103131185df0SDevin Teske
103231185df0SDevin Teske	if [ "$depended" ]; then
103331185df0SDevin Teske		f_show_info "$msg_adding_package_as_a_dependency_from_media" \
103431185df0SDevin Teske		            "$name" "$devname"
103531185df0SDevin Teske	else
103631185df0SDevin Teske		f_show_info "$msg_adding_package_from_media" "$name" "$devname"
103731185df0SDevin Teske	fi
103831185df0SDevin Teske
1039632d9a08SDevin Teske	# Request the package be added via pkg-install(8)
104031185df0SDevin Teske	if f_debugging; then
10413a2e3fe2SDevin Teske		f_eval_catch $funcname pkg \
10423a2e3fe2SDevin Teske			'pkg -d install -${depended:+A}y "%s"' "$name"
104331185df0SDevin Teske	else
10443a2e3fe2SDevin Teske		f_eval_catch $funcname pkg \
10453a2e3fe2SDevin Teske			'pkg install -${depended:+A}y "%s"' "$name"
104631185df0SDevin Teske	fi
104731185df0SDevin Teske	if [ $? -ne $SUCCESS ]; then
1048632d9a08SDevin Teske		$alert "$msg_pkg_install_apparently_did_not_like_the_package" \
104931185df0SDevin Teske		       "$name"
105031185df0SDevin Teske		[ "$no_confirm" ] && sleep 2
105131185df0SDevin Teske	else
105231185df0SDevin Teske		f_show_info "$msg_package_was_added_successfully" "$name"
105331185df0SDevin Teske		sleep 1
105431185df0SDevin Teske	fi
105531185df0SDevin Teske
105631185df0SDevin Teske	return $SUCCESS
105731185df0SDevin Teske}
105831185df0SDevin Teske
1059542dd84bSDevin Teske# f_package_delete $name
1060542dd84bSDevin Teske#
1061542dd84bSDevin Teske# Delete package by full $name (lacks archive suffix; e.g., `.tbz').
1062542dd84bSDevin Teske#
1063542dd84bSDevin Teskef_package_delete()
1064542dd84bSDevin Teske{
106584873facSDevin Teske	local funcname=f_package_delete
1066542dd84bSDevin Teske	local name="$1"
1067542dd84bSDevin Teske
1068542dd84bSDevin Teske	if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
1069542dd84bSDevin Teske	then
1070542dd84bSDevin Teske		f_dprintf "packageDelete: %s" \
1071542dd84bSDevin Teske		          "$msg_no_package_name_passed_in_package_variable"
1072542dd84bSDevin Teske		return $FAILURE
1073542dd84bSDevin Teske	fi
1074542dd84bSDevin Teske
107584873facSDevin Teske	f_dprintf "$funcname: name=[%s]" "$name"
1076542dd84bSDevin Teske
1077542dd84bSDevin Teske	[ "$name" ] || return $FAILURE
1078542dd84bSDevin Teske
1079542dd84bSDevin Teske	{ # Verify and initialize device media if-defined
1080542dd84bSDevin Teske		f_media_verify &&
10819ecd54f2SDevin Teske		f_device_init device_media &&
108295d45410SDevin Teske		f_index_initialize
1083542dd84bSDevin Teske	} || return $FAILURE
1084542dd84bSDevin Teske
1085542dd84bSDevin Teske	# Now we have (indirectly via f_index_read()):
1086542dd84bSDevin Teske	#   CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
1087542dd84bSDevin Teske	#   PACKAGE_CATEGORIES _npkgs
1088542dd84bSDevin Teske
1089542dd84bSDevin Teske	local varpkg
1090542dd84bSDevin Teske	f_str2varname "$name" varpkg
1091542dd84bSDevin Teske
1092542dd84bSDevin Teske	# Just as-in the user-interface (opposed to scripted-use), only allow
1093542dd84bSDevin Teske	# packages with at least one category to be recognized.
1094542dd84bSDevin Teske	#
1095542dd84bSDevin Teske	local pkgcat=
1096542dd84bSDevin Teske	if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then
1097542dd84bSDevin Teske		# $pkg may be a partial name, search the index (this is slow)
1098542dd84bSDevin Teske		f_index_search PACKAGE_INDEX "$name" name
1099542dd84bSDevin Teske		if [ ! "$name" ]; then
1100542dd84bSDevin Teske			f_show_msg \
1101542dd84bSDevin Teske			    "$msg_sorry_package_was_not_found_in_the_index" \
1102542dd84bSDevin Teske			    "$name"
1103542dd84bSDevin Teske			return $FAILURE
1104542dd84bSDevin Teske		fi
1105542dd84bSDevin Teske		f_str2varname "$name" varpkg
1106542dd84bSDevin Teske	fi
1107542dd84bSDevin Teske
1108542dd84bSDevin Teske	# If invoked through the scripted interface, we likely have not yet
1109542dd84bSDevin Teske	# detected the installed packages -- something we should do only once.
1110542dd84bSDevin Teske	#
1111542dd84bSDevin Teske	if [ ! "$PACKAGES_DETECTED" ]; then
111284873facSDevin Teske		f_dprintf "$funcname: Detecting installed packages"
1113542dd84bSDevin Teske		f_package_detect_installed
1114542dd84bSDevin Teske		export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
1115542dd84bSDevin Teske	fi
1116542dd84bSDevin Teske	# Now we have: _mark_{varpkg}=X for all installed packages
1117542dd84bSDevin Teske
1118542dd84bSDevin Teske	#
1119542dd84bSDevin Teske	# Return failure if the package is not already installed.
1120542dd84bSDevin Teske	#
1121542dd84bSDevin Teske	local pkgmark=
1122542dd84bSDevin Teske	f_getvar _mark_$varpkg pkgmark
1123542dd84bSDevin Teske	if ! [ "$pkgmark" -a ! "${pkgmark#[XUR]}" ]; then
1124542dd84bSDevin Teske		f_show_msg "$msg_package_not_installed_cannot_delete" "$name"
1125542dd84bSDevin Teske		return $FAILURE
1126542dd84bSDevin Teske	fi
1127542dd84bSDevin Teske
1128542dd84bSDevin Teske	#
1129542dd84bSDevin Teske	# Check for dependencies
1130542dd84bSDevin Teske	#
1131542dd84bSDevin Teske	local pkgsel depc=0 udeps=
1132542dd84bSDevin Teske	for pkgsel in $SELECTED_PACKAGES; do
1133542dd84bSDevin Teske		local mark=
1134542dd84bSDevin Teske		f_str2varname $pkgsel varpkg
1135542dd84bSDevin Teske		debug= f_getvar _mark_$varpkg mark
1136542dd84bSDevin Teske		[ "$mark" -a ! "${mark#[XUR]}" ] || continue
1137542dd84bSDevin Teske		local dep rundeps=
1138542dd84bSDevin Teske		debug= f_getvar _rundeps_$varpkg rundeps
1139542dd84bSDevin Teske		for dep in $rundeps; do
1140542dd84bSDevin Teske			if [ "$dep" = "$name" ]; then
1141542dd84bSDevin Teske				# Maybe this package is marked for deletion too
1142542dd84bSDevin Teske				if [ "$mark" = "U" ]; then
1143542dd84bSDevin Teske					udeps="$udeps $pkgsel"
1144542dd84bSDevin Teske				else
1145542dd84bSDevin Teske					depc=$(( $depc + 1 ))
1146542dd84bSDevin Teske				fi
1147542dd84bSDevin Teske				break
1148542dd84bSDevin Teske			fi
1149542dd84bSDevin Teske		done
1150542dd84bSDevin Teske	done
1151542dd84bSDevin Teske	if [ $depc -gt 0 ]; then
1152542dd84bSDevin Teske		local grammatical_s=
1153542dd84bSDevin Teske		[ $depc -gt 1 ] && grammatical_s=s
1154542dd84bSDevin Teske		f_show_msg \
1155542dd84bSDevin Teske			"$msg_package_is_needed_by_other_installed_packages" \
1156542dd84bSDevin Teske			"$name" "$depc" "$grammatical_s"
1157542dd84bSDevin Teske		return $FAILURE
1158542dd84bSDevin Teske	fi
1159542dd84bSDevin Teske
1160542dd84bSDevin Teske	#
1161542dd84bSDevin Teske	# Chase dependencies that are marked for uninstallation
1162542dd84bSDevin Teske	#
1163542dd84bSDevin Teske	for pkgsel in $udeps; do
116484873facSDevin Teske		f_dprintf "$funcname: Uninstalling dependency %s (%s)" \
116584873facSDevin Teske		          "$pkgsel" "marked for delete"
1166542dd84bSDevin Teske		f_package_delete "$pkgsel"
1167542dd84bSDevin Teske	done
1168542dd84bSDevin Teske
1169542dd84bSDevin Teske	#
1170542dd84bSDevin Teske	# OK to perform the delete (no other packages depend on it)...
1171542dd84bSDevin Teske	#
1172542dd84bSDevin Teske	f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name"
1173542dd84bSDevin Teske	if f_debugging; then
1174ee5ef711SDevin Teske		f_eval_catch $funcname pkg 'pkg -d delete -y "%s"' "$name"
1175542dd84bSDevin Teske	else
1176ee5ef711SDevin Teske		f_eval_catch $funcname pkg 'pkg delete -y "%s"' "$name"
1177542dd84bSDevin Teske	fi
1178542dd84bSDevin Teske	if [ $? -ne $SUCCESS ]; then
1179542dd84bSDevin Teske		f_show_msg "$msg_pkg_delete_failed" "$name"
1180542dd84bSDevin Teske		return $FAILURE
1181542dd84bSDevin Teske	else
118284873facSDevin Teske		f_dprintf "$funcname: pkg-delete(8) of %s successful" "$name"
1183542dd84bSDevin Teske		f_str2varname "$name" varpkg
1184542dd84bSDevin Teske		setvar _mark_$varpkg ""
1185542dd84bSDevin Teske	fi
1186542dd84bSDevin Teske}
1187542dd84bSDevin Teske
118852d41f91SDevin Teske# f_package_reinstall $name
118952d41f91SDevin Teske#
119052d41f91SDevin Teske# A simple wrapper to f_package_delete() + f_package_add()
119152d41f91SDevin Teske#
119252d41f91SDevin Teskef_package_reinstall()
119352d41f91SDevin Teske{
119452d41f91SDevin Teske	f_package_delete "$1" && f_package_add "$1"
119552d41f91SDevin Teske}
119652d41f91SDevin Teske
119787c16275SDevin Teske############################################################ MAIN
119887c16275SDevin Teske
119987c16275SDevin Teskef_dprintf "%s: Successfully loaded." packages/packages.subr
120087c16275SDevin Teske
120187c16275SDevin Teskefi # ! $_PACKAGES_PACKAGES_SUBR
1202