1252995Sdteskeif [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_SUBR=1 2252995Sdteske# 3252995Sdteske# Copyright (c) 2013 Devin Teske 4252995Sdteske# All rights reserved. 5252995Sdteske# 6252995Sdteske# Redistribution and use in source and binary forms, with or without 7252995Sdteske# modification, are permitted provided that the following conditions 8252995Sdteske# are met: 9252995Sdteske# 1. Redistributions of source code must retain the above copyright 10252995Sdteske# notice, this list of conditions and the following disclaimer. 11252995Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12252995Sdteske# notice, this list of conditions and the following disclaimer in the 13252995Sdteske# documentation and/or other materials provided with the distribution. 14252995Sdteske# 15252995Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16252995Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17252995Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18252995Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19252995Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20252995Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21252995Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22252995Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23252995Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24252995Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25252995Sdteske# SUCH DAMAGE. 26252995Sdteske# 27252995Sdteske# $FreeBSD$ 28252995Sdteske# 29252995Sdteske############################################################ INCLUDES 30252995Sdteske 31252995SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32252995Sdteske. $BSDCFG_SHARE/common.subr || exit 1 33252995Sdteskef_dprintf "%s: loading includes..." "$0" 34252995Sdteskef_include $BSDCFG_SHARE/dialog.subr 35252995Sdteskef_include $BSDCFG_SHARE/device.subr 36252995Sdteskef_include $BSDCFG_SHARE/media/common.subr 37252995Sdteskef_include $BSDCFG_SHARE/packages/categories.subr 38252995Sdteskef_include $BSDCFG_SHARE/packages/index.subr 39252995Sdteskef_include $BSDCFG_SHARE/strings.subr 40252995Sdteske 41252995SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 42252995Sdteskef_include_lang $BSDCFG_LIBE/include/messages.subr 43252995Sdteske 44252995Sdteske############################################################ CONFIGURATION 45252995Sdteske 46252995Sdteske# 47252995Sdteske# How many packages to display (maximum) per dialog menubox. 48252995Sdteske# 49252995Sdteske: ${PACKAGE_MENU_PAGESIZE:=2000} 50252995Sdteske 51252995Sdteske############################################################ GLOBALS 52252995Sdteske 53252995Sdteske# 54252995Sdteske# Package extensions to try 55252995Sdteske# 56267892SgjbPACKAGE_EXTENSIONS=".txz .tbz .tbz2 .tgz" 57252995Sdteske 58252995Sdteske# 59252995Sdteske# Variables used to track runtime states 60252995Sdteske# 61252995SdteskePACKAGES_DETECTED= # Boolean (NULL/non-NULL); detected installed packages? 62252995SdteskePACKAGE_CATEGORIES= # List of package categories parsed from INDEX 63252995SdteskeSELECTED_PACKAGES= # Packages selected by user in [X]dialog(1) interface 64252995Sdteske 65252995Sdteske# 66252995Sdteske# Options 67252995Sdteske# 68252995Sdteske[ "${SHOW_DESC+set}" ] || SHOW_DESC=1 69252995Sdteske 70252995Sdteske############################################################ FUNCTIONS 71252995Sdteske 72252995Sdteske# eval f_package_accent_category_menu $var_to_set $CATEGORY_MENU_LIST 73252995Sdteske# 74252995Sdteske# Accent the CATEGORY_MENU_LIST produced by f_index_read() (see 75252995Sdteske# packages/index.subr). Accented information includes adding an asterisk to the 76252995Sdteske# category name if its index has been cached, adding the number of installed 77252995Sdteske# packages for each category, and adding the number _selected_ packages for 78252995Sdteske# each category. 79252995Sdteske# 80252995Sdteske# NOTE: The reason `eval' is recommended/shown for the syntax above is because 81252995Sdteske# the $CATEGORY_MENU_LIST generated by f_index_read() is meant to be expanded 82252995Sdteske# prior to execution (it contains a series of pre-quoted strings which act as 83252995Sdteske# the interpolated command arguments). 84252995Sdteske# 85252995Sdteskef_package_accent_category_menu() 86252995Sdteske{ 87252995Sdteske local var_to_set="$1" category cat desc help varcat menu_buf n 88252995Sdteske shift 1 # var_to_set 89252995Sdteske while [ $# -gt 0 ]; do 90252995Sdteske category="${1%\*}" desc="${2%%; *}" help="$3" 91252995Sdteske shift 3 # cat/desc/help 92252995Sdteske 93252995Sdteske cat="${category# }" # Trim lead space inserted by sort-method 94252995Sdteske f_str2varname "$cat" varcat 95252995Sdteske 96252995Sdteske # Add number of installed packages for this category (if any) 97252995Sdteske n=0 98252995Sdteske case "$cat" in 99252995Sdteske "$msg_all") debug= f_getvar "_All_ninstalled" n ;; 100252995Sdteske *) debug= f_getvar "_${varcat}_ninstalled" n ;; 101252995Sdteske esac && 102252995Sdteske [ $n -ge 1 ] && desc="$desc; $n $msg_installed_lc" 103252995Sdteske 104252995Sdteske # Add number of selected packages for this category (if any) 105252995Sdteske n=0 106252995Sdteske case "$cat" in 107252995Sdteske "$msg_all") debug= f_getvar "_All_nselected" n ;; 108252995Sdteske *) debug= f_getvar "_${varcat}_nselected" n ;; 109252995Sdteske esac && 110252995Sdteske [ $n -ge 1 ] && desc="$desc; $n $msg_selected" 111252995Sdteske 112252995Sdteske # Re-Add asterisk to the category if its index has been cached 113252995Sdteske f_isset _index_page_${varcat}_1 && category="$category*" 114252995Sdteske 115252995Sdteske # Update buffer with modified elements 116252995Sdteske menu_buf="$menu_buf 117252995Sdteske '$category' '$desc' '$help'" # End-Quote 118252995Sdteske done 119252995Sdteske setvar "$var_to_set" "$menu_buf" # return our buffer 120252995Sdteske} 121252995Sdteske 122252995Sdteske# f_package_select $package ... 123252995Sdteske# 124252995Sdteske# Add $package to the list of tracked/selected packages. If $package is already 125252995Sdteske# being tracked (already apears in $SELECTED_PACKAGES), this function amounts 126252995Sdteske# to having no effect. 127252995Sdteske# 128252995Sdteskef_package_select() 129252995Sdteske{ 130252995Sdteske local package pkgsel 131252995Sdteske while [ $# -gt 0 ]; do 132252995Sdteske package="$1" 133252995Sdteske shift 1 # package 134252995Sdteske for pkgsel in $SELECTED_PACKAGES; do 135263791Sdteske [ "$package" = "$pkgsel" ] && return $SUCCESS 136252995Sdteske done 137252995Sdteske SELECTED_PACKAGES="$SELECTED_PACKAGES $package" 138252995Sdteske f_dprintf "Added %s to selection list" "$package" 139252995Sdteske done 140252995Sdteske SELECTED_PACKAGES="${SELECTED_PACKAGES# }" # Trim leading space 141252995Sdteske} 142252995Sdteske 143252995Sdteske# f_package_deselect $package ... 144252995Sdteske# 145252995Sdteske# Remove $package from teh list of tracked/selected packages. If $package is 146252995Sdteske# not being tracked (doesn't appear in $SELECTED_PACKAGES), this function 147252995Sdteske# amounts to having no effet. 148252995Sdteske# 149252995Sdteskef_package_deselect() 150252995Sdteske{ 151252995Sdteske local package pkgsel 152252995Sdteske while [ $# -gt 1 ]; do 153252995Sdteske local new_list="" 154252995Sdteske package="$1" 155252995Sdteske shift 1 # package 156252995Sdteske for pkgsel in $SELECTED_PACKAGES; do 157252995Sdteske [ "$pkgsel" = "$package" ] && continue 158252995Sdteske new_list="$new_list${new_list:+ }$pkgsel" 159252995Sdteske done 160252995Sdteske SELECTED_PACKAGES="$new_list" 161252995Sdteske f_dprintf "Removed %s from selection list" "$package" 162252995Sdteske done 163252995Sdteske} 164252995Sdteske 165252995Sdteske# f_package_detect_installed 166252995Sdteske# 167267892Sgjb# Detect installed packages. Currently this uses pkg-query(8) for querying 168252995Sdteske# entries and marks each entry as an installed/selected package. 169252995Sdteske# 170252995Sdteskef_package_detect_installed() 171252995Sdteske{ 172267892Sgjb local package varpkg 173267892Sgjb for package in $( pkg query "%n-%v" ); do 174252995Sdteske f_str2varname $package varpkg 175252995Sdteske export _mark_$varpkg=X # exported for awk(1) ENVIRON[] 176252995Sdteske f_package_select $package 177252995Sdteske done 178252995Sdteske} 179252995Sdteske 180252995Sdteske# f_package_calculate_totals 181252995Sdteske# 182252995Sdteske# Calculate number of installed/selected packages for each category listed in 183252995Sdteske# $PACKAGE_CATEGORIES (the number of installed packages for $category is stored 184252995Sdteske# as $_${varcat}_ninstalled -- where $varcat is the product of `f_str2varname 185252995Sdteske# $category varcat' -- and number selected packages as $_${varcat}_nselected). 186252995Sdteske# Also calculates the total number of installed/selected packages stored as 187252995Sdteske# $_All_ninstalled and $_All_nselected. 188252995Sdteske# 189252995Sdteske# Calculations are peformed by checking "marks". A "mark" is stored as 190252995Sdteske# $_mark_$varpkg -- where $varpkg is the product of `f_str2varname $package 191252995Sdteske# varpkg'. A mark can be "X" for an installed package, `I' for a package that 192252995Sdteske# is marked for installation, "R" for a package that is marked for re-install, 193252995Sdteske# and "U" for a package that is marked for uninstallation. If a package mark is 194252995Sdteske# NULL or a single space (e.g., " "), the package is considered to be NOT 195252995Sdteske# selected (and therefore does not increment the counts calculated herein). 196252995Sdteske# 197252995Sdteskef_package_calculate_totals() 198252995Sdteske{ 199252995Sdteske local pkg varpkg mark cat varcat pkgcat n tselected=0 tinstalled=0 200252995Sdteske for cat in $PACKAGE_CATEGORIES; do 201252995Sdteske f_str2varname $cat varcat 202252995Sdteske setvar _${varcat}_ninstalled=0 203252995Sdteske setvar _${varcat}_nselected=0 204252995Sdteske done 205252995Sdteske for pkg in $SELECTED_PACKAGES; do 206252995Sdteske f_str2varname $pkg varpkg 207252995Sdteske mark= 208252995Sdteske f_getvar _mark_$varpkg mark 209252995Sdteske case "$mark" in 210252995Sdteske ""|" ") : ;; 211252995Sdteske X) tinstalled=$(( $tinstalled + 1 )) ;; 212252995Sdteske *) tselected=$(( $tselected + 1 )) 213252995Sdteske esac 214252995Sdteske f_getvar _categories_$varpkg pkgcat 215252995Sdteske for cat in $pkgcat; do 216252995Sdteske f_str2varname $cat varcat 217252995Sdteske case "$mark" in 218252995Sdteske ""|" ") : ;; 219252995Sdteske X) debug= f_getvar _${varcat}_ninstalled n 220252995Sdteske setvar _${varcat}_ninstalled $(( $n + 1 )) ;; 221252995Sdteske *) debug= f_getvar _${varcat}_nselected n 222252995Sdteske setvar _${varcat}_nselected $(( $n + 1 )) 223252995Sdteske esac 224252995Sdteske done 225252995Sdteske done 226252995Sdteske _All_nselected=$tselected 227252995Sdteske _All_ninstalled=$tinstalled 228252995Sdteske} 229252995Sdteske 230252995Sdteske# f_package_calculate_rundeps 231252995Sdteske# 232252995Sdteske# Update package dependencies by first unmarking all dependencies and then 233252995Sdteske# re-marking all dependencies of packages marked for either install ("I") or 234252995Sdteske# re-install ("R"). 235252995Sdteske# 236252995Sdteskef_package_calculate_rundeps() 237252995Sdteske{ 238252995Sdteske local pkg varpkg mark rundeps dep vardep 239252995Sdteske 240252995Sdteske # 241252995Sdteske # First unmark all the existing run-dependencies 242252995Sdteske # 243252995Sdteske f_dprintf "Unselecting package run-dependencies..." 244252995Sdteske for pkg in $SELECTED_PACKAGES; do 245252995Sdteske f_str2varname $pkg varpkg 246252995Sdteske mark= 247252995Sdteske debug= f_getvar _mark_$varpkg mark 248252995Sdteske # Only unmark if it's marked as a Dependency 249252995Sdteske if [ "$mark" = "D" ]; then 250252995Sdteske f_dprintf "%s unselected" $pkg 251252995Sdteske unset _mark_$varpkg 252252995Sdteske f_package_deselect $pkg 253252995Sdteske fi 254252995Sdteske done 255252995Sdteske 256252995Sdteske # 257252995Sdteske # Processes selected packages, adding dependencies 258252995Sdteske # 259252995Sdteske f_dprintf "Re-selecting package run-dependencies..." 260252995Sdteske for pkg in $SELECTED_PACKAGES; do 261252995Sdteske f_str2varname $pkg varpkg 262252995Sdteske mark= 263252995Sdteske debug= f_getvar _mark_$varpkg mark 264252995Sdteske # Skip pkg unless marked for [Re-]Install 265252995Sdteske [ "$mark" = "I" -o "$mark" = "R" ] || continue 266252995Sdteske f_getvar _rundeps_$varpkg rundeps 267252995Sdteske for dep in $rundeps; do 268252995Sdteske f_str2varname $dep vardep 269252995Sdteske mark= 270252995Sdteske debug= f_getvar _mark_$vardep mark 271252995Sdteske # Skip dep if already marked 272252995Sdteske [ "${mark:- }" = " " ] || continue 273252995Sdteske export _mark_$vardep="D" 274252995Sdteske f_package_select $dep 275252995Sdteske done 276252995Sdteske done 277252995Sdteske 278252995Sdteske f_dprintf "Finished recalculating dependencies." 279252995Sdteske} 280252995Sdteske 281252995Sdteske# f_package_menu_categories $var_to_set $defaultitem 282252995Sdteske# 283252995Sdteske# Dislay the menu of package categories, complete with package counts for each 284252995Sdteske# category, accents, and other miscellany. If $defaultitem is non-NULL and 285252995Sdteske# matches one of the existing menu-items, it will be pre-highlighted in the 286252995Sdteske# menu dialog (HINT: Use f_dialog_menutag_fetch() to populate a local variable 287252995Sdteske# that is passed as $defaultitem to highlight the user's last selection). 288252995Sdteske# 289252995Sdteskef_package_menu_categories() 290252995Sdteske{ 291252995Sdteske local var_to_get="$1" defaultitem="$2" 292252995Sdteske local prompt="$msg_please_select_a_category_to_display" 293252995Sdteske local menu_list=" 294252995Sdteske '> $msg_review' '$msg_review_desc' '$msg_review_help' 295252995Sdteske " # End-Quote 296252995Sdteske local hline= 297252995Sdteske 298252995Sdteske f_package_calculate_rundeps 299252995Sdteske # updates package mark variables and SELECTED_PACKAGES 300252995Sdteske f_package_calculate_totals 301252995Sdteske # creates _{varcat}_ninstalled and _{varcat}_nselected 302252995Sdteske 303252995Sdteske local category_list 304263791Sdteske debug= f_getvar "$var_to_get" category_list || return $DIALOG_CANCEL 305252995Sdteske 306252995Sdteske # Accent the category menu list with ninstalled/nselected 307252995Sdteske eval f_package_accent_category_menu category_list $category_list 308252995Sdteske 309252995Sdteske # Add list of categories to menu list 310252995Sdteske menu_list="$menu_list $category_list" 311252995Sdteske 312252995Sdteske local height width rows 313252995Sdteske eval f_dialog_menu_with_help_size height width rows \ 314252995Sdteske \"\$DIALOG_TITLE\" \ 315252995Sdteske \"\$DIALOG_BACKTITLE\" \ 316252995Sdteske \"\$prompt\" \ 317252995Sdteske \"\$hline\" \ 318252995Sdteske $menu_list 319252995Sdteske local menu_choice 320252995Sdteske menu_choice=$( eval $DIALOG \ 321252995Sdteske --title \"\$DIALOG_TITLE\" \ 322252995Sdteske --backtitle \"\$DIALOG_BACKTITLE\" \ 323252995Sdteske --hline \"\$hline\" \ 324252995Sdteske --item-help \ 325252995Sdteske --default-item \"\$defaultitem\" \ 326252995Sdteske --ok-label \"$msg_select\" \ 327252995Sdteske --cancel-label \"$msg_cancel\" \ 328252995Sdteske --menu \"\$prompt\" \ 329252995Sdteske $height $width $rows \ 330252995Sdteske $menu_list \ 331252995Sdteske 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 332252995Sdteske ) 333252995Sdteske local retval=$? 334252995Sdteske f_dialog_menutag_store -s "$menu_choice" 335252995Sdteske return $retval 336252995Sdteske} 337252995Sdteske 338252995Sdteske# f_package_index_get_page $category $page [$var_to_set [$var_to_get]] 339252995Sdteske# 340252995Sdteske# Obtain a [potentially cached] page of the INDEX file for a given $category. 341252995Sdteske# If $page is 1 and the cache has not yet been generated, the cache-generating 342252995Sdteske# function f_index_extract_pages() (above) is called to generate all pages 343252995Sdteske# (not just the requested page) in cache before returning the requested page. 344252995Sdteske# If $page is not 1 and there is no cached page, failure status is returned. 345252995Sdteske# 346252995Sdteskef_package_index_get_page() 347252995Sdteske{ 348252995Sdteske local category="$1" page="$2" var_to_set="$3" var_to_get="$4" varcat 349252995Sdteske f_str2varname "$category" varcat 350252995Sdteske if ! debug= f_getvar "_index_page_${varcat}_$page" $var_to_set && 351252995Sdteske [ "$page" = "1" ] 352252995Sdteske then 353252995Sdteske f_show_info "$msg_building_package_menus" 354252995Sdteske local pagesize="$PACKAGE_MENU_PAGESIZE" 355252995Sdteske f_index_extract_pages "${var_to_get:-PACKAGE_INDEX}" \ 356252995Sdteske _index_page_${varcat} "$pagesize" "$category" 357252995Sdteske debug= f_getvar _index_page_${varcat}_$page $var_to_set 358252995Sdteske 359252995Sdteske # Update category default-item because now we're cached 360252995Sdteske [ $page -eq 1 ] && 361252995Sdteske category_defaultitem="${category_defaultitem%\*}*" 362252995Sdteske else 363252995Sdteske return $FAILURE 364252995Sdteske fi 365252995Sdteske} 366252995Sdteske 367252995Sdteske# f_package_menu_select $category [$page [$defaultitem]] 368252995Sdteske# 369252995Sdteske# Display list of packages for $category, optionally $page N and with a default 370252995Sdteske# item selected. If $page is omitted, the first page is displayed (but this 371252995Sdteske# only matters if there are multiple pages; which is determined by the global 372252995Sdteske# maximum $PACKAGE_MENU_PAGESIZE). 373252995Sdteske# 374252995Sdteske# On success, if the user doesn't press ESC or choose Cancel, use 375252995Sdteske# f_dialog_menuitem_fetch() to populate a local variable with the item (not 376252995Sdteske# tag) corresponding to the user's selection. The tag portion of the user's 377252995Sdteske# selection is available through f_dialog_menutag_fetch(). 378252995Sdteske# 379252995Sdteskef_package_menu_select() 380252995Sdteske{ 381252995Sdteske local category="$1" page="${2:-1}" 382252995Sdteske local prompt= # Calculated below 383252995Sdteske local menu_list # Calculated below 384252995Sdteske local defaultitem="$3" 385252995Sdteske local hline="$hline_arrows_tab_punc_enter" 386252995Sdteske 387263791Sdteske f_isinteger "$page" || return $DIALOG_CANCEL 388252995Sdteske 389252995Sdteske local varcat 390252995Sdteske f_str2varname "$category" varcat 391252995Sdteske 392252995Sdteske # Get number of packages for this category 393252995Sdteske local npkgs=0 394252995Sdteske case "$category" in 395252995Sdteske "$msg_all"|"") npkgs="${_npkgs:-0}" ;; 396252995Sdteske *) f_getvar _npkgs_$varcat npkgs 397252995Sdteske esac 398252995Sdteske 399252995Sdteske # Calculate number of pages 400252995Sdteske local npages=$(( ${npkgs:=0} / $PACKAGE_MENU_PAGESIZE )) 401252995Sdteske 402252995Sdteske # Add a page to the pagecount if not evenly divisible 403252995Sdteske [ $(( $npages * $PACKAGE_MENU_PAGESIZE )) -lt $npkgs ] && 404252995Sdteske npages=$(( $npages + 1 )) 405252995Sdteske 406252995Sdteske # Print some debugging information 407252995Sdteske f_dprintf "f_package_menu_select: category=[%s] npkgs=%u npages=%u" \ 408252995Sdteske "$category" "$npkgs" "$npages" 409252995Sdteske 410252995Sdteske local add_prev="" add_next="" 411252995Sdteske local previous_page="$msg_previous_page" next_page="$msg_next_page" 412252995Sdteske if [ $page -gt 1 ]; then 413252995Sdteske add_prev=1 414252995Sdteske # Accent the `Previous Page' item with an asterisk 415252995Sdteske # if the page-before-previous is loaded/cached 416252995Sdteske f_isset _index_page_${varcat}_$(( $page - 1 )) && 417252995Sdteske previous_page="$previous_page*" 418252995Sdteske fi 419252995Sdteske if [ $page -lt $npages ]; then 420252995Sdteske add_next=1 421252995Sdteske # Accent the `Next Page' item with an asterisk 422252995Sdteske # if the page-after-next is loaded/cached 423252995Sdteske f_isset _index_page_${varcat}_$(( $page + 1 )) && 424252995Sdteske next_page="$next_page*" 425252995Sdteske fi 426252995Sdteske 427252995Sdteske local index_page 428252995Sdteske f_package_index_get_page "$category" $page index_page 429252995Sdteske 430252995Sdteske menu_list=" 431252995Sdteske ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} 432252995Sdteske ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} 433252995Sdteske $( 434252995Sdteske export SHOW_DESC 435252995Sdteske export VALID_VARNAME_CHARS 436252995Sdteske echo "$index_page" | awk -F'|' -v view="port" ' 437252995Sdteske BEGIN { 438252995Sdteske valid_chars = ENVIRON["VALID_VARNAME_CHARS"] 439252995Sdteske prefix = "" 440252995Sdteske } 441252995Sdteske { 442252995Sdteske cur_prefix = tolower(substr($1, 1, 1)) 443252995Sdteske printf "'\''" 444252995Sdteske if ( prefix != cur_prefix ) 445252995Sdteske prefix = cur_prefix 446252995Sdteske else 447252995Sdteske printf " " 448252995Sdteske package = $1 449252995Sdteske if ( view == "port" ) 450252995Sdteske desc = $2 451252995Sdteske varpkg = package 452252995Sdteske gsub("[^" valid_chars "]", "_", varpkg) 453252995Sdteske mark = ENVIRON["_mark_" varpkg] 454252995Sdteske if ( ! mark ) mark = " " 455252995Sdteske printf "%s'\'' '\''[%c] %s'\''", 456252995Sdteske package, mark, desc 457252995Sdteske if ( ENVIRON["SHOW_DESC"] ) { 458252995Sdteske help = $4 459252995Sdteske gsub(/'\''/, "'\''\\'\'\''", help) 460252995Sdteske printf " '\''%s'\''", help 461252995Sdteske } 462252995Sdteske printf "\n" 463252995Sdteske }' 464252995Sdteske ) 465252995Sdteske ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} 466252995Sdteske ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} 467252995Sdteske " # End-Quote 468252995Sdteske 469252995Sdteske # Accept/Translate i18n "All" but other category names must 470252995Sdteske # match tree definitions from INDEX, ports, FTP, etc. 471252995Sdteske case "$category" in 472252995Sdteske "$msg_all"|"") f_category_desc_get "All" prompt ;; 473252995Sdteske *) f_category_desc_get "$category" prompt ;; 474252995Sdteske esac 475263791Sdteske f_sprintf prompt "%s $msg_page_of_npages" "$prompt" "$page" "$npages" 476252995Sdteske 477252995Sdteske local mheight mwidth mrows 478252995Sdteske eval f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \ 479252995Sdteske \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \ 480252995Sdteske \"\$prompt\" \"\$hline\" $menu_list 481252995Sdteske local iheight iwidth 482252995Sdteske f_dialog_infobox_size iheight iwidth \ 483252995Sdteske "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \ 484252995Sdteske "$msg_processing_selection" 485252995Sdteske 486252995Sdteske local menu_choice 487252995Sdteske menu_choice=$( eval $DIALOG \ 488252995Sdteske --title \"\$DIALOG_TITLE\" \ 489252995Sdteske --backtitle \"\$DIALOG_BACKTITLE\" \ 490252995Sdteske --hline \"\$hline\" \ 491252995Sdteske --keep-tite \ 492252995Sdteske --ok-label \"$msg_select\" \ 493252995Sdteske --cancel-label \"$msg_back\" \ 494252995Sdteske ${SHOW_DESC:+--item-help} \ 495252995Sdteske --default-item \"\$defaultitem\" \ 496252995Sdteske --menu \"\$prompt\" \ 497252995Sdteske $mheight $mwidth $mrows \ 498252995Sdteske $menu_list \ 499252995Sdteske --and-widget \ 500252995Sdteske ${USE_XDIALOG:+--no-buttons} \ 501252995Sdteske --infobox \"\$msg_processing_selection\" \ 502252995Sdteske $iheight $iwidth \ 503252995Sdteske 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 504252995Sdteske ) 505252995Sdteske local retval=$? 506252995Sdteske f_dialog_data_sanitize menu_choice 507252995Sdteske f_dialog_menutag_store "$menu_choice" 508252995Sdteske 509263791Sdteske if [ $retval -eq $DIALOG_OK ]; then 510252995Sdteske local item 511252995Sdteske item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \ 512252995Sdteske \"\$menu_choice\" $menu_list ) 513252995Sdteske f_dialog_menuitem_store "$item" 514252995Sdteske fi 515252995Sdteske 516252995Sdteske return $retval 517252995Sdteske} 518252995Sdteske 519252995Sdteske# f_package_menu_deselect $package 520252995Sdteske# 521252995Sdteske# Display a menu, asking the user what they would like to do with $package 522252995Sdteske# with regard to "deselecting" an already installed package. Choices include 523252995Sdteske# uninstall, re-install, or cancel (leave $package marked as installed). 524252995Sdteske# Returns success if the user does not press ESC or choose Cnacel. Use the 525252995Sdteske# f_dialog_menutag_fetch() function upon success to retrieve the user's choice. 526252995Sdteske# 527252995Sdteskef_package_menu_deselect() 528252995Sdteske{ 529252995Sdteske local package="$1" 530252995Sdteske local prompt # Calculated below 531252995Sdteske local menu_list=" 532252995Sdteske 'X $msg_installed' '$msg_installed_desc' 533252995Sdteske 'R $msg_reinstall' '$msg_reinstall_desc' 534252995Sdteske 'U $msg_uninstall' '$msg_uninstall_desc' 535252995Sdteske " # End-Quote 536252995Sdteske local hline="$hline_alnum_arrows_punc_tab_enter" 537252995Sdteske 538263791Sdteske f_sprintf prompt "$msg_what_would_you_like_to_do_with" "$package" 539252995Sdteske 540252995Sdteske local height width rows 541252995Sdteske eval f_dialog_menu_size height width rows \ 542252995Sdteske \"\$DIALOG_TITLE\" \ 543252995Sdteske \"\$DIALOG_BACKTITLE\" \ 544252995Sdteske \"\$prompt\" \ 545252995Sdteske \"\$hline\" \ 546252995Sdteske $menu_list 547252995Sdteske local menu_choice 548252995Sdteske menu_choice=$( eval $DIALOG \ 549252995Sdteske --title \"\$DIALOG_TITLE\" \ 550252995Sdteske --backtitle \"\$DIALOG_BACKTITLE\" \ 551252995Sdteske --hline \"\$hline\" \ 552252995Sdteske --ok-label \"$msg_select\" \ 553252995Sdteske --cancel-label \"$msg_cancel\" \ 554252995Sdteske --menu \"\$prompt\" \ 555252995Sdteske $height $width $rows \ 556252995Sdteske $menu_list \ 557252995Sdteske 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 558252995Sdteske ) 559252995Sdteske local retval=$? 560252995Sdteske f_dialog_menutag_store -s "$menu_choice" 561252995Sdteske return $retval 562252995Sdteske} 563252995Sdteske 564252995Sdteske# f_package_review 565252995Sdteske# 566252995Sdteske# Display a review screen, showing selected packages and what they are marked 567252995Sdteske# for, before proceeding (if the user does not press ESC or choose Cancel) to 568252995Sdteske# operate on each selection. Returns error if no packages have been selected, 569252995Sdteske# or the user has pressed ESC, or if they have chosen Cancel. 570252995Sdteske# 571252995Sdteskef_package_review() 572252995Sdteske{ 573263791Sdteske local funcname=f_package_review 574252995Sdteske local prompt # Calculated below 575252995Sdteske local menu_list # Calculated below 576252995Sdteske local hline="$hline_alnum_arrows_punc_tab_enter" 577252995Sdteske 578263791Sdteske f_dprintf "$funcname: SELECTED_PACKAGES=[%s]" "$SELECTED_PACKAGES" 579252995Sdteske 580263791Sdteske f_sprintf prompt "$msg_reviewing_selected_packages" "$_All_nselected" 581252995Sdteske 582252995Sdteske local package varpkg mark 583252995Sdteske for package in $SELECTED_PACKAGES; do 584252995Sdteske mark= 585252995Sdteske f_str2varname "$package" varpkg 586252995Sdteske f_getvar _mark_$varpkg mark 587252995Sdteske [ "$mark" -a ! "${mark#[IRUD]}" ] || continue 588252995Sdteske menu_list="$menu_list 589252995Sdteske '$mark' '$package' 590252995Sdteske " # End-Quote 591252995Sdteske done 592252995Sdteske if [ ! "$menu_list" ]; then 593252995Sdteske f_show_msg "$msg_no_packages_were_selected_for_extraction" 594263791Sdteske return $DIALOG_CANCEL # Might have selected this by accident 595252995Sdteske fi 596252995Sdteske menu_list=$( echo "$menu_list" | sort ) 597252995Sdteske 598252995Sdteske local height width rows 599252995Sdteske eval f_dialog_menu_size height width rows \ 600252995Sdteske \"\$DIALOG_TITLE\" \ 601252995Sdteske \"\$DIALOG_BACKTITLE\" \ 602252995Sdteske \"\$prompt\" \ 603252995Sdteske \"\$hline\" \ 604252995Sdteske $menu_list 605252995Sdteske 606252995Sdteske # Show the review menu (ignore menu choice) 607252995Sdteske eval $DIALOG \ 608252995Sdteske --title \"\$DIALOG_TITLE\" \ 609252995Sdteske --backtitle \"\$DIALOG_BACKTITLE\" \ 610252995Sdteske --hline \"\$hline\" \ 611252995Sdteske --ok-label \"\$msg_proceed\" \ 612252995Sdteske --cancel-label \"\$msg_cancel\" \ 613252995Sdteske --menu \"\$prompt\" \ 614252995Sdteske $height $width $rows \ 615252995Sdteske $menu_list \ 616252995Sdteske 2> /dev/null || return $? 617252995Sdteske # Return if the user pressed ESC or chose Cancel/No 618252995Sdteske 619252995Sdteske # 620252995Sdteske # Process each of the selected packages: 621252995Sdteske # + First, process packages marked for Install. 622252995Sdteske # + Second, process packages marked for Re-install. 623252995Sdteske # + Finally, process packages marked for Uninstall. 624252995Sdteske # 625252995Sdteske for package in $SELECTED_PACKAGES; do 626252995Sdteske mark= 627252995Sdteske f_str2varname "$package" varpkg 628252995Sdteske debug= f_getvar _mark_$varpkg mark 629252995Sdteske [ "$mark" = "I" ] || continue 630263791Sdteske f_dprintf "$funcname: Installing %s package" "$package" 631252995Sdteske f_package_add "$package" 632252995Sdteske done 633252995Sdteske for package in $SELECTED_PACKAGES; do 634252995Sdteske mark= 635252995Sdteske f_str2varname "$package" varpkg 636252995Sdteske debug= f_getvar _mark_$varpkg mark 637252995Sdteske [ "$mark" = "R" ] || continue 638263791Sdteske f_dprintf "$funcname: Reinstalling %s package" "$package" 639252995Sdteske f_package_reinstall "$package" 640252995Sdteske done 641252995Sdteske for package in $SELECTED_PACKAGES; do 642252995Sdteske mark= 643252995Sdteske f_str2varname "$package" varpkg 644252995Sdteske debug= f_getvar _mark_$varpkg mark 645252995Sdteske [ "$mark" = "U" ] || continue 646263791Sdteske f_dprintf "$funcname: Uninstalling %s package" "$package" 647252995Sdteske f_package_delete "$package" || continue 648252995Sdteske f_package_deselect "$package" 649252995Sdteske done 650252995Sdteske 651263791Sdteske return $DIALOG_OK 652252995Sdteske} 653252995Sdteske 654252995Sdteske# f_package_config 655252995Sdteske# 656252995Sdteske# Allow the user to configure packages and install them. Initially, a list of 657252995Sdteske# package categories is loaded/displayed. When the user selects a category, 658252995Sdteske# the menus for that category are built (unlike sysinstall which built all 659252995Sdteske# category menus up-front -- which also took forever, despite the fact that 660252995Sdteske# few people visit more than a couple of categories each time). 661252995Sdteske# 662252995Sdteskef_package_config() 663252995Sdteske{ 664252995Sdteske # Did we get an INDEX? 665252995Sdteske f_index_initialize packages/INDEX || return $FAILURE 666252995Sdteske # Creates following variables (indirectly via f_index_read()) 667252995Sdteske # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} 668252995Sdteske # PACKAGE_CATEGORIES _npkgs 669252995Sdteske 670252995Sdteske # Detect installed packages (updates marks/SELECTED_PACKAGES) 671252995Sdteske f_package_detect_installed 672252995Sdteske export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] 673252995Sdteske 674252995Sdteske local retval category varcat defaultitem category_defaultitem="" 675252995Sdteske while :; do 676252995Sdteske # Display the list of package categories 677252995Sdteske f_package_menu_categories \ 678252995Sdteske CATEGORY_MENU_LIST "$category_defaultitem" 679252995Sdteske retval=$? 680252995Sdteske f_dialog_menutag_fetch category 681252995Sdteske f_dprintf "retval=%u mtag=[%s]" $retval "$category" 682252995Sdteske category_defaultitem="$category" 683252995Sdteske 684263791Sdteske [ $retval -eq $DIALOG_OK ] || break 685252995Sdteske 686252995Sdteske # Maybe the user chose an action (like `Review') 687252995Sdteske case "$category" in 688252995Sdteske "> $msg_review") 689252995Sdteske f_package_review && break 690252995Sdteske continue ;; 691252995Sdteske "> "*) 692252995Sdteske continue 693252995Sdteske esac 694252995Sdteske 695252995Sdteske # Anything else is a package category 696252995Sdteske 697252995Sdteske category=${category# } # Trim leading space if present 698252995Sdteske category=${category%\*} # Trim trailing asterisk if present 699252995Sdteske 700252995Sdteske f_str2varname "$category" varcat 701252995Sdteske 702252995Sdteske local page package varpkg mark menu_choice 703252995Sdteske while :; do 704252995Sdteske # Display the list of packages for selected category 705252995Sdteske page=1 defaultitem="" 706252995Sdteske f_getvar _defaultitem_$varcat defaultitem 707252995Sdteske f_getvar _defaultpage_$varcat page 708252995Sdteske f_package_menu_select \ 709252995Sdteske "$category" "${page:=1}" "$defaultitem" 710252995Sdteske retval=$? 711252995Sdteske f_dialog_menutag_fetch menu_choice 712252995Sdteske f_dprintf "retval=%u mtag=[%s]" $retval "$menu_choice" 713252995Sdteske 714252995Sdteske # NOTE: When --and-widget is used only ESC will cause 715252995Sdteske # dialog(1) to return without going to the next widget. 716252995Sdteske # This is alright in our case as we can still detect 717252995Sdteske # the Cancel button because stdout will be NULL. 718252995Sdteske # Alternatively, Xdialog(1) will terminate with 1 719252995Sdteske # if/when Cancel is chosen on any widget. 720263791Sdteske if [ $retval -eq $DIALOG_ESC -o ! "$menu_choice" ] 721263791Sdteske then 722252995Sdteske break 723263791Sdteske elif [ $retval -eq $DIALOG_CANCEL ]; then 724252995Sdteske # Using X11, Xdialog(1) returned 1 for Cancel 725252995Sdteske f_show_msg "%s" "$menu_choice" 726252995Sdteske break 727263791Sdteske elif [ $retval -ne $DIALOG_OK ]; then 728252995Sdteske # X11-related error occurred using Xdialog(1) 729252995Sdteske f_show_msg "%s" "$menu_choice" 730252995Sdteske break 731252995Sdteske fi 732252995Sdteske 733252995Sdteske defaultitem="$menu_choice" 734252995Sdteske 735252995Sdteske # NOTE: f_package_menu_select() does not show the 736252995Sdteske # `Previous Page' or `Next Page' items unless needed 737252995Sdteske case "$menu_choice" in 738252995Sdteske "> $msg_previous_page"|"> $msg_previous_page*") 739252995Sdteske page=$(( $page - 1 )) 740252995Sdteske setvar _defaultpage_$varcat $page 741252995Sdteske # Update default-item to match accent that will 742252995Sdteske # be applied by f_package_menu_select(); if the 743252995Sdteske # page-before-prev is cached, add an asterisk. 744252995Sdteske if f_isset \ 745252995Sdteske _index_page_${varcat}_$(( $page - 1 )) 746252995Sdteske then 747252995Sdteske defaultitem="${defaultitem%\*}*" 748252995Sdteske else 749252995Sdteske defaultitem="${defaultitem%\*}" 750252995Sdteske fi 751252995Sdteske setvar _defaultitem_$varcat "$defaultitem" 752252995Sdteske continue ;; 753252995Sdteske "> $msg_next_page"|"> $msg_next_page*") 754252995Sdteske page=$(( $page + 1 )) 755252995Sdteske setvar _defaultpage_$varcat $page 756252995Sdteske # Update default-item to match accent that will 757252995Sdteske # be applied by f_package_menu_select(); if the 758252995Sdteske # page-after-next is cached, add an asterisk. 759252995Sdteske if f_isset \ 760252995Sdteske _index_page_${varcat}_$(( $page + 1 )) 761252995Sdteske then 762252995Sdteske defaultitem="${defaultitem%\*}*" 763252995Sdteske else 764252995Sdteske defaultitem="${defaultitem%\*}" 765252995Sdteske fi 766252995Sdteske setvar _defaultitem_$varcat "$defaultitem" 767252995Sdteske continue ;; 768252995Sdteske "> "*) # Unknown navigation/action item 769252995Sdteske setvar _defaultpage_$varcat $page 770252995Sdteske continue ;; # Do not treat as a package 771252995Sdteske *) 772252995Sdteske setvar _defaultitem_$varcat "$defaultitem" 773252995Sdteske esac 774252995Sdteske 775252995Sdteske # Treat any other selection as a package 776252995Sdteske package="${menu_choice# }" # Trim leading space 777252995Sdteske f_str2varname $package varpkg 778252995Sdteske f_dialog_menuitem_fetch mark 779252995Sdteske mark="${mark#?}" 780252995Sdteske mark="${mark%%\] *}" 781252995Sdteske case "$mark" in 782252995Sdteske "I") 783252995Sdteske mark=" " 784252995Sdteske f_package_deselect $package 785252995Sdteske ;; 786252995Sdteske " "|"D") 787252995Sdteske mark="I" 788252995Sdteske f_package_select $package 789252995Sdteske ;; 790252995Sdteske "X"|"R"|"U") 791252995Sdteske f_package_menu_deselect $package || continue 792252995Sdteske f_dialog_menutag_fetch menu_choice 793252995Sdteske case "$menu_choice" in 794252995Sdteske "X $msg_installed") 795252995Sdteske f_package_deselect "$package" 796252995Sdteske mark="X" 797252995Sdteske ;; 798252995Sdteske "R $msg_reinstall") 799252995Sdteske f_package_select "$package" 800252995Sdteske mark="R" 801252995Sdteske ;; 802252995Sdteske "U $msg_uninstall") 803252995Sdteske f_package_select "$package" 804252995Sdteske mark="U" 805252995Sdteske ;; 806252995Sdteske esac 807252995Sdteske ;; 808252995Sdteske esac 809252995Sdteske export _mark_$varpkg="$mark" 810252995Sdteske # NOTE: exported for awk(1) ENVIRON[] 811252995Sdteske done 812252995Sdteske done 813252995Sdteske} 814252995Sdteske 815252995Sdteske# f_package_add $package_name [$depended] 816252995Sdteske# 817252995Sdteske# Like f_package_extract(), but assumes current media device and chases deps. 818252995Sdteske# Note that $package_name should not contain the archive suffix (e.g., `.tbz'). 819252995Sdteske# If $depended is present and non-NULL, the package is treated as a dependency 820252995Sdteske# (in this function, dependencies are not handled any differently, but the 821252995Sdteske# f_package_extract() function is passed this value and it displays a different 822252995Sdteske# message when installing a dependency versus non-dependency). 823252995Sdteske# 824252995Sdteskef_package_add() 825252995Sdteske{ 826252995Sdteske local name="$1" depended="$2" status=$SUCCESS retval 827252995Sdteske 828252995Sdteske local alert=f_show_msg no_confirm= 829252995Sdteske f_getvar $VAR_NO_CONFIRM no_confirm 830252995Sdteske [ "$no_confirm" ] && alert=f_show_info 831252995Sdteske 832252995Sdteske if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; } 833252995Sdteske then 834252995Sdteske f_dprintf "packageAdd: %s" \ 835252995Sdteske "$msg_no_package_name_passed_in_package_variable" 836252995Sdteske return $FAILURE 837252995Sdteske fi 838252995Sdteske 839252995Sdteske { # Verify and initialize device media if-defined 840252995Sdteske f_media_verify && 841266292Sdteske f_device_init device_media && 842252995Sdteske f_index_initialize packages/INDEX 843252995Sdteske } || return $FAILURE 844252995Sdteske 845252995Sdteske # Now we have (indirectly via f_index_read()): 846252995Sdteske # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} 847252995Sdteske # PACKAGE_CATEGORIES _npkgs 848252995Sdteske 849252995Sdteske local varpkg 850252995Sdteske f_str2varname "$name" varpkg 851252995Sdteske 852252995Sdteske # Just as-in the user-interface (opposed to scripted-use), only allow 853252995Sdteske # packages with at least one category to be recognized. 854252995Sdteske # 855252995Sdteske local pkgcat= 856252995Sdteske if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then 857252995Sdteske # $pkg may be a partial name, search the index (this is slow) 858252995Sdteske f_index_search PACKAGE_INDEX $name name 859252995Sdteske if [ ! "$name" ]; then 860252995Sdteske f_show_msg \ 861252995Sdteske "$msg_sorry_package_was_not_found_in_the_index" \ 862252995Sdteske "$name" 863252995Sdteske return $FAILURE 864252995Sdteske fi 865252995Sdteske f_str2varname "$name" varpkg 866252995Sdteske fi 867252995Sdteske 868252995Sdteske # If invoked through the scripted interface, we likely have not yet 869252995Sdteske # detected the installed packages -- something we should do only once. 870252995Sdteske # 871252995Sdteske if [ ! "$PACKAGES_DETECTED" ]; then 872252995Sdteske f_dprintf "f_package_add: Detecting installed packages" 873252995Sdteske f_package_detect_installed 874252995Sdteske export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] 875252995Sdteske fi 876252995Sdteske # Now we have: _mark_{varpkg}=X for all installed packages 877252995Sdteske 878252995Sdteske # 879252995Sdteske # Since we're maintaining data structures for installed packages, 880252995Sdteske # short-circuit the package dependency checks if the package is already 881252995Sdteske # installed. This prevents wasted cycles, minor delays between package 882252995Sdteske # extractions, and worst-case an infinite loop with a certain faulty 883252995Sdteske # INDEX file. 884252995Sdteske # 885252995Sdteske local mark= 886252995Sdteske f_getvar _mark_$varpkg mark && [ "$mark" = "X" ] && return $SUCCESS 887252995Sdteske 888252995Sdteske local dep vardep rundeps= 889252995Sdteske f_getvar _rundeps_$varpkg rundeps 890252995Sdteske for dep in $rundeps; do 891252995Sdteske f_str2varname "$dep" vardep 892252995Sdteske 893252995Sdteske # Skip dependency if already installed 894252995Sdteske mark= 895252995Sdteske f_getvar _mark_$vardep mark && [ "$mark" = "X" ] && continue 896252995Sdteske 897252995Sdteske # Just as-in the user-interface (opposed to scripted-use), only 898252995Sdteske # allow packages with at least one category to be recognized. 899252995Sdteske # 900252995Sdteske local depcat= 901252995Sdteske if ! f_getvar _categories_$vardep depcat || [ ! "$depcat" ] 902252995Sdteske then 903252995Sdteske $alert "$msg_required_package_not_found" "$dep" 904252995Sdteske [ "$no_confirm" ] && sleep 2 905252995Sdteske fi 906252995Sdteske 907252995Sdteske f_package_add "$dep" 908252995Sdteske retval=$? 909252995Sdteske if [ $retval -ne $SUCCESS ]; then 910252995Sdteske status=$(( $status | $retval )) 911252995Sdteske 912252995Sdteske # XXX package could be on a future disc volume 913252995Sdteske # XXX (not supporting multiple disc volumes yet) 914252995Sdteske 915252995Sdteske $alert "$msg_loading_of_dependent_package_failed" \ 916252995Sdteske "$dep" 917252995Sdteske [ "$no_confirm" ] && sleep 2 918252995Sdteske fi 919252995Sdteske done 920252995Sdteske [ $status -eq $SUCCESS ] || return $status 921252995Sdteske 922252995Sdteske # 923252995Sdteske # Done with the deps? Try to load the real m'coy. 924252995Sdteske # 925252995Sdteske 926266292Sdteske f_package_extract device_media "$name" "$depended" 927252995Sdteske retval=$? 928252995Sdteske if [ $retval -ne $SUCCESS ]; then 929252995Sdteske status=$(( $status | $retval )) 930252995Sdteske else 931252995Sdteske setvar _mark_$varpkg X 932252995Sdteske fi 933252995Sdteske 934252995Sdteske return $status 935252995Sdteske} 936252995Sdteske 937252995Sdteske# f_package_extract $device $name [$depended] 938252995Sdteske# 939252995Sdteske# Extract a package based on a namespec and media device. If $depended is 940252995Sdteske# present and non-NULL, the notification displayed while installing the package 941252995Sdteske# has "as a dependency" appended. 942252995Sdteske# 943252995Sdteskef_package_extract() 944252995Sdteske{ 945263791Sdteske local funcname=f_package_extract 946252995Sdteske local device="$1" name="$2" depended="$3" 947266292Sdteske local devname= 948252995Sdteske 949266292Sdteske $device get name devname 950263791Sdteske f_dprintf "$funcname: device=[%s] name=[%s] depended=[%s]" \ 951266292Sdteske "$devname" "$name" "$depended" 952252995Sdteske 953252995Sdteske # Check to make sure it's not already there 954252995Sdteske local varpkg mark= 955252995Sdteske f_str2varname "$name" varpkg 956252995Sdteske f_getvar _mark_$varpkg mark 957252995Sdteske [ "$mark" = "X" ] && return $SUCCESS 958252995Sdteske 959252995Sdteske if ! f_device_init $device; then 960252995Sdteske f_show_msg \ 961252995Sdteske "$msg_unable_to_initialize_media_type_for_package_extract" 962252995Sdteske return $FAILURE 963252995Sdteske fi 964252995Sdteske 965252995Sdteske # If necessary, initialize the ldconfig hints 966252995Sdteske [ -f "/var/run/ld-elf.so.hints" ] || 967252995Sdteske f_quietly ldconfig /usr/lib /usr/lib/compat /usr/local/lib 968252995Sdteske 969252995Sdteske # Make a couple paranoid locations for temp 970252995Sdteske # files to live if user specified none 971252995Sdteske local tmpdir 972252995Sdteske f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir 973252995Sdteske f_quietly mkdir -p -m 1777 "$tmpdir" 974252995Sdteske 975267892Sgjb local path device_type 976267892Sgjb $device get type device_type 977252995Sdteske case "$name" in 978252995Sdteske */*) path="$name" ;; 979252995Sdteske *) 980267892Sgjb if [ "$device_type" = "$DEVICE_TYPE_HTTP" ]; then 981267892Sgjb path="$PKG_ABI/latest/All/$name" 982267892Sgjb else 983267892Sgjb path="packages/$PKG_ABI/All/$name" 984267892Sgjb fi 985252995Sdteske esac 986252995Sdteske 987267892Sgjb # We have a path, call the device strategy routine to check the file 988263791Sdteske local pkg_ext found= 989252995Sdteske for pkg_ext in "" $PACKAGE_EXTENSIONS; do 990263791Sdteske if f_device_get $device "$path$pkg_ext" $PROBE_EXIST; then 991252995Sdteske path="$path$pkg_ext" 992252995Sdteske found=1 993252995Sdteske break 994267892Sgjb elif [ "$device_type" = "$DEVICE_TYPE_HTTP" ] && 995267892Sgjb f_device_get $device \ 996267892Sgjb "packages/$PKG_ABI/All/$name$pkg_ext" $PROBE_EXIST 997267892Sgjb then 998267892Sgjb # Mirroring physical media over HTTP 999267892Sgjb path="packages/$PKG_ABI/All/$name$pkg_ext" 1000267892Sgjb found=1 1001267892Sgjb break 1002252995Sdteske fi 1003252995Sdteske done 1004266292Sdteske [ "$found" ] && f_dprintf "$funcname: found path=[%s] dev=[%s]" \ 1005266292Sdteske "$path" "$devname" 1006252995Sdteske 1007252995Sdteske local alert=f_show_msg no_confirm= 1008252995Sdteske f_getvar $VAR_NO_CONFIRM no_confirm 1009252995Sdteske [ "$no_confirm" ] && alert=f_show_info 1010252995Sdteske 1011252995Sdteske if [ ! "$found" ]; then 1012263791Sdteske f_dprintf "$funcname: No such %s file on %s device" \ 1013266292Sdteske "$path" "$devname" 1014252995Sdteske $alert "$msg_unable_to_fetch_package_from_selected_media" \ 1015252995Sdteske "$name" 1016252995Sdteske [ "$no_confirm" ] && sleep 2 1017252995Sdteske return $FAILURE 1018252995Sdteske fi 1019252995Sdteske 1020252995Sdteske if [ "$depended" ]; then 1021252995Sdteske f_show_info "$msg_adding_package_as_a_dependency_from_media" \ 1022252995Sdteske "$name" "$devname" 1023252995Sdteske else 1024252995Sdteske f_show_info "$msg_adding_package_from_media" "$name" "$devname" 1025252995Sdteske fi 1026252995Sdteske 1027267892Sgjb # Request the package be added via pkg-install(8) 1028267892Sgjb if f_debugging; then 1029267892Sgjb f_eval_catch $funcname pkg 'pkg -d install -y "%s"' "$name" 1030267892Sgjb else 1031267892Sgjb f_eval_catch $funcname pkg 'pkg install -y "%s"' "$name" 1032267892Sgjb fi 1033252995Sdteske if [ $? -ne $SUCCESS ]; then 1034267892Sgjb $alert "$msg_pkg_install_apparently_did_not_like_the_package" \ 1035252995Sdteske "$name" 1036252995Sdteske [ "$no_confirm" ] && sleep 2 1037252995Sdteske else 1038252995Sdteske f_show_info "$msg_package_was_added_successfully" "$name" 1039252995Sdteske sleep 1 1040252995Sdteske fi 1041252995Sdteske 1042252995Sdteske return $SUCCESS 1043252995Sdteske} 1044252995Sdteske 1045252995Sdteske# f_package_delete $name 1046252995Sdteske# 1047252995Sdteske# Delete package by full $name (lacks archive suffix; e.g., `.tbz'). 1048252995Sdteske# 1049252995Sdteskef_package_delete() 1050252995Sdteske{ 1051263791Sdteske local funcname=f_package_delete 1052252995Sdteske local name="$1" 1053252995Sdteske 1054252995Sdteske if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; } 1055252995Sdteske then 1056252995Sdteske f_dprintf "packageDelete: %s" \ 1057252995Sdteske "$msg_no_package_name_passed_in_package_variable" 1058252995Sdteske return $FAILURE 1059252995Sdteske fi 1060252995Sdteske 1061263791Sdteske f_dprintf "$funcname: name=[%s]" "$name" 1062252995Sdteske 1063252995Sdteske [ "$name" ] || return $FAILURE 1064252995Sdteske 1065252995Sdteske { # Verify and initialize device media if-defined 1066252995Sdteske f_media_verify && 1067266292Sdteske f_device_init device_media && 1068252995Sdteske f_index_initialize packages/INDEX 1069252995Sdteske } || return $FAILURE 1070252995Sdteske 1071252995Sdteske # Now we have (indirectly via f_index_read()): 1072252995Sdteske # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} 1073252995Sdteske # PACKAGE_CATEGORIES _npkgs 1074252995Sdteske 1075252995Sdteske local varpkg 1076252995Sdteske f_str2varname "$name" varpkg 1077252995Sdteske 1078252995Sdteske # Just as-in the user-interface (opposed to scripted-use), only allow 1079252995Sdteske # packages with at least one category to be recognized. 1080252995Sdteske # 1081252995Sdteske local pkgcat= 1082252995Sdteske if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then 1083252995Sdteske # $pkg may be a partial name, search the index (this is slow) 1084252995Sdteske f_index_search PACKAGE_INDEX "$name" name 1085252995Sdteske if [ ! "$name" ]; then 1086252995Sdteske f_show_msg \ 1087252995Sdteske "$msg_sorry_package_was_not_found_in_the_index" \ 1088252995Sdteske "$name" 1089252995Sdteske return $FAILURE 1090252995Sdteske fi 1091252995Sdteske f_str2varname "$name" varpkg 1092252995Sdteske fi 1093252995Sdteske 1094252995Sdteske # If invoked through the scripted interface, we likely have not yet 1095252995Sdteske # detected the installed packages -- something we should do only once. 1096252995Sdteske # 1097252995Sdteske if [ ! "$PACKAGES_DETECTED" ]; then 1098263791Sdteske f_dprintf "$funcname: Detecting installed packages" 1099252995Sdteske f_package_detect_installed 1100252995Sdteske export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] 1101252995Sdteske fi 1102252995Sdteske # Now we have: _mark_{varpkg}=X for all installed packages 1103252995Sdteske 1104252995Sdteske # 1105252995Sdteske # Return failure if the package is not already installed. 1106252995Sdteske # 1107252995Sdteske local pkgmark= 1108252995Sdteske f_getvar _mark_$varpkg pkgmark 1109252995Sdteske if ! [ "$pkgmark" -a ! "${pkgmark#[XUR]}" ]; then 1110252995Sdteske f_show_msg "$msg_package_not_installed_cannot_delete" "$name" 1111252995Sdteske return $FAILURE 1112252995Sdteske fi 1113252995Sdteske 1114252995Sdteske # 1115252995Sdteske # Check for dependencies 1116252995Sdteske # 1117252995Sdteske local pkgsel depc=0 udeps= 1118252995Sdteske for pkgsel in $SELECTED_PACKAGES; do 1119252995Sdteske local mark= 1120252995Sdteske f_str2varname $pkgsel varpkg 1121252995Sdteske debug= f_getvar _mark_$varpkg mark 1122252995Sdteske [ "$mark" -a ! "${mark#[XUR]}" ] || continue 1123252995Sdteske local dep rundeps= 1124252995Sdteske debug= f_getvar _rundeps_$varpkg rundeps 1125252995Sdteske for dep in $rundeps; do 1126252995Sdteske if [ "$dep" = "$name" ]; then 1127252995Sdteske # Maybe this package is marked for deletion too 1128252995Sdteske if [ "$mark" = "U" ]; then 1129252995Sdteske udeps="$udeps $pkgsel" 1130252995Sdteske else 1131252995Sdteske depc=$(( $depc + 1 )) 1132252995Sdteske fi 1133252995Sdteske break 1134252995Sdteske fi 1135252995Sdteske done 1136252995Sdteske done 1137252995Sdteske if [ $depc -gt 0 ]; then 1138252995Sdteske local grammatical_s= 1139252995Sdteske [ $depc -gt 1 ] && grammatical_s=s 1140252995Sdteske f_show_msg \ 1141252995Sdteske "$msg_package_is_needed_by_other_installed_packages" \ 1142252995Sdteske "$name" "$depc" "$grammatical_s" 1143252995Sdteske return $FAILURE 1144252995Sdteske fi 1145252995Sdteske 1146252995Sdteske # 1147252995Sdteske # Chase dependencies that are marked for uninstallation 1148252995Sdteske # 1149252995Sdteske for pkgsel in $udeps; do 1150263791Sdteske f_dprintf "$funcname: Uninstalling dependency %s (%s)" \ 1151263791Sdteske "$pkgsel" "marked for delete" 1152252995Sdteske f_package_delete "$pkgsel" 1153252995Sdteske done 1154252995Sdteske 1155252995Sdteske # 1156252995Sdteske # OK to perform the delete (no other packages depend on it)... 1157252995Sdteske # 1158252995Sdteske f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name" 1159252995Sdteske if f_debugging; then 1160267892Sgjb f_eval_catch $funcname pkg 'pkg -d delete -y "%s"' "$name" 1161252995Sdteske else 1162267892Sgjb f_eval_catch $funcname pkg 'pkg delete -y "%s"' "$name" 1163252995Sdteske fi 1164252995Sdteske if [ $? -ne $SUCCESS ]; then 1165252995Sdteske f_show_msg "$msg_pkg_delete_failed" "$name" 1166252995Sdteske return $FAILURE 1167252995Sdteske else 1168263791Sdteske f_dprintf "$funcname: pkg-delete(8) of %s successful" "$name" 1169252995Sdteske f_str2varname "$name" varpkg 1170252995Sdteske setvar _mark_$varpkg "" 1171252995Sdteske fi 1172252995Sdteske} 1173252995Sdteske 1174252995Sdteske# f_package_reinstall $name 1175252995Sdteske# 1176252995Sdteske# A simple wrapper to f_package_delete() + f_package_add() 1177252995Sdteske# 1178252995Sdteskef_package_reinstall() 1179252995Sdteske{ 1180252995Sdteske f_package_delete "$1" && f_package_add "$1" 1181252995Sdteske} 1182252995Sdteske 1183252995Sdteske############################################################ MAIN 1184252995Sdteske 1185252995Sdteskef_dprintf "%s: Successfully loaded." packages/packages.subr 1186252995Sdteske 1187252995Sdteskefi # ! $_PACKAGES_PACKAGES_SUBR 1188