packages.subr revision 251354
1130803Smarcelif [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_SUBR=1 2130803Smarcel# 3130803Smarcel# Copyright (c) 2013 Devin Teske 4130803Smarcel# All Rights Reserved. 5130803Smarcel# 6130803Smarcel# Redistribution and use in source and binary forms, with or without 7130803Smarcel# modification, are permitted provided that the following conditions 8130803Smarcel# are met: 9130803Smarcel# 1. Redistributions of source code must retain the above copyright 10130803Smarcel# notice, this list of conditions and the following disclaimer. 11130803Smarcel# 2. Redistributions in binary form must reproduce the above copyright 12130803Smarcel# notice, this list of conditions and the following disclaimer in the 13130803Smarcel# documentation and/or other materials provided with the distribution. 14130803Smarcel# 15130803Smarcel# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16130803Smarcel# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE 17130803Smarcel# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18130803Smarcel# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19130803Smarcel# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20130803Smarcel# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21130803Smarcel# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22130803Smarcel# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23130803Smarcel# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24130803Smarcel# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25130803Smarcel# SUCH DAMAGE. 26130803Smarcel# 27130803Smarcel# $FreeBSD: head/usr.sbin/bsdconfig/share/packages/packages.subr 251354 2013-06-04 00:35:57Z dteske $ 28130803Smarcel# 29130803Smarcel############################################################ INCLUDES 30130803Smarcel 31130803SmarcelBSDCFG_SHARE="/usr/share/bsdconfig" 32130803Smarcel. $BSDCFG_SHARE/common.subr || exit 1 33130803Smarcelf_dprintf "%s: loading includes..." "$0" 34130803Smarcelf_include $BSDCFG_SHARE/dialog.subr 35130803Smarcelf_include $BSDCFG_SHARE/strings.subr 36130803Smarcelf_include $BSDCFG_SHARE/packages/categories.subr 37130803Smarcelf_include $BSDCFG_SHARE/packages/index.subr 38130803Smarcel 39130803SmarcelBSDCFG_LIBE="/usr/libexec/bsdconfig" 40130803Smarcelf_include_lang $BSDCFG_LIBE/include/messages.subr 41130803Smarcel 42130803Smarcel############################################################ CONFIGURATION 43130803Smarcel 44130803Smarcel# 45130803Smarcel# How many packages to display (maximum) per dialog menubox. 46130803Smarcel# 47130803Smarcel: ${PACKAGE_MENU_PAGESIZE:=2000} 48130803Smarcel 49130803Smarcel############################################################ GLOBALS 50130803Smarcel 51130803SmarcelPACKAGE_CATEGORIES= 52130803SmarcelSELECTED_PACKAGES= 53130803Smarcel 54130803Smarcel# 55130803Smarcel# Options 56130803Smarcel# 57130803Smarcel[ "${SHOW_DESC+set}" ] || SHOW_DESC=1 58130803Smarcel 59130803Smarcel############################################################ FUNCTIONS 60130803Smarcel 61130803Smarcel# eval f_package_accent_category_menu $var_to_set $CATEGORY_MENU_LIST 62130803Smarcel# 63130803Smarcel# Accent the CATEGORY_MENU_LIST produced by f_index_read() (see 64130803Smarcel# packages/index.subr). Accented information includes adding an asterisk to the 65130803Smarcel# category name if its index has been cached, adding the number of installed 66130803Smarcel# packages for each category, and adding the number _selected_ packages for 67130803Smarcel# each category. 68130803Smarcel# 69130803Smarcel# NOTE: The reason `eval' is recommended/shown for the syntax above is because 70130803Smarcel# the $CATEGORY_MENU_LIST generated by f_index_read() is meant to be expanded 71130803Smarcel# prior to execution (it contains a series of pre-quoted strings which act as 72130803Smarcel# the interpolated command arguments). 73130803Smarcel# 74130803Smarcelf_package_accent_category_menu() 75130803Smarcel{ 76130803Smarcel local var_to_set="$1" cat desc help varcat menu_buf n 77130803Smarcel shift 1 # var_to_set 78130803Smarcel while [ $# -gt 0 ]; do 79130803Smarcel cat="${1%\*}" desc="${2%%; *}" help="$3" 80130803Smarcel shift 3 # cat/desc/help 81130803Smarcel 82130803Smarcel cat="${cat# }" # Trim leading space inserted by sort-method 83130803Smarcel f_str2varname "$cat" varcat 84130803Smarcel 85130803Smarcel # Add number of installed packages for this category (if any) 86130803Smarcel n=0 87130803Smarcel case "$cat" in 88130803Smarcel "$msg_all") debug= f_getvar "_All_ninstalled" n ;; 89130803Smarcel *) debug= f_getvar "_${varcat}_ninstalled" n ;; 90130803Smarcel esac && 91130803Smarcel [ $n -ge 1 ] && desc="$desc; $n $msg_installed_lc" 92130803Smarcel 93130803Smarcel # Add number of selected packages for this category (if any) 94130803Smarcel n=0 95130803Smarcel case "$cat" in 96130803Smarcel "$msg_all") debug= f_getvar "_All_nselected" n ;; 97130803Smarcel *) debug= f_getvar "_${varcat}_nselected" n ;; 98130803Smarcel esac && 99130803Smarcel [ $n -ge 1 ] && desc="$desc; $n $msg_selected" 100130803Smarcel 101130803Smarcel # Re-Add asterisk to the category if its index has been cached 102130803Smarcel f_isset _index_page_${varcat}_1 && cat="$cat*" 103130803Smarcel 104130803Smarcel # Update buffer with modified elements 105130803Smarcel menu_buf="$menu_buf 106130803Smarcel '$cat' '$desc' '$help'" # End-Quote 107130803Smarcel done 108130803Smarcel setvar "$var_to_set" "$menu_buf" # return our buffer 109130803Smarcel} 110130803Smarcel 111130803Smarcel# f_package_select $package ... 112130803Smarcel# 113130803Smarcel# Add $package to the list of tracked/selected packages. If $package is already 114130803Smarcel# being tracked (already apears in $SELECTED_PACKAGES), this function amounts 115130803Smarcel# to having no effect. 116130803Smarcel# 117130803Smarcelf_package_select() 118130803Smarcel{ 119130803Smarcel local package pkgsel 120130803Smarcel while [ $# -gt 0 ]; do 121130803Smarcel package="$1" 122130803Smarcel shift 1 # package 123130803Smarcel for pkgsel in $SELECTED_PACKAGES; do 124130803Smarcel [ "$package" = "$pkgsel" ] && return 125130803Smarcel done 126130803Smarcel SELECTED_PACKAGES="$SELECTED_PACKAGES $package" 127130803Smarcel done 128130803Smarcel SELECTED_PACKAGES="${SELECTED_PACKAGES# }" # Trim leading space 129130803Smarcel} 130130803Smarcel 131130803Smarcel# f_package_deselect $package ... 132130803Smarcel# 133130803Smarcel# Remove $package from teh list of tracked/selected packages. If $package is 134130803Smarcel# not being tracked (doesn't appear in $SELECTED_PACKAGES), this function 135130803Smarcel# amounts to having no effet. 136130803Smarcel# 137130803Smarcelf_package_deselect() 138130803Smarcel{ 139130803Smarcel local package pkgsel 140130803Smarcel while [ $# -gt 1 ]; do 141130803Smarcel local new_list="" 142130803Smarcel package="$1" 143130803Smarcel shift 1 # package 144130803Smarcel for pkgsel in $SELECTED_PACKAGES; do 145130803Smarcel [ "$pkgsel" = "$package" ] && continue 146130803Smarcel new_list="$new_list${new_list:+ }$pkgsel" 147130803Smarcel done 148130803Smarcel SELECTED_PACKAGES="$new_list" 149130803Smarcel done 150130803Smarcel} 151130803Smarcel 152130803Smarcel# f_package_detect_installed 153130803Smarcel# 154130803Smarcel# Detect installed packages. Currently this searches /var/db/pkg for directory 155130803Smarcel# entries and marks each entry as an installed/selected package. 156130803Smarcel# 157130803Smarcelf_package_detect_installed() 158130803Smarcel{ 159130803Smarcel local installed package varpkg 160130803Smarcel installed=$( find -s /var/db/pkg -mindepth 1 -maxdepth 1 -type d | 161130803Smarcel sed -e 's:/var/db/pkg/::' ) 162130803Smarcel for package in $installed; do 163130803Smarcel f_str2varname $package varpkg 164130803Smarcel export _mark_$varpkg=X # exported for awk(1) ENVIRON[] 165130803Smarcel f_package_select $package 166130803Smarcel done 167130803Smarcel} 168130803Smarcel 169130803Smarcel# f_package_calculate_totals 170130803Smarcel# 171130803Smarcel# Calculate number of installed/selected packages for each category listed in 172130803Smarcel# $PACKAGE_CATEGORIES (the number of installed packages for $category is stored 173130803Smarcel# as $_${varcat}_ninstalled -- where $varcat is the product of `f_str2varname 174130803Smarcel# $category varcat' -- and number selected packages as $_${varcat}_nselected). 175130803Smarcel# Also calculates the total number of installed/selected packages stored as 176130803Smarcel# $_All_ninstalled and $_All_nselected. 177130803Smarcel# 178130803Smarcel# Calculations are peformed by checking "marks". A "mark" is stored as 179130803Smarcel# $_mark_$varpkg -- where $varpkg is the product of `f_str2varname $package 180130803Smarcel# varpkg'. A mark can be "X" for an installed package, `I' for a package that 181130803Smarcel# is marked for installation, "R" for a package that is marked for re-install, 182130803Smarcel# and "U" for a package that is marked for uninstallation. If a package mark is 183130803Smarcel# NULL or a single space (e.g., " "), the package is considered to be NOT 184130803Smarcel# selected (and therefore does not increment the counts calculated herein). 185130803Smarcel# 186130803Smarcelf_package_calculate_totals() 187130803Smarcel{ 188130803Smarcel local pkg varpkg mark cat varcat pkgcat n tselected=0 tinstalled=0 189130803Smarcel for cat in $PACKAGE_CATEGORIES; do 190130803Smarcel f_str2varname $cat varcat 191130803Smarcel setvar _${varcat}_ninstalled=0 192130803Smarcel setvar _${varcat}_nselected=0 193130803Smarcel done 194130803Smarcel for pkg in $SELECTED_PACKAGES; do 195130803Smarcel f_str2varname $pkg varpkg 196130803Smarcel mark= 197130803Smarcel f_getvar _mark_$varpkg mark 198130803Smarcel case "$mark" in 199130803Smarcel ""|" ") : ;; 200130803Smarcel X) tinstalled=$(( $tinstalled + 1 ));; 201130803Smarcel *) tselected=$(( $tselected + 1 )) 202130803Smarcel esac 203130803Smarcel f_getvar _categories_$varpkg pkgcat 204130803Smarcel for cat in $pkgcat; do 205130803Smarcel f_str2varname $cat varcat 206130803Smarcel case "$mark" in 207130803Smarcel ""|" ") : ;; 208130803Smarcel X) debug= f_getvar _${varcat}_ninstalled n 209130803Smarcel setvar _${varcat}_ninstalled $(( $n + 1 ));; 210130803Smarcel *) debug= f_getvar _${varcat}_nselected n 211130803Smarcel setvar _${varcat}_nselected $(( $n + 1 )) 212130803Smarcel esac 213130803Smarcel done 214130803Smarcel done 215130803Smarcel _All_nselected=$tselected 216130803Smarcel _All_ninstalled=$tinstalled 217130803Smarcel} 218130803Smarcel 219130803Smarcel# f_package_calculate_rundeps 220130803Smarcel# 221130803Smarcel# Update package dependencies by first unmarking all dependencies and then 222130803Smarcel# re-marking all dependencies of packages marked for either install ("I") or 223130803Smarcel# re-install ("R"). 224130803Smarcel# 225130803Smarcelf_package_calculate_rundeps() 226130803Smarcel{ 227130803Smarcel local pkg varpkg mark rundeps dep vardep 228130803Smarcel 229130803Smarcel # 230130803Smarcel # First unmark all the existing run-dependencies 231130803Smarcel # 232130803Smarcel f_dprintf "Unselecting package run-dependencies..." 233130803Smarcel for pkg in $SELECTED_PACKAGES; do 234130803Smarcel f_str2varname $pkg varpkg 235130803Smarcel mark= 236130803Smarcel debug= f_getvar _mark_$varpkg mark 237130803Smarcel # Only unmark if it's marked as a Dependency 238130803Smarcel if [ "$mark" = "D" ]; then 239130803Smarcel f_dprintf "%s unselected" $pkg 240130803Smarcel unset _mark_$varpkg 241130803Smarcel f_package_deselect $pkg 242130803Smarcel fi 243130803Smarcel done 244130803Smarcel 245130803Smarcel # 246130803Smarcel # Processes selected packages, adding dependencies 247130803Smarcel # 248130803Smarcel f_dprintf "Re-selecting package run-dependencies..." 249130803Smarcel for pkg in $SELECTED_PACKAGES; do 250130803Smarcel f_str2varname $pkg varpkg 251130803Smarcel mark= 252130803Smarcel debug= f_getvar _mark_$varpkg mark 253130803Smarcel # Skip pkg unless marked for [Re-]Install 254130803Smarcel [ "$mark" = "I" -o "$mark" = "R" ] || continue 255130803Smarcel f_getvar _rundeps_$varpkg rundeps 256130803Smarcel for dep in $rundeps; do 257130803Smarcel f_str2varname $dep vardep 258130803Smarcel mark= 259130803Smarcel debug= f_getvar _mark_$vardep mark 260130803Smarcel # Skip dep if already marked 261130803Smarcel [ "${mark:- }" = " " ] || continue 262130803Smarcel export _mark_$vardep="D" 263130803Smarcel f_package_select $dep 264130803Smarcel done 265130803Smarcel done 266130803Smarcel 267130803Smarcel f_dprintf "Finished recalculating dependencies." 268130803Smarcel} 269130803Smarcel 270130803Smarcel# f_package_menu_categories $var_to_set $defaultitem 271130803Smarcel# 272130803Smarcel# Dislay the menu of package categories, complete with package counts for each 273130803Smarcel# category, accents, and other miscellany. If $defaultitem is non-NULL and 274130803Smarcel# matches one of the existing menu-items, it will be pre-highlighted in the 275130803Smarcel# menu dialog (HINT: Use f_dialog_menutag_fetch() to populate a local variable 276130803Smarcel# that is passed as $defaultitem to highlight the user's last selection). 277130803Smarcel# 278130803Smarcelf_package_menu_categories() 279130803Smarcel{ 280130803Smarcel local var_to_get="$1" defaultitem="$2" 281130803Smarcel local prompt="$msg_please_select_a_category_to_display" 282130803Smarcel local menu_list=" 283130803Smarcel '> $msg_review' '$msg_review_desc' '$msg_review_help' 284130803Smarcel " # End-Quote 285130803Smarcel local hline= 286130803Smarcel 287130803Smarcel f_package_calculate_rundeps 288130803Smarcel # updates package mark variables and SELECTED_PACKAGES 289130803Smarcel f_package_calculate_totals 290130803Smarcel # creates _{varcat}_ninstalled and _{varcat}_nselected 291130803Smarcel 292130803Smarcel local category_list 293130803Smarcel debug= f_getvar "$var_to_get" category_list || return $FAILURE 294130803Smarcel 295130803Smarcel # Accent the category menu list with ninstalled/nselected 296130803Smarcel eval f_package_accent_category_menu category_list $category_list 297130803Smarcel 298130803Smarcel # Add list of categories to menu list 299130803Smarcel menu_list="$menu_list $category_list" 300130803Smarcel 301130803Smarcel local height width rows 302130803Smarcel eval f_dialog_menu_with_help_size height width rows \ 303130803Smarcel \"\$DIALOG_TITLE\" \ 304130803Smarcel \"\$DIALOG_BACKTITLE\" \ 305130803Smarcel \"\$prompt\" \ 306130803Smarcel \"\$hline\" \ 307130803Smarcel $menu_list 308130803Smarcel local menu_choice 309130803Smarcel menu_choice=$( eval $DIALOG \ 310130803Smarcel --title \"\$DIALOG_TITLE\" \ 311130803Smarcel --backtitle \"\$DIALOG_BACKTITLE\" \ 312130803Smarcel --hline \"\$hline\" \ 313130803Smarcel --item-help \ 314130803Smarcel --default-item \"\$defaultitem\" \ 315130803Smarcel --ok-label \"$msg_select\" \ 316130803Smarcel --cancel-label \"$msg_cancel\" \ 317130803Smarcel --menu \"\$prompt\" \ 318130803Smarcel $height $width $rows \ 319130803Smarcel $menu_list \ 320130803Smarcel 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 321130803Smarcel ) 322130803Smarcel local retval=$? 323130803Smarcel f_dialog_menutag_store -s "$menu_choice" 324130803Smarcel return $retval 325130803Smarcel} 326130803Smarcel 327130803Smarcel# f_package_index_get_page $category $page [$var_to_set [$var_to_get]] 328130803Smarcel# 329130803Smarcel# Obtain a [potentially cached] page of the INDEX file for a given $category. 330130803Smarcel# If $page is 1 and the cache has not yet been generated, the cache-generating 331130803Smarcel# function f_index_extract_pages() (above) is called to generate all pages 332130803Smarcel# (not just the requested page) in cache before returning the requested page. 333130803Smarcel# If $page is not 1 and there is no cached page, failure status is returned. 334130803Smarcel# 335130803Smarcelf_package_index_get_page() 336130803Smarcel{ 337130803Smarcel local category="$1" page="$2" var_to_set="$3" var_to_get="$4" varcat 338130803Smarcel f_str2varname "$category" varcat 339130803Smarcel if ! debug= f_getvar "_index_page_${varcat}_$page" $var_to_set && 340130803Smarcel [ "$page" = "1" ] 341130803Smarcel then 342130803Smarcel f_show_info "$msg_building_package_menus" 343130803Smarcel local pagesize="$PACKAGE_MENU_PAGESIZE" 344130803Smarcel f_index_extract_pages "${var_to_get:-PACKAGE_INDEX}" \ 345130803Smarcel _index_page_${varcat} "$pagesize" "$category" 346130803Smarcel debug= f_getvar _index_page_${varcat}_$page $var_to_set 347130803Smarcel 348130803Smarcel # Update category default-item because now we're cached 349130803Smarcel [ $page -eq 1 ] && 350130803Smarcel category_defaultitem="${category_defaultitem%\*}*" 351130803Smarcel else 352130803Smarcel return $FAILURE 353130803Smarcel fi 354130803Smarcel} 355130803Smarcel 356130803Smarcel# f_package_menu_select $category [$page [$defaultitem]] 357130803Smarcel# 358130803Smarcel# Display list of packages for $category, optionally $page N and with a default 359130803Smarcel# item selected. If $page is omitted, the first page is displayed (but this 360130803Smarcel# only matters if there are multiple pages; which is determined by the global 361130803Smarcel# maximum $PACKAGE_MENU_PAGESIZE). 362130803Smarcel# 363130803Smarcel# On success, if the user doesn't press ESC or choose Cancel, the environment 364130803Smarcel# variable $DIALOG_MENUITEM_$$ will hold the item associated with the chosen 365130803Smarcel# tag (accessible through f_dialog_menutag_fetch()). 366130803Smarcel# 367130803Smarcelf_package_menu_select() 368130803Smarcel{ 369130803Smarcel local category="$1" page="${2:-1}" 370130803Smarcel local prompt= # Calculated below 371130803Smarcel local menu_list # Calculated below 372130803Smarcel local defaultitem="$3" 373130803Smarcel local hline="$hline_arrows_tab_punc_enter" 374130803Smarcel 375130803Smarcel f_isinteger "$page" || return $FAILURE 376130803Smarcel 377130803Smarcel local varcat 378130803Smarcel f_str2varname "$category" varcat 379130803Smarcel 380130803Smarcel # Get number of packages for this category 381130803Smarcel local npkgs=0 382130803Smarcel case "$category" in 383130803Smarcel "$msg_all"|"") npkgs="${_npkgs:-0}";; 384130803Smarcel *) f_getvar _npkgs_$varcat npkgs 385130803Smarcel esac 386130803Smarcel 387130803Smarcel # Calculate number of pages 388130803Smarcel local npages=$(( ${npkgs:=0} / $PACKAGE_MENU_PAGESIZE )) 389130803Smarcel 390130803Smarcel # Add a page to the pagecount if not evenly divisible 391130803Smarcel [ $(( $npages * $PACKAGE_MENU_PAGESIZE )) -lt $npkgs ] && 392130803Smarcel npages=$(( $npages + 1 )) 393130803Smarcel 394130803Smarcel # Print some debugging information 395130803Smarcel f_dprintf "f_package_menu_select: category=[%s] npkgs=%u npages=%u" \ 396130803Smarcel "$category" "$npkgs" "$npages" 397130803Smarcel 398130803Smarcel local add_prev="" add_next="" 399130803Smarcel local previous_page="$msg_previous_page" next_page="$msg_next_page" 400130803Smarcel if [ $page -gt 1 ]; then 401130803Smarcel add_prev=1 402130803Smarcel # Accent the `Previous Page' item with an asterisk 403130803Smarcel # if the page-before-previous is loaded/cached 404130803Smarcel f_isset _index_page_${varcat}_$(( $page - 1 )) && 405130803Smarcel previous_page="$previous_page*" 406130803Smarcel fi 407130803Smarcel if [ $page -lt $npages ]; then 408130803Smarcel add_next=1 409130803Smarcel # Accent the `Next Page' item with an asterisk 410130803Smarcel # if the page-after-next is loaded/cached 411130803Smarcel f_isset _index_page_${varcat}_$(( $page + 1 )) && 412130803Smarcel next_page="$next_page*" 413130803Smarcel fi 414130803Smarcel 415130803Smarcel local index_page 416130803Smarcel f_package_index_get_page "$category" $page index_page 417130803Smarcel 418130803Smarcel menu_list=" 419130803Smarcel ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} 420130803Smarcel ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} 421130803Smarcel $( 422130803Smarcel export SHOW_DESC 423130803Smarcel export VALID_VARNAME_CHARS 424130803Smarcel echo "$index_page" | awk -F'|' -v view="port" ' 425130803Smarcel BEGIN { 426130803Smarcel valid_chars = ENVIRON["VALID_VARNAME_CHARS"] 427130803Smarcel prefix = "" 428130803Smarcel } 429130803Smarcel { 430130803Smarcel cur_prefix = tolower(substr($1, 1, 1)) 431130803Smarcel printf "'\''" 432130803Smarcel if ( prefix != cur_prefix ) 433130803Smarcel prefix = cur_prefix 434130803Smarcel else 435130803Smarcel printf " " 436130803Smarcel package = $1 437130803Smarcel if ( view == "port" ) 438130803Smarcel desc = $2 439130803Smarcel varpkg = package 440130803Smarcel gsub("[^" valid_chars "]", "_", varpkg) 441130803Smarcel mark = ENVIRON["_mark_" varpkg] 442130803Smarcel if ( ! mark ) mark = " " 443130803Smarcel printf "%s'\'' '\''[%c] %s'\''", 444130803Smarcel package, mark, desc 445130803Smarcel if ( ENVIRON["SHOW_DESC"] ) { 446130803Smarcel help = $4 447130803Smarcel gsub(/'\''/, "'\''\\'\'\''", help) 448130803Smarcel printf " '\''%s'\''", help 449130803Smarcel } 450130803Smarcel printf "\n" 451130803Smarcel }' 452130803Smarcel ) 453130803Smarcel ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} 454130803Smarcel ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} 455130803Smarcel " # End-Quote 456130803Smarcel 457130803Smarcel # Accept/Translate i18n "All" but other category names must 458130803Smarcel # match tree definitions from INDEX, ports, FTP, etc. 459130803Smarcel case "$category" in 460130803Smarcel "$msg_all"|"") f_category_desc_get "All" prompt ;; 461130803Smarcel *) f_category_desc_get "$category" prompt ;; 462130803Smarcel esac 463130803Smarcel prompt="$prompt $( printf "$msg_page_of_npages" \ 464130803Smarcel "$page" "$npages" )" 465130803Smarcel 466130803Smarcel local mheight mwidth mrows 467130803Smarcel f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \ 468130803Smarcel \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \ 469130803Smarcel \"\$prompt\" \"\$hline\" $menu_list 470130803Smarcel local iheight iwidth 471130803Smarcel f_dialog_infobox_size iheight iwidth \ 472130803Smarcel "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \ 473130803Smarcel "$msg_processing_selection" 474130803Smarcel 475130803Smarcel local menu_choice 476130803Smarcel menu_choice=$( eval $DIALOG \ 477130803Smarcel --title \"\$DIALOG_TITLE\" \ 478130803Smarcel --backtitle \"\$DIALOG_BACKTITLE\" \ 479130803Smarcel --hline \"\$hline\" \ 480130803Smarcel --keep-tite \ 481130803Smarcel --ok-label \"$msg_select\" \ 482130803Smarcel --cancel-label \"$msg_back\" \ 483130803Smarcel ${SHOW_DESC:+--item-help} \ 484130803Smarcel --default-item \"\$defaultitem\" \ 485130803Smarcel --menu \"\$prompt\" \ 486130803Smarcel $mheight $mwidth $mrows \ 487130803Smarcel $menu_list \ 488130803Smarcel --and-widget \ 489130803Smarcel ${USE_XDIALOG:+--no-buttons} \ 490130803Smarcel --infobox \"\$msg_processing_selection\" \ 491130803Smarcel $iheight $iwidth \ 492130803Smarcel 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 493130803Smarcel ) 494130803Smarcel local retval=$? 495130803Smarcel f_dialog_data_sanitize menu_choice 496130803Smarcel f_dialog_menutag_store "$menu_choice" 497130803Smarcel 498130803Smarcel if [ $retval -eq $SUCCESS ]; then 499130803Smarcel local item 500130803Smarcel item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \ 501130803Smarcel \"\$menu_choice\" $menu_list ) 502130803Smarcel setvar DIALOG_MENUITEM_$$ "$item" 503130803Smarcel fi 504130803Smarcel 505130803Smarcel return $retval 506130803Smarcel} 507130803Smarcel 508130803Smarcel# f_package_menu_deselect $package 509130803Smarcel# 510130803Smarcel# Display a menu, asking the user what they would like to do with $package 511130803Smarcel# with regard to "deselecting" an already installed package. Choices include 512130803Smarcel# uninstall, re-install, or cancel (leave $package marked as installed). 513130803Smarcel# Returns success if the user does not press ESC or choose Cnacel. Use the 514130803Smarcel# f_dialog_menutag_fetch() function upon success to retrieve the user's choice. 515130803Smarcel# 516130803Smarcelf_package_menu_deselect() 517130803Smarcel{ 518130803Smarcel local package="$1" 519130803Smarcel local prompt # Calculated below 520130803Smarcel local menu_list=" 521130803Smarcel 'X $msg_installed' '$msg_installed_desc' 522130803Smarcel 'R $msg_reinstall' '$msg_reinstall_desc' 523130803Smarcel 'U $msg_uninstall' '$msg_uninstall_desc' 524130803Smarcel " # End-Quote 525130803Smarcel local hline="$hline_alnum_arrows_punc_tab_enter" 526130803Smarcel 527130803Smarcel prompt=$( printf "$msg_what_would_you_like_to_do_with" "$package" ) 528130803Smarcel 529130803Smarcel local height width rows 530130803Smarcel eval f_dialog_menu_size height width rows \ 531130803Smarcel \"\$DIALOG_TITLE\" \ 532130803Smarcel \"\$DIALOG_BACKTITLE\" \ 533130803Smarcel \"\$prompt\" \ 534130803Smarcel \"\$hline\" \ 535130803Smarcel $menu_list 536130803Smarcel local menu_choice 537130803Smarcel menu_choice=$( eval $DIALOG \ 538130803Smarcel --title \"\$DIALOG_TITLE\" \ 539130803Smarcel --backtitle \"\$DIALOG_BACKTITLE\" \ 540130803Smarcel --hline \"\$hline\" \ 541130803Smarcel --ok-label \"$msg_select\" \ 542130803Smarcel --cancel-label \"$msg_cancel\" \ 543130803Smarcel --menu \"\$prompt\" \ 544130803Smarcel $height $width $rows \ 545130803Smarcel $menu_list \ 546130803Smarcel 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 547130803Smarcel ) 548130803Smarcel local retval=$? 549130803Smarcel f_dialog_menutag_store -s "$menu_choice" 550130803Smarcel return $retval 551130803Smarcel} 552130803Smarcel 553130803Smarcel# f_package_review 554130803Smarcel# 555130803Smarcel# Display a review screen, showing selected packages and what they are marked 556130803Smarcel# for, before proceeding (if the user does not press ESC or choose Cancel) to 557130803Smarcel# operate on each selection. Returns error if no packages have been selected, 558130803Smarcel# or the user has pressed ESC, or if they have chosen Cancel. 559130803Smarcel# 560130803Smarcelf_package_review() 561130803Smarcel{ 562130803Smarcel local prompt # Calculated below 563130803Smarcel local menu_list # Calculated below 564130803Smarcel local hline="$hline_alnum_arrows_punc_tab_enter" 565130803Smarcel 566130803Smarcel f_dprintf "f_package_review: SELECTED_PACKAGES=[%s]" \ 567130803Smarcel "$SELECTED_PACKAGES" 568130803Smarcel 569130803Smarcel prompt=$( printf "$msg_reviewing_selected_packages" "$_All_nselected" ) 570130803Smarcel 571130803Smarcel local package varpkg mark 572130803Smarcel for package in $SELECTED_PACKAGES; do 573130803Smarcel mark= 574130803Smarcel f_str2varname "$package" varpkg 575130803Smarcel f_getvar _mark_$varpkg mark 576130803Smarcel [ "$mark" -a ! "${mark#[IRUD]}" ] || continue 577130803Smarcel menu_list="$menu_list 578130803Smarcel '$mark' '$package' 579130803Smarcel " # End-Quote 580130803Smarcel done 581130803Smarcel if [ ! "$menu_list" ]; then 582130803Smarcel f_show_msg "$msg_no_packages_were_selected_for_extraction" 583130803Smarcel return $FAILURE # They might have selected this by accident 584130803Smarcel fi 585130803Smarcel menu_list=$( echo "$menu_list" | sort ) 586130803Smarcel 587130803Smarcel local height width rows 588130803Smarcel eval f_dialog_menu_size height width rows \ 589130803Smarcel \"\$DIALOG_TITLE\" \ 590130803Smarcel \"\$DIALOG_BACKTITLE\" \ 591130803Smarcel \"\$prompt\" \ 592130803Smarcel \"\$hline\" \ 593130803Smarcel $menu_list 594130803Smarcel 595130803Smarcel # Show the review menu (ignore menu choice) 596130803Smarcel eval $DIALOG \ 597130803Smarcel --title \"\$DIALOG_TITLE\" \ 598130803Smarcel --backtitle \"\$DIALOG_BACKTITLE\" \ 599130803Smarcel --hline \"\$hline\" \ 600130803Smarcel --ok-label \"\$msg_proceed\" \ 601130803Smarcel --cancel-label \"\$msg_cancel\" \ 602130803Smarcel --menu \"\$prompt\" \ 603130803Smarcel $height $width $rows \ 604130803Smarcel $menu_list \ 605130803Smarcel 2> /dev/null 606130803Smarcel local retval=$? 607130803Smarcel 608130803Smarcel # 609130803Smarcel # XXX 610130803Smarcel # 611130803Smarcel f_show_msg "Coming soon..." 612130803Smarcel # 613130803Smarcel # XXX 614130803Smarcel # 615130803Smarcel 616130803Smarcel return $retval 617130803Smarcel} 618130803Smarcel 619130803Smarcel# f_package_config 620130803Smarcel# 621130803Smarcel# Allow the user to configure packages and install them. Initially, a list of 622130803Smarcel# package categories is loaded/displayed. When the user selects a category, 623130803Smarcel# the menus for that category are built (unlike sysinstall which built all 624130803Smarcel# category menus up-front -- which also took forever, despite the fact that 625130803Smarcel# few people visit more than a couple of categories each time). 626130803Smarcel# 627130803Smarcelf_package_config() 628130803Smarcel{ 629130803Smarcel # Did we get an INDEX? 630130803Smarcel f_index_initialize packages/INDEX || return $FAILURE 631130803Smarcel # Creates following variables (indirectly via f_index_read()) 632130803Smarcel # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} 633130803Smarcel # PACKAGE_CATEGORIES _npkgs 634130803Smarcel 635130803Smarcel # Detect installed packages (updates marks/SELECTED_PACKAGES) 636130803Smarcel f_package_detect_installed 637130803Smarcel 638130803Smarcel local retval category varcat defaultitem category_defaultitem="" 639130803Smarcel while :; do 640130803Smarcel # Display the list of package categories 641130803Smarcel f_package_menu_categories \ 642130803Smarcel CATEGORY_MENU_LIST "$category_defaultitem" 643130803Smarcel retval=$? 644130803Smarcel f_dialog_menutag_fetch category 645130803Smarcel f_dprintf "retval=%u mtag=[%s]" $retval "$category" 646130803Smarcel category_defaultitem="$category" 647130803Smarcel 648130803Smarcel [ $retval -eq $SUCCESS ] || break 649130803Smarcel 650130803Smarcel # Maybe the user chose an action (like `Review') 651130803Smarcel case "$category" in 652130803Smarcel "> $msg_review") 653130803Smarcel f_package_review && break 654130803Smarcel continue ;; 655130803Smarcel "> "*) 656130803Smarcel continue 657130803Smarcel esac 658130803Smarcel 659130803Smarcel # Anything else is a package category 660130803Smarcel 661130803Smarcel category=${category# } # Trim leading space if present 662130803Smarcel category=${category%\*} # Trim trailing asterisk if present 663130803Smarcel 664130803Smarcel f_str2varname "$category" varcat 665130803Smarcel 666130803Smarcel local page package varpkg mark menu_choice 667130803Smarcel while :; do 668130803Smarcel # Display the list of packages for selected category 669130803Smarcel page=1 defaultitem="" 670130803Smarcel f_getvar _defaultitem_$varcat defaultitem 671130803Smarcel f_getvar _defaultpage_$varcat page 672130803Smarcel f_package_menu_select \ 673130803Smarcel "$category" "${page:=1}" "$defaultitem" 674130803Smarcel retval=$? 675130803Smarcel f_dialog_menutag_fetch menu_choice 676130803Smarcel f_dprintf "retval=%u mtag=[%s]" $retval "$menu_choice" 677130803Smarcel 678130803Smarcel # NOTE: When --and-widget is used only ESC will cause 679130803Smarcel # dialog(1) to return without going to the next widget. 680130803Smarcel # This is alright in our case as we can still detect 681130803Smarcel # the Cancel button because stdout will be NULL. 682130803Smarcel # Alternatively, Xdialog(1) will terminate with 1 683130803Smarcel # if/when Cancel is chosen on any widget. 684130803Smarcel if [ $retval -eq 255 -o ! "$menu_choice" ]; then 685130803Smarcel # User pressed ESC or chose Cancel 686130803Smarcel break 687130803Smarcel elif [ $retval -eq 1 ]; then 688130803Smarcel # Using X11, Xdialog(1) returned 1 for Cancel 689130803Smarcel f_show_msg "%s" "$menu_choice" 690130803Smarcel break 691130803Smarcel elif [ $retval -ne $SUCCESS ]; then 692130803Smarcel # X11-related error occurred using Xdialog(1) 693130803Smarcel f_show_msg "%s" "$menu_choice" 694130803Smarcel break 695130803Smarcel fi 696130803Smarcel 697130803Smarcel defaultitem="$menu_choice" 698130803Smarcel 699130803Smarcel # NOTE: f_package_menu_select() does not show the 700130803Smarcel # `Previous Page' or `Next Page' items unless needed 701130803Smarcel case "$menu_choice" in 702130803Smarcel "> $msg_previous_page"|"> $msg_previous_page*") 703130803Smarcel page=$(( $page - 1 )) 704130803Smarcel setvar _defaultpage_$varcat $page 705130803Smarcel # Update default-item to match accent that will 706130803Smarcel # be applied by f_package_menu_select(); if the 707130803Smarcel # page-before-prev is cached, add an asterisk. 708130803Smarcel if f_isset \ 709130803Smarcel _index_page_${varcat}_$(( $page - 1 )) 710130803Smarcel then 711130803Smarcel defaultitem="${defaultitem%\*}*" 712130803Smarcel else 713130803Smarcel defaultitem="${defaultitem%\*}" 714130803Smarcel fi 715130803Smarcel setvar _defaultitem_$varcat "$defaultitem" 716130803Smarcel continue ;; 717130803Smarcel "> $msg_next_page"|"> $msg_next_page*") 718130803Smarcel page=$(( $page + 1 )) 719130803Smarcel setvar _defaultpage_$varcat $page 720130803Smarcel # Update default-item to match accent that will 721130803Smarcel # be applied by f_package_menu_select(); if the 722130803Smarcel # page-after-next is cached, add an asterisk. 723130803Smarcel if f_isset \ 724130803Smarcel _index_page_${varcat}_$(( $page + 1 )) 725130803Smarcel then 726130803Smarcel defaultitem="${defaultitem%\*}*" 727130803Smarcel else 728130803Smarcel defaultitem="${defaultitem%\*}" 729130803Smarcel fi 730130803Smarcel setvar _defaultitem_$varcat "$defaultitem" 731130803Smarcel continue ;; 732130803Smarcel "> "*) # Unknown navigation/action item 733130803Smarcel setvar _defaultpage_$varcat $page 734130803Smarcel continue ;; # Do not treat as a package 735130803Smarcel *) 736130803Smarcel setvar _defaultitem_$varcat "$defaultitem" 737130803Smarcel esac 738130803Smarcel 739130803Smarcel # Treat any other selection as a package 740130803Smarcel package="${menu_choice# }" # Trim leading space 741130803Smarcel f_str2varname $package varpkg 742130803Smarcel f_getvar DIALOG_MENUITEM_$$ mark 743130803Smarcel mark="${mark#?}" 744130803Smarcel mark="${mark%%\] *}" 745130803Smarcel case "$mark" in 746130803Smarcel "I") 747130803Smarcel mark=" " 748130803Smarcel f_package_deselect $package 749130803Smarcel ;; 750130803Smarcel " "|"D") 751130803Smarcel mark="I" 752130803Smarcel f_package_select $package 753130803Smarcel ;; 754130803Smarcel "X"|"R"|"U") 755130803Smarcel f_package_menu_deselect $package || continue 756130803Smarcel f_dialog_menutag_fetch menu_choice 757130803Smarcel case "$menu_choice" in 758130803Smarcel "X $msg_installed") 759130803Smarcel f_package_deselect "$package" 760130803Smarcel mark="X" 761130803Smarcel ;; 762130803Smarcel "R $msg_reinstall") 763130803Smarcel f_package_select "$package" 764130803Smarcel mark="R" 765130803Smarcel ;; 766130803Smarcel "U $msg_uninstall") 767130803Smarcel f_package_select "$package" 768130803Smarcel mark="U" 769130803Smarcel ;; 770130803Smarcel esac 771130803Smarcel ;; 772130803Smarcel esac 773130803Smarcel export _mark_$varpkg="$mark" 774130803Smarcel # NOTE: exported for awk(1) ENVIRON[] 775130803Smarcel done 776130803Smarcel done 777130803Smarcel} 778130803Smarcel 779130803Smarcel############################################################ MAIN 780130803Smarcel 781130803Smarcelf_dprintf "%s: Successfully loaded." packages/packages.subr 782130803Smarcel 783130803Smarcelfi # ! $_PACKAGES_PACKAGES_SUBR 784130803Smarcel