Index: stable/9/usr.sbin/bsdconfig/include/messages.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/include/messages.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/include/messages.subr (revision 267683) @@ -1,423 +1,429 @@ # Copyright (c) 2012 Ron McDowell # Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ field_password="Password:" field_username="Username:" hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER" hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER" hline_arrows_tab_enter="Press arrows, TAB or ENTER" hline_arrows_tab_punc_enter="Use arrows, TAB, punctuation, ENTER" hline_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types" msg_accept_continue="Accept/Continue" msg_accessibility_desc="Ports to help disabled users." msg_adding_package_as_a_dependency_from_media="Adding %s (as a dependency) from %s" msg_adding_package_from_media="Adding %s from %s" msg_afterstep_desc="Ports to support the AfterStep window manager." msg_all="All" msg_all_desc="All available packages in all categories." msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s" msg_an_unknown_error_occurred="An unknown error occurred" msg_arabic_desc="Ported software for Arab countries." msg_archivers_desc="Utilities for archiving and unarchiving data." msg_armenia="Armenia" msg_assume_network_is_already_configured="Running multi-user, assume that the network is already configured?" msg_assume_yes_to_all_non_critical_dialogs="Assume \"Yes\" answers to all non-critical dialogs" msg_astro_desc="Applications related to astronomy." msg_attempt_automatic_dhcp_configuration="Attempt automatic DHCP configuration of interfaces" msg_attempt_ipv6_configuration_of_interfaces="Attempt IPv6 configuration of interfaces" -msg_attempting_to_fetch_file_from_selected_media="Attempting to fetch %s file from selected media." +msg_attempting_to_update_repository_catalogue="Attempting to update repository catalogue from selected media." msg_audio_desc="Audio utilities - most require a supported sound card." msg_australia="Australia" msg_austria="Austria" msg_back="Back" msg_becoming_root_via_sudo="Becoming root via sudo(8)..." msg_benchmarks_desc="Utilities for measuring system performance." msg_biology_desc="Software related to biology." msg_brazil="Brazil" msg_building_package_menus="Building package menu(s)..." msg_cad_desc="Computer Aided Design utilities." msg_canada="Canada" msg_cancel="Cancel" msg_cancel_exit="Cancel/Exit" msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied" msg_cannot_resolve_hostname="Cannot resolve \`%s'! Are you sure that your\nname server, gateway and network interface are correctly configured?" msg_cant_find_distribution="Warning: Can't find the \`%s' distribution on this\nFTP server. You may need to visit a different server for\nthe release you are trying to fetch or go to the Options\nmenu and set the release name to explicitly match what's\navailable on %s (or set to \"any\").\n\nWould you like to select another FTP server?" msg_cant_seem_to_write_out_resolv_conf="Can't seem to write out %s. Net cannot be used." msg_cd_dvd="CD/DVD" msg_cdrom="CDROM" msg_checking_access_to="Checking access to\n %s" msg_china="China" msg_chinese_desc="Ported software for the Chinese market." msg_choose_a_cd_dvd_type="Choose a CD/DVD type" msg_choose_a_dos_partition="Choose a DOS partition" msg_choose_a_floppy_drive="Choose a Floppy drive" msg_choose_a_ufs_partition="Choose a UFS partition" msg_choose_a_usb_drive="Choose a USB drive" msg_choose_installation_media="Choose Installation Media" msg_choose_installation_media_description="FreeBSD can be installed from a variety of different installation\nmedia, ranging from floppies to an Internet FTP server. If you're\ninstalling FreeBSD from a supported CD/DVD drive then this is generally\nthe best media to use if you have no overriding reason for using other\nmedia." msg_client_error="Client error, you could try an other server" msg_command_failed_rest_of_script_aborted="Command \`%s' failed - rest of script aborted." msg_comms_desc="Communications utilities." msg_configuration_for_interface="Configuration for Interface" msg_converters_desc="Format conversion utilities." msg_could_not_unmount_the_cdrom_dvd="Could not unmount the CDROM/DVD from %s: %s" msg_could_not_unmount_the_dos_partition="Could not unmount the DOS partition from %s: %s" msg_could_not_unmount_the_nfs_partition="Could not unmount the NFS partition from %s: %s" msg_could_not_unmount_the_ufs_partition="Could not unmount the UFS partition from %s: %s" msg_couldnt_connect_to_ftp_server="Couldn't connect to FTP server" msg_couldnt_connect_to_proxy="Couldn't connect to proxy" msg_couldnt_connect_to_server="Couldn't connect to server" msg_couldnt_open_ftp_connection="Couldn't open FTP connection to %s:\n %s." msg_created_path="Created %s" msg_czech_republic="Czech Republic" msg_databases_desc="Database software." msg_debugging="Debugging" msg_denmark="Denmark" msg_deskutils_desc="Various Desktop utilities." msg_devel_desc="Software development utilities and libraries." msg_device_is_not_configured="The %s device is not configured. You will need to do so\nin the Networking configuration menu before proceeding." msg_dhcp="DHCP" msg_dialog_mixedform_navigation_help="Use / arrows to navigate between fields, TAB to focus buttons, and Enter for OK/Cancel." msg_directory="Directory" msg_directory_not_found="%s: Directory not found." msg_directory_where_package_temporary_files_go="The directory where package temporary files should go" msg_dns_desc="Domain Name Service tools." msg_docs_desc="Meta-ports for FreeBSD documentation." msg_done="Done" msg_dos="DOS" msg_editor="Editor" msg_editors_desc="Editors." msg_elisp_desc="Things related to Emacs Lisp." msg_emit_extra_debugging_output="Emit extra debugging output" msg_emulators_desc="Utilities for emulating other operating systems." msg_enlightenment_desc="Software for the Enlightenment Desktop Environment." msg_enter_a_fully_qualified_pathname_for_the_directory="Enter a fully qualified pathname for the directory\ncontaining the FreeBSD distribution files:" msg_enter_the_device_name_of_a_ufs_formatted_partition="Enter the device-name of a UFS formatted partition" msg_error="Error" msg_error_mounting_device="Error mounting %s on %s: %s" msg_error_mounting_floppy_device="Error mounting floppy %s (%s) on %s: %s" msg_error_mounting_usb_drive="Error mounting USB drive %s on %s: %s" msg_error_when_requesting_url="Error when requesting %s, you could try an other server" msg_estonia="Estonia" msg_exit="Exit" msg_exit_bsdconfig="Exit bsdconfig" msg_extra_options_to_ifconfig="Extra options to ifconfig (usually empty):" msg_failed_to_add_default_route="Failed to add a default route; please check your network configuration" msg_file_system="File System" msg_finance_desc="Monetary, financial and related applications." msg_finland="Finland" msg_floppy="Floppy" msg_france="France" msg_french_desc="Ported software for French countries." msg_ftp="FTP" msg_ftp_desc="FTP client and server utilities." msg_ftp_passive="FTP Passive" msg_ftp_username="FTP username" msg_games_desc="Various games and sundry amusements." +msg_generating_index_from_pkg_database="Generating INDEX from pkg(8) database\n(this can take a while)..." msg_geography_desc="Geography-related software." msg_german_desc="Ported software for Germanic countries." msg_germany="Germany" +msg_getting_package_categories_via_pkg_rquery="Getting package categories via pkg-rquery(8)..." +msg_getting_package_dependencies_via_pkg_rquery="Getting package dependencies via pkg-rquery(8)\n(this can take a while)..." msg_gnome_desc="Components of the Gnome Desktop environment." msg_gnustep_desc="Software for GNUstep desktop environment." msg_graphics_desc="Graphics libraries and utilities." msg_greece="Greece" msg_hamradio_desc="Software for amateur radio." msg_haskell_desc="Software related to the Haskell language." msg_hebrew_desc="Ported software for Hebrew language." msg_help="Help" msg_host_name_including_domain="Host name (including domain)" msg_hostname_variable_not_set="WARNING: hostname variable not set and is a non-optional\nparameter. Please add this to your installation script\nor set the netInteractive variable (see bsdconfig man page)" msg_http_direct="HTTP Direct" msg_http_proxy="HTTP Proxy" msg_hungarian_desc="Ported software for the Hungarian market." msg_iceland="Iceland" msg_install_from_a_dos_partition="Install from a DOS partition" msg_install_from_a_floppy_disk_set="Install from a floppy disk set" msg_install_from_a_freebsd_cd_dvd="Install from a FreeBSD CD/DVD" msg_install_from_a_ufs_partition="Install from a UFS partition" msg_install_from_a_usb_drive="Install from a USB drive" msg_install_from_an_ftp_server="Install from an FTP server" msg_install_from_an_ftp_server_thru_firewall="Install from an FTP server through a firewall" msg_install_from_an_ftp_server_thru_proxy="Install from an FTP server through an HTTP proxy" msg_install_from_an_http_server="Install from an HTTP server" msg_install_from_the_existing_filesystem="Install from the existing filesystem" msg_install_over_nfs="Install over NFS" msg_installed="Installed" msg_installed_desc="Leave package as-is, installed" msg_installed_lc="installed" msg_invalid_gateway_ipv4_address_specified="Invalid gateway IPv4 address specified" msg_invalid_hostname_value="Invalid hostname value" msg_invalid_ipv4_address="Invalid IPv4 address" msg_invalid_name_server_ip_address_specified="Invalid name server IP address specified" msg_invalid_netmask_value="Invalid netmask value" msg_invalid_nfs_path_specification="Invalid NFS path specification. Must be of the form:\nhost:/full/pathname/to/FreeBSD/distdir" msg_io_error_while_reading_in_the_package="I/O error while reading in the %s package." -msg_io_or_format_error_on_index_file="I/O or format error on %s file.\nPlease verify media (or path to media) and try again." +msg_io_or_format_error_on_index_file="I/O or format error on INDEX file.\nPlease verify media (or path to media) and try again." msg_ipv4_address="IPv4 Address" msg_ipv4_gateway="IPv4 Gateway" msg_ipv6="IPv6" msg_ipv6_desc="IPv6-related software." msg_ipv6_ready="IPv6 ready" msg_irc_desc="Internet Relay Chat utilities." msg_ireland="Ireland" msg_israel="Israel" msg_italy="Italy" msg_japan="Japan" msg_japanese_desc="Ported software for the Japanese market." msg_java_desc="Java language support." msg_kde_desc="Software for the K Desktop Environment." msg_kld_desc="Kernel loadable modules." msg_korea="Korea" msg_korean_desc="Ported software for the Korean market." msg_lang_desc="Computer languages." msg_latvia="Latvia" msg_length_of_specified_url_is_too_long="Length of specified URL is %u characters. Allowable maximum is %u." msg_linux_desc="Linux programs that can run under binary compatibility." msg_lisp_desc="Software related to the Lisp language." msg_lithuania="Lithuania" msg_loading_of_dependent_package_failed="Loading of dependent package %s failed" msg_located_index_now_reading_package_data_from_it="Located INDEX, now reading package data from it..." msg_logging_in_to_user_at_host="Logging in to %s@%s.." msg_looking_for_keymap_files="Looking for keymap files..." msg_looking_up_host="Looking up host %s" msg_mail_desc="Electronic mail packages and utilities." msg_main_menu="Main Menu" msg_main_site="Main Site" msg_math_desc="Mathematical computation software." msg_mbone_desc="Applications and utilities for the MBONE." msg_media_timeout="Media Timeout" msg_media_type="Media Type" msg_menu_text="If you've already installed FreeBSD, you may use\nthis menu to customize it somewhat to suit your\nparticular configuration. Most importantly, you\ncan use the Packages utility to load extra '3rd\nparty' software not provided in the base\ndistributions." msg_misc_desc="Miscellaneous utilities." msg_missing_ftp_host_or_directory="Missing FTP host or directory specification. FTP media not initialized." msg_multimedia_desc="Multimedia software." msg_must_be_root_to_execute="%s: must be root to execute" msg_must_specify_a_host_name_of_some_sort="Must specify a host name of some sort!" msg_name_server="Name server" msg_net_desc="Networking utilities." msg_net_device_init_failed="Net device init failed." msg_net_im_desc="Instant messaging software." msg_net_mgmt_desc="Network management tools." msg_net_p2p_desc="Peer to peer network applications." msg_netherlands="Netherlands" msg_netmask="Netmask" msg_network_configuration="Network Configuration" msg_network_interface_information_required="Network interface information required" msg_new_zealand="New Zealand" msg_news_desc="USENET News support software." msg_next_page="Next page" msg_nfailed_attempts="%u incorrect password attempts" msg_nfs="NFS" msg_nfs_secure="NFS Secure" msg_nfs_server_talks_only_on_a_secure_port="NFS server talks only on a secure port" msg_nfs_slow="NFS Slow" msg_nfs_tcp="NFS TCP" msg_nfs_version_3="NFS version 3" msg_no="No" msg_no_cd_dvd_devices_found="No CD/DVD devices found! Please check that your system's\nconfiguration is correct and that the CD/DVD drive is of a\nsupported type. For more information, consult the hardware\nguide in the Doc menu." msg_no_description_provided="No description provided" msg_no_dos_primary_partitions_found="No DOS primary partitions found! This installation method is unavailable" msg_no_floppy_devices_found="No floppy devices found! Please check that your system's configuration\nis correct. For more information, consult the hardware guide in the Doc\nmenu." msg_no_gateway_has_been_set="No gateway has been set. You will be unable to access hosts\nnot on your local network" msg_no_network_devices="No network devices available!" msg_no_package_name_passed_in_package_variable="No package name passed in package variable" msg_no_packages_were_selected_for_extraction="No packages were selected for extraction." +msg_no_pkg_database_found="No pkg(8) database found!" msg_no_such_file_or_directory="%s: %s: No such file or directory" msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)" msg_no_username="No username provided!" msg_norway="Norway" msg_not_a_directory="%s: %s: Not a directory" msg_not_found="not found" msg_not_yet_set="not yet set" msg_ok="OK" msg_options="Options" msg_options_editor="Options Editor" msg_other="other" -msg_pkg_delete_failed="Warning: pkg_delete of %s failed.\n Run with debugging for details." msg_package_is_needed_by_other_installed_packages="Warning: Package %s is needed by\n %d other installed package%s." msg_package_not_installed_cannot_delete="Warning: package %s not installed\n No package can be deleted." -msg_package_read_successfully_waiting_for_pkg_add="Package %s read successfully - waiting for pkg_add(1)" msg_package_temp="Package Temp" msg_package_was_added_successfully="Package %s was added successfully" msg_packages="packages" msg_page_of_npages="(Page %s of %s)" msg_palm_desc="Software support for the Palm(tm) series." msg_parallel_desc="Applications dealing with parallelism in computing." msg_pear_desc="Software related to the Pear PHP framework." msg_perl5_desc="Utilities/modules for the PERL5 language." msg_permission_denied="%s: %s: Permission denied" -msg_pkg_add_apparently_did_not_like_the_package="pkg_add(1) apparently did not like the %s package." +msg_pkg_delete_failed="Warning: pkg-delete(8) of %s failed.\n Run with debugging for details." +msg_pkg_install_apparently_did_not_like_the_package="pkg-install(8) apparently did not like the %s package." msg_plan9_desc="Software from the Plan9 operating system." msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again.\n" msg_please_enter_password="Please enter your password for sudo(8):" msg_please_enter_the_address_of_the_http_proxy="Please enter the address of the HTTP proxy in this format:\n hostname:port (the ':port' is optional, default is 3128)" msg_please_enter_the_full_nfs_file_specification="Please enter the full NFS file specification for the remote\nhost and directory containing the FreeBSD distribution files.\nThis should be in the format: hostname:/some/freebsd/dir" msg_please_enter_the_password_for_this_user="Please enter the password for this user:" msg_please_enter_the_username_you_wish_to_login_as="Please enter the username you wish to login as:" msg_please_enter_username_password="Please enter a username and password for sudo(8):" msg_please_insert_floppy_containing="Please insert floppy containing %s in %s" msg_please_insert_floppy_in_drive="Please insert floppy in %s" msg_please_select_a_category_to_display="Please select a category to display." msg_please_select_a_cd_dvd_drive="FreeBSD can be installed directly from a CD/DVD containing a valid\nFreeBSD distribution. If you are seeing this menu it is because\nmore than one CD/DVD drive was found on your system. Please select\none of the following CD/DVD drives as your installation drive." msg_please_select_a_floppy_drive="You have more than one floppy drive. Please choose which drive\nyou would like to use." msg_please_select_a_freebsd_ftp_distribution_site="Please select a FreeBSD FTP distribution site" msg_please_select_a_freebsd_http_distribution_site="Please select a FreeBSD HTTP distribution site" msg_please_select_a_usb_drive="You have more than one USB drive. Please choose which drive\nyou would like to use." msg_please_select_dos_partition="FreeBSD can be installed directly from a DOS partition assuming,\nof course, that you have copied the relevant distributions into\nyour DOS partition before starting this installation. If this is\nnot the case then you should reboot DOS at this time and copy the\ndistributions you wish to install into a \"FREEBSD\" subdirectory\non one of your DOS partitions. Otherwise, please select the DOS\npartition containing the FreeBSD distribution files." msg_please_select_ethernet_device_to_configure="Please select the ethernet or PLIP device to configure." msg_please_select_the_site_closest_to_you_or_other="Please select the site closest to you or \"other\" if you'd like to\nspecify a different choice. Also note that not every site listed here\ncarries more than the base distribution kits. Only Primary sites are\nguaranteed to carry the full range of possible distributions." msg_please_select_ufs_partition="FreeBSD can be installed directly from another FreeBSD partition\nthat is UFS formatted assuming, of course, that you have copied\nthe relevant distributions into said partition before starting\ninstallation." msg_please_specify_a_temporary_directory="Please specify a temporary directory with lots of free space:" msg_please_specify_the_name_of_the_text_editor="Please specify the name of the text editor you wish to use:" msg_please_specify_the_number_of_seconds_to_wait="Please specify the number of seconds to wait for slow media:" msg_please_specify_the_release_you_wish_to_load="Please specify the release you wish to load or\n\"any\" for a generic release install:" msg_please_specify_url_of_a_freebsd_distribution="Please specify the URL of a FreeBSD distribution on a\nremote ftp site. This site must accept either anonymous\nftp or you should have set an ftp username and password\nin the Options screen.\n\nA URL looks like this: ftp:///\nWhere is relative to the anonymous ftp directory or the\nhome directory of the user being logged in as." msg_please_specify_url_of_freebsd_http_distribution="Please specify the URL of a FreeBSD distribution on a\nremote http site.\nA URL looks like this: http:///" msg_poland="Poland" msg_polish_desc="Ported software for the Polish market." msg_ports_mgmt_desc="Utilities for managing ports and packages." msg_portuguese_desc="Ported software for the Portuguese market." msg_previous_page="Previous page" msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors" msg_primary="Primary" msg_print_desc="Utilities for dealing with printing." msg_probing_devices_please_wait_this_can_take_a_while="Probing devices, please wait (this can take a while)..." msg_proceed="Proceed" msg_processing_selection="Processing selection..." msg_python_desc="Software related to the Python language." msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu system" msg_reinstall="Reinstall" msg_reinstall_desc="Mark this package for reinstall" msg_release_name="Release Name" msg_required_package_not_found="Warning: %s is a required package but was not found." msg_rerun_bsdconfig_initial_device_probe="Re-run bsdconfig initial device probe" msg_rescan_devices="Re-scan Devices" msg_reset="RESET!" msg_reset_all_values_to_startup_defaults="Reset all values to startup defaults" msg_reuse_old_ftp_site_selection_values="Re-use old FTP site selection values?" msg_reuse_old_http_site_settings="Re-use old HTTP site settings?" msg_review="Review" msg_review_desc="Review/perform pending actions" msg_review_help="Install, Re-Install, or Un-install selected packages and dependencies" msg_reviewing_selected_packages="Reviewing %u selected packages:" msg_ruby_desc="Software related to the Ruby language." msg_rubygems_desc="Ports of RubyGems packages." msg_russia="Russia" msg_russian_desc="Ported software for the Russian market." msg_scanning_for_dhcp_servers="Scanning for DHCP servers..." msg_scanning_for_ra_servers="Scanning for RA servers..." msg_scheme_desc="Software related to the Scheme language." msg_science_desc="Scientific software." msg_secure_mode_requires_root="Secure-mode requires root-access!" msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!" msg_security_desc="System security software." msg_select="Select" msg_select_a_site_thats_close="Select a site that's close!" msg_selected="selected" msg_server_error_when_requesting_url="Server error when requesting %s, you could try an other server" msg_shells_desc="Various shells (tcsh, bash, etc)." msg_slovak_republic="Slovak Republic" msg_slovenia="Slovenia" msg_sorry_invalid_url="Sorry, %s is an invalid URL!" msg_sorry_package_was_not_found_in_the_index="Sorry, package %s was not found in the INDEX." msg_sorry_try_again="Sorry, try again." msg_south_africa="South Africa" msg_spain="Spain" msg_spanish_desc="Ported software for the Spanish market." msg_specify_some_other_ftp_site="Specify some other ftp site by URL" msg_specify_some_other_http_site="Specify some other http site by URL" msg_sweden="Sweden" msg_switzerland="Switzerland" msg_sysutils_desc="Various system utilities." msg_taiwan="Taiwan" msg_tcl_desc="TCL and packages that depend on it." msg_textproc_desc="Text processing/search utilities." msg_the_current_installation_media_type="The current installation media type." msg_timeout_value_in_seconds_for_slow_media="Timeout value in seconds for slow media." msg_tk_desc="Tk and packages that depend on it." msg_try_dhcp_configuration="Do you want to try DHCP configuration of the interface?" msg_try_ipv6_configuration="Do you want to try IPv6 configuration of the interface?" msg_try_sudo_only_this_once="Try sudo(8) only this once" msg_ufs="UFS" msg_uk="UK" msg_ukraine="Ukraine" msg_ukrainian_desc="Ported software for the Ukrainian market." msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used." msg_unable_to_fetch_package_from_selected_media="Unable to fetch package %s from selected media.\nNo package add will be done." msg_unable_to_get_file_from_selected_media="Unable to get %s file from selected media.\n\nThis may be because the packages collection is not available\non the distribution media you've chosen, most likely an FTP site\nwithout the packages collection mirrored. Please verify that\nyour media, or your path to the media, is correct and try again." msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized." msg_unable_to_initialize_media_type_for_package_extract="Unable to initialize media type for package extract." msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!" msg_unable_to_open="Unable to open %s" +msg_unable_to_pkg_rquery_package_categories="Unable to pkg-rquery(8) package categories!" +msg_unable_to_pkg_rquery_package_dependencies="Unable to pkg-rquery(8) package dependencies!" +msg_unable_to_update_pkg_from_selected_media="Unable to update pkg(8) from selected media." msg_uninstall="Uninstall" msg_uninstall_desc="Mark this package for deletion" -msg_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg_delete(1)" +msg_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg-delete(8)" msg_unknown="unknown" msg_unknown_user="Unknown user: %s" msg_url_was_not_found="%s was not found, maybe directory or release-version are wrong?" msg_usa="USA" msg_usage="Usage" msg_usb="USB" msg_use_defaults="Use Defaults" msg_use_nfs_version_3="Use NFS version 3" msg_use_tcp_protocol_for_nfs="Use TCP protocol for NFS" msg_user_disallowed="User disallowed: %s" msg_user_is_using_a_slow_pc_or_ethernet_card="User is using a slow PC or Ethernet card" msg_username_and_password_to_use="Username and password to use instead of anonymous" msg_using_interface="Using interface %s" msg_using_usb_device="Using USB device: %s" msg_vietnamese_desc="Ported software for the Vietnamese market." msg_view_set_various_media_options="View/Set various media options" msg_what_would_you_like_to_do_with="What would you like to do with %s?" msg_which_release_to_attempt_to_load="Which release to attempt to load from installation media" msg_which_text_editor_to_use="Which text editor to use during installation" msg_windowmaker_desc="Ports to support the WindowMaker window manager." msg_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?" msg_www_desc="Web utilities (browsers, HTTP servers, etc)." msg_x11_clocks_desc="X Window System based clocks." msg_x11_desc="X Window System based utilities." msg_x11_drivers_desc="X Window System drivers." msg_x11_fm_desc="X Window System based file managers." msg_x11_fonts_desc="X Window System fonts and font utilties." msg_x11_servers_desc="X Window System servers." msg_x11_themes_desc="X Window System themes." msg_x11_toolkits_desc="X Window System based development toolkits." msg_x11_wm_desc="X Window System window managers." msg_xfce_desc="Software related to the Xfce Desktop Environment." msg_yes="Yes" msg_yes_to_all="Yes to All" msg_you_are_not_root_but="You are not root but %s can use sudo(8).\nWhat would you like to do?" msg_you_may_remove_the_floppy="You may remove the floppy from %s" msg_youve_already_done_the_network_configuration="You've already done the network configuration once,\nwould you like to skip over it now?" msg_zope_desc="Software related to the Zope platform." tcplayout_extras_help="Any interface-specific options to ifconfig you would like to add" tcplayout_extras_help_for_plip="For PLIP configuration, you must enter the peer's IP address here." tcplayout_gateway_help="IPv4 address of host forwarding packets to non-local destinations" tcplayout_hostname_help="Your fully-qualified hostname, e.g. foo.example.com" tcplayout_ipaddr_help="The IPv4 address to be used for this interface" tcplayout_nameserver_help="IPv4 or IPv6 address of your local DNS server" tcplayout_netmask_help="The netmask for this interface, e.g. 255.255.255.0 for a class C network" Index: stable/9/usr.sbin/bsdconfig/share/common.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/share/common.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/share/common.subr (revision 267683) @@ -1,987 +1,994 @@ if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 # # Copyright (c) 2012 Ron McDowell # Copyright (c) 2012-2014 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ CONFIGURATION # # Default file descriptors to link to stdout/stderr for passthru allowing # redirection within a sub-shell to bypass directly to the terminal. # : ${TERMINAL_STDOUT_PASSTHRU:=3}} : ${TERMINAL_STDERR_PASSTHRU:=4}} ############################################################ GLOBALS # # Program name # pgm="${0##*/}" # # Program arguments # ARGC="$#" ARGV="$@" # # Global exit status variables # SUCCESS=0 FAILURE=1 # # Operating environment details # export UNAME_S="$( uname -s )" # Operating System (i.e. FreeBSD) export UNAME_P="$( uname -p )" # Processor Architecture (i.e. i386) +export UNAME_M="$( uname -m )" # Machine platform (i.e. i386) export UNAME_R="$( uname -r )" # Release Level (i.e. X.Y-RELEASE) +if [ ! "${PKG_ABI+set}" ]; then + export PKG_ABI="$( + ASSUME_ALWAYS_YES=1 pkg -vv 2> /dev/null | + awk '$1=="ABI"{print $3;exit}' + )" +fi # # Default behavior is to call f_debug_init() automatically when loaded. # : ${DEBUG_SELF_INITIALIZE=1} # # Default behavior of f_debug_init() is to truncate $debugFile (set to NULL to # disable truncating the debug file when initializing). To get child processes # to append to the same log file, export this variarable (with a NULL value) # and also export debugFile with the desired value. # : ${DEBUG_INITIALIZE_FILE=1} # # Define standard optstring arguments that should be supported by all programs # using this include (unless DEBUG_SELF_INITIALIZE is set to NULL to prevent # f_debug_init() from autamatically processing "$@" for the below arguments): # # d Sets $debug to 1 # D: Sets $debugFile to $OPTARG # GETOPTS_STDARGS="dD:" # # The getopts builtin will return 1 either when the end of "$@" or the first # invalid flag is reached. This makes it impossible to determine if you've # processed all the arguments or simply have hit an invalid flag. In the cases # where we want to tolerate invalid flags (f_debug_init() for example), the # following variable can be appended to your optstring argument to getopts, # preventing it from prematurely returning 1 before the end of the arguments. # # NOTE: This assumes that all unknown flags are argument-less. # GETOPTS_ALLFLAGS="abcdefghijklmnopqrstuvwxyz" GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}ABCDEFGHIJKLMNOPQRSTUVWXYZ" GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}0123456789" # # When we get included, f_debug_init() will fire (unless $DEBUG_SELF_INITIALIZE # is set to disable automatic initialization) and process "$@" for a few global # options such as `-d' and/or `-D file'. However, if your program takes custom # flags that take arguments, this automatic processing may fail unexpectedly. # # The solution to this problem is to pre-define (before including this file) # the following variable (which defaults to NULL) to indicate that there are # extra flags that should be considered when performing automatic processing of # globally persistent flags. # : ${GETOPTS_EXTRA:=} ############################################################ FUNCTIONS # f_dprintf $format [$arguments ...] # # Sensible debug function. Override in ~/.bsdconfigrc if desired. # See /usr/share/examples/bsdconfig/bsdconfigrc for example. # # If $debug is set and non-NULL, prints DEBUG info using printf(1) syntax: # + To $debugFile, if set and non-NULL # + To standard output if $debugFile is either NULL or unset # + To both if $debugFile begins with a single plus-sign (`+') # f_dprintf() { [ "$debug" ] || return $SUCCESS local fmt="$1"; shift case "$debugFile" in ""|+*) printf "DEBUG: $fmt${fmt:+\n}" "$@" >&${TERMINAL_STDOUT_PASSTHRU:-1} esac [ "${debugFile#+}" ] && printf "DEBUG: $fmt${fmt:+\n}" "$@" >> "${debugFile#+}" return $SUCCESS } # f_debug_init # # Initialize debugging. Truncates $debugFile to zero bytes if set. # f_debug_init() { # # Process stored command-line arguments # set -- $ARGV local OPTIND OPTARG flag f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \ "$ARGV" "$GETOPTS_STDARGS" while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \ > /dev/null; do case "$flag" in d) debug=1 ;; D) debugFile="$OPTARG" ;; esac done shift $(( $OPTIND - 1 )) f_dprintf "f_debug_init: debug=[%s] debugFile=[%s]" \ "$debug" "$debugFile" # # Automagically enable debugging if debugFile is set (and non-NULL) # [ "$debugFile" ] && { [ "${debug+set}" ] || debug=1; } # # Make debugging persistant if set # [ "$debug" ] && export debug [ "$debugFile" ] && export debugFile # # Truncate debug file unless requested otherwise. Note that we will # trim a leading plus (`+') from the value of debugFile to support # persistant meaning that f_dprintf() should print both to standard # output and $debugFile (minus the leading plus, of course). # local _debug_file="${debugFile#+}" if [ "$_debug_file" -a "$DEBUG_INITIALIZE_FILE" ]; then if ( umask 022 && :> "$_debug_file" ); then f_dprintf "Successfully initialized debugFile \`%s'" \ "$_debug_file" f_isset debug || debug=1 # turn debugging on if not set else unset debugFile f_dprintf "Unable to initialize debugFile \`%s'" \ "$_debug_file" fi fi } # f_err $format [$arguments ...] # # Print a message to stderr (fd=2). # f_err() { printf "$@" >&2 } # f_quietly $command [$arguments ...] # # Run a command quietly (quell any output to stdout or stderr) # f_quietly() { "$@" > /dev/null 2>&1 } # f_have $anything ... # # A wrapper to the `type' built-in. Returns true if argument is a valid shell # built-in, keyword, or externally-tracked binary, otherwise false. # f_have() { f_quietly type "$@" } # f_getvar $var_to_get [$var_to_set] # # Utility function designed to go along with the already-builtin setvar. # Allows clean variable name indirection without forking or sub-shells. # # Returns error status if the requested variable ($var_to_get) is not set. # # If $var_to_set is missing or NULL, the value of $var_to_get is printed to # standard output for capturing in a sub-shell (which is less-recommended # because of performance degredation; for example, when called in a loop). # f_getvar() { local __var_to_get="$1" __var_to_set="$2" [ "$__var_to_set" ] || local value eval [ \"\${$__var_to_get+set}\" ] local __retval=$? eval ${__var_to_set:-value}=\"\${$__var_to_get}\" eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \ \"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval [ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; } return $__retval } # f_isset $var # # Check if variable $var is set. Returns success if variable is set, otherwise # returns failure. # f_isset() { eval [ \"\${${1%%[$IFS]*}+set}\" ] } # f_die [$status [$format [$arguments ...]]] # # Abruptly terminate due to an error optionally displaying a message in a # dialog box using printf(1) syntax. # f_die() { local status=$FAILURE # If there is at least one argument, take it as the status if [ $# -gt 0 ]; then status=$1 shift 1 # status fi # If there are still arguments left, pass them to f_show_msg [ $# -gt 0 ] && f_show_msg "$@" # Optionally call f_clean_up() function if it exists f_have f_clean_up && f_clean_up exit $status } # f_interrupt # # Interrupt handler. # f_interrupt() { exec 2>&1 # fix sh(1) bug where stderr gets lost within async-trap f_die } # f_show_info $format [$arguments ...] # # Display a message in a dialog infobox using printf(1) syntax. # f_show_info() { local msg msg=$( printf "$@" ) # # Use f_dialog_infobox from dialog.subr if possible, otherwise fall # back to dialog(1) (without options, making it obvious when using # un-aided system dialog). # if f_have f_dialog_info; then f_dialog_info "$msg" else dialog --infobox "$msg" 0 0 fi } # f_show_msg $format [$arguments ...] # # Display a message in a dialog box using printf(1) syntax. # f_show_msg() { local msg msg=$( printf "$@" ) # # Use f_dialog_msgbox from dialog.subr if possible, otherwise fall # back to dialog(1) (without options, making it obvious when using # un-aided system dialog). # if f_have f_dialog_msgbox; then f_dialog_msgbox "$msg" else dialog --msgbox "$msg" 0 0 fi } # f_show_err $format [$arguments ...] # # Display a message in a dialog box with ``Error'' i18n title (overridden by # setting msg_error) using printf(1) syntax. # f_show_err() { local msg msg=$( printf "$@" ) : ${msg:=${msg_an_unknown_error_occurred:-An unknown error occurred}} if [ "$_DIALOG_SUBR" ]; then f_dialog_title "${msg_error:-Error}" f_dialog_msgbox "$msg" f_dialog_title_restore else dialog --title "${msg_error:-Error}" --msgbox "$msg" 0 0 fi return $SUCCESS } # f_yesno $format [$arguments ...] # # Display a message in a dialog yes/no box using printf(1) syntax. # f_yesno() { local msg msg=$( printf "$@" ) # # Use f_dialog_yesno from dialog.subr if possible, otherwise fall # back to dialog(1) (without options, making it obvious when using # un-aided system dialog). # if f_have f_dialog_yesno; then f_dialog_yesno "$msg" else dialog --yesno "$msg" 0 0 fi } # f_noyes $format [$arguments ...] # # Display a message in a dialog yes/no box using printf(1) syntax. # NOTE: THis is just like the f_yesno function except "No" is default. # f_noyes() { local msg msg=$( printf "$@" ) # # Use f_dialog_noyes from dialog.subr if possible, otherwise fall # back to dialog(1) (without options, making it obvious when using # un-aided system dialog). # if f_have f_dialog_noyes; then f_dialog_noyes "$msg" else dialog --defaultno --yesno "$msg" 0 0 fi } # f_show_help $file # # Display a language help-file. Automatically takes $LANG and $LC_ALL into # consideration when displaying $file (suffix ".$LC_ALL" or ".$LANG" will # automatically be added prior to loading the language help-file). # # If a language has been requested by setting either $LANG or $LC_ALL in the # environment and the language-specific help-file does not exist we will fall # back to $file without-suffix. # # If the language help-file does not exist, an error is displayed instead. # f_show_help() { local file="$1" local lang="${LANG:-$LC_ALL}" [ -f "$file.$lang" ] && file="$file.$lang" # # Use f_dialog_textbox from dialog.subr if possible, otherwise fall # back to dialog(1) (without options, making it obvious when using # un-aided system dialog). # if f_have f_dialog_textbox; then f_dialog_textbox "$file" else dialog --msgbox "$( cat "$file" 2>&1 )" 0 0 fi } # f_include $file # # Include a shell subroutine file. # # If the subroutine file exists but returns error status during loading, exit # is called and execution is prematurely terminated with the same error status. # f_include() { local file="$1" f_dprintf "f_include: file=[%s]" "$file" . "$file" || exit $? } # f_include_lang $file # # Include a language file. Automatically takes $LANG and $LC_ALL into # consideration when including $file (suffix ".$LC_ALL" or ".$LANG" will # automatically by added prior to loading the language file). # # No error is produced if (a) a language has been requested (by setting either # $LANG or $LC_ALL in the environment) and (b) the language file does not # exist -- in which case we will fall back to loading $file without-suffix. # # If the language file exists but returns error status during loading, exit # is called and execution is prematurely terminated with the same error status. # f_include_lang() { local file="$1" local lang="${LANG:-$LC_ALL}" f_dprintf "f_include_lang: file=[%s] lang=[%s]" "$file" "$lang" if [ -f "$file.$lang" ]; then . "$file.$lang" || exit $? else . "$file" || exit $? fi } # f_usage $file [$key1 $value1 ...] # # Display USAGE file with optional pre-processor macro definitions. The first # argument is the template file containing the usage text to be displayed. If # $LANG or $LC_ALL (in order of preference, respectively) is set, ".encoding" # will automatically be appended as a suffix to the provided $file pathname. # # When processing $file, output begins at the first line containing that is # (a) not a comment, (b) not empty, and (c) is not pure-whitespace. All lines # appearing after this first-line are output, including (a) comments (b) empty # lines, and (c) lines that are purely whitespace-only. # # If additional arguments appear after $file, substitutions are made while # printing the contents of the USAGE file. The pre-processor macro syntax is in # the style of autoconf(1), for example: # # f_usage $file "FOO" "BAR" # # Will cause instances of "@FOO@" appearing in $file to be replaced with the # text "BAR" before being printed to the screen. # # This function is a two-parter. Below is the awk(1) portion of the function, # afterward is the sh(1) function which utilizes the below awk script. # f_usage_awk=' BEGIN { found = 0 } { if ( !found && $0 ~ /^[[:space:]]*($|#)/ ) next found = 1 print } ' f_usage() { local file="$1" local lang="${LANG:-$LC_ALL}" f_dprintf "f_usage: file=[%s] lang=[%s]" "$file" "$lang" shift 1 # file local usage if [ -f "$file.$lang" ]; then usage=$( awk "$f_usage_awk" "$file.$lang" ) || exit $FAILURE else usage=$( awk "$f_usage_awk" "$file" ) || exit $FAILURE fi while [ $# -gt 0 ]; do local key="$1" export value="$2" usage=$( echo "$usage" | awk \ "{ gsub(/@$key@/, ENVIRON[\"value\"]); print }" ) shift 2 done f_err "%s\n" "$usage" exit $FAILURE } # f_index_file $keyword [$var_to_set] # # Process all INDEX files known to bsdconfig and return the path to first file # containing a menu_selection line with a keyword portion matching $keyword. # # If $LANG or $LC_ALL (in order of preference, respectively) is set, # "INDEX.encoding" files will be searched first. # # If no file is found, error status is returned along with the NULL string. # # If $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # # This function is a two-parter. Below is the awk(1) portion of the function, # afterward is the sh(1) function which utilizes the below awk script. # f_index_file_awk=' # Variables that should be defined on the invocation line: # -v keyword="keyword" BEGIN { found = 0 } ( $0 ~ "^menu_selection=\"" keyword "\\|" ) { print FILENAME found++ exit } END { exit ! found } ' f_index_file() { local __keyword="$1" __var_to_set="$2" local __lang="${LANG:-$LC_ALL}" local __indexes="$BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX" f_dprintf "f_index_file: keyword=[%s] lang=[%s]" "$__keyword" "$__lang" if [ "$__lang" ]; then if [ "$__var_to_set" ]; then eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \ "$f_index_file_awk" $__indexes.$__lang )"' && return $SUCCESS else awk -v keyword="$__keyword" "$f_index_file_awk" \ $__indexes.$__lang && return $SUCCESS fi # No match, fall-thru to non-i18n sources fi if [ "$__var_to_set" ]; then eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \ "$f_index_file_awk" $__indexes )"' && return $SUCCESS else awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes && return $SUCCESS fi # No match? Fall-thru to `local' libexec sources (add-on modules) [ "$BSDCFG_LOCAL_LIBE" ] || return $FAILURE __indexes="$BSDCFG_LOCAL_LIBE/*/INDEX" if [ "$__lang" ]; then if [ "$__var_to_set" ]; then eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \ "$f_index_file_awk" $__indexes.$__lang )"' && return $SUCCESS else awk -v keyword="$__keyword" "$f_index_file_awk" \ $__indexes.$__lang && return $SUCCESS fi # No match, fall-thru to non-i18n sources fi if [ "$__var_to_set" ]; then eval "$__var_to_set"='$( awk -v keyword="$__keyword" \ "$f_index_file_awk" $__indexes )"' else awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes fi } # f_index_menusel_keyword $indexfile $pgm [$var_to_set] # # Process $indexfile and return only the keyword portion of the menu_selection # line with a command portion matching $pgm. # # This function is for internationalization (i18n) mapping of the on-disk # scriptname ($pgm) into the localized language (given language-specific # $indexfile). If $LANG or $LC_ALL (in orderder of preference, respectively) is # set, ".encoding" will automatically be appended as a suffix to the provided # $indexfile pathname. # # If, within $indexfile, multiple $menu_selection values map to $pgm, only the # first one will be returned. If no mapping can be made, the NULL string is # returned. # # If $indexfile does not exist, error status is returned with NULL. # # If $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # # This function is a two-parter. Below is the awk(1) portion of the function, # afterward is the sh(1) function which utilizes the below awk script. # f_index_menusel_keyword_awk=' # Variables that should be defined on the invocation line: # -v pgm="program_name" # BEGIN { prefix = "menu_selection=\"" plen = length(prefix) found = 0 } { if (!match($0, "^" prefix ".*\\|.*\"")) next keyword = command = substr($0, plen + 1, RLENGTH - plen - 1) sub(/^.*\|/, "", command) sub(/\|.*$/, "", keyword) if ( command == pgm ) { print keyword found++ exit } } END { exit ! found } ' f_index_menusel_keyword() { local __indexfile="$1" __pgm="$2" __var_to_set="$3" local __lang="${LANG:-$LC_ALL}" __file="$__indexfile" [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang" f_dprintf "f_index_menusel_keyword: index=[%s] pgm=[%s] lang=[%s]" \ "$__file" "$__pgm" "$__lang" if [ "$__var_to_set" ]; then setvar "$__var_to_set" "$( awk \ -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file" )" else awk -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file" fi } # f_index_menusel_command $indexfile $keyword [$var_to_set] # # Process $indexfile and return only the command portion of the menu_selection # line with a keyword portion matching $keyword. # # This function is for mapping [possibly international] keywords into the # command to be executed. If $LANG or $LC_ALL (order of preference) is set, # ".encoding" will automatically be appended as a suffix to the provided # $indexfile pathname. # # If, within $indexfile, multiple $menu_selection values map to $keyword, only # the first one will be returned. If no mapping can be made, the NULL string is # returned. # # If $indexfile doesn't exist, error status is returned with NULL. # # If $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # # This function is a two-parter. Below is the awk(1) portion of the function, # afterward is the sh(1) function which utilizes the below awk script. # f_index_menusel_command_awk=' # Variables that should be defined on the invocation line: # -v key="keyword" # BEGIN { prefix = "menu_selection=\"" plen = length(prefix) found = 0 } { if (!match($0, "^" prefix ".*\\|.*\"")) next keyword = command = substr($0, plen + 1, RLENGTH - plen - 1) sub(/^.*\|/, "", command) sub(/\|.*$/, "", keyword) if ( keyword == key ) { print command found++ exit } } END { exit ! found } ' f_index_menusel_command() { local __indexfile="$1" __keyword="$2" __var_to_set="$3" __command local __lang="${LANG:-$LC_ALL}" __file="$__indexfile" [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang" f_dprintf "f_index_menusel_command: index=[%s] key=[%s] lang=[%s]" \ "$__file" "$__keyword" "$__lang" [ -f "$__file" ] || return $FAILURE __command=$( awk -v key="$__keyword" \ "$f_index_menusel_command_awk" "$__file" ) || return $FAILURE # # If the command pathname is not fully qualified fix-up/force to be # relative to the $indexfile directory. # case "$__command" in /*) : already fully qualified ;; *) local __indexdir="${__indexfile%/*}" [ "$__indexdir" != "$__indexfile" ] || __indexdir="." __command="$__indexdir/$__command" esac if [ "$__var_to_set" ]; then setvar "$__var_to_set" "$__command" else echo "$__command" fi } # f_running_as_init # # Returns true if running as init(1). # f_running_as_init() { # # When a custom init(8) performs an exec(3) to invoke a shell script, # PID 1 becomes sh(1) and $PPID is set to 1 in the executed script. # [ ${PPID:-0} -eq 1 ] # Return status } # f_mounted $local_directory # f_mounted -b $device # # Return success if a filesystem is mounted on a particular directory. If `-b' # is present, instead check that the block device (or a partition thereof) is # mounted. # f_mounted() { local OPTIND OPTARG flag use_device= while getopts b flag; do case "$flag" in b) use_device=1 ;; esac done shift $(( $OPTIND - 1 )) if [ "$use_device" ]; then local device="$1" mount | grep -Eq \ "^$device([[:space:]]|p[0-9]|s[0-9]|\.nop|\.eli)" else [ -d "$dir" ] || return $FAILURE mount | grep -Eq " on $dir \([^)]+\)$" fi # Return status is that of last grep(1) } # f_eval_catch [-de] [-k $var_to_set] $funcname $utility \ # $format [$arguments ...] # # Silently evaluate a command in a sub-shell and test for error. If debugging # is enabled a copy of the command and its output is sent to debug (either # stdout or file depending on environment). If an error occurs, output of the # command is displayed in a dialog(1) msgbox using the [above] f_show_err() # function (unless optional `-d' flag is given, then no dialog). # # The $funcname argument is sent to debugging while the $utility argument is # used in the title of the dialog box. The command that is executed as well as # sent to debugging with $funcname is the product of the printf(1) syntax # produced by $format with optional $arguments. # # The following options are supported: # # -d Do not use dialog(1). # -e Produce error text from failed command on stderr. # -k var Save output from the command in var. # # Example 1: # # debug=1 # f_eval_catch myfunc echo 'echo "%s"' "Hello, World!" # # Produces the following debug output: # # DEBUG: myfunc: echo "Hello, World!" # DEBUG: myfunc: retval=0 # Hello, World! # # Example 2: # # debug=1 # f_eval_catch -k contents myfunc cat 'cat "%s"' /some/file # # dialog(1) Error ``cat: /some/file: No such file or directory'' # # contents=[cat: /some/file: No such file or directory] # # Produces the following debug output: # # DEBUG: myfunc: cat "/some/file" # DEBUG: myfunc: retval=1 # cat: /some/file: No such file or directory # # Example 3: # # debug=1 # echo 123 | f_eval_catch myfunc rev rev # # Produces the following debug output: # # DEBUG: myfunc: rev # DEBUG: myfunc: retval=0 # 321 # # Example 4: # # debug=1 # f_eval_catch myfunc true true # # Produces the following debug output: # # DEBUG: myfunc: true # DEBUG: myfunc: retval=0 # # Example 5: # # f_eval_catch -de myfunc ls 'ls "%s"' /some/dir # # Output on stderr ``ls: /some/dir: No such file or directory'' # # Example 6: # # f_eval_catch -dek contents myfunc ls 'ls "%s"' /etc # # Output from `ls' sent to stderr and also saved in $contents # f_eval_catch() { local __no_dialog= __show_err= __var_to_set= # # Process local function arguments # local OPTIND OPTARG __flag while getopts "dek:" __flag > /dev/null; do case "$__flag" in d) __no_dialog=1 ;; e) __show_err=1 ;; k) __var_to_set="$OPTARG" ;; esac done shift $(( $OPTIND - 1 )) local __funcname="$1" __utility="$2"; shift 2 local __cmd __output __retval __cmd=$( printf -- "$@" ) f_dprintf "%s: %s" "$__funcname" "$__cmd" # Log command *before* eval __output=$( exec 2>&1; eval "$__cmd" ) __retval=$? if [ "$__output" ]; then [ "$__show_err" ] && echo "$__output" >&2 f_dprintf "%s: retval=%i \n%s" "$__funcname" \ $__retval "$__output" else f_dprintf "%s: retval=%i " "$__funcname" $__retval fi ! [ "$__no_dialog" -o "$nonInteractive" -o $__retval -eq $SUCCESS ] && msg_error="${msg_error:-Error}${__utility:+: $__utility}" \ f_show_err "%s" "$__output" # NB: f_show_err will handle NULL output appropriately [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output" return $__retval } # f_count $var_to_set arguments ... # # Sets $var_to_set to the number of arguments minus one (the effective number # of arguments following $var_to_set). # # Example: # f_count count dog house # count=[2] # f_count() { setvar "$1" $(( $# - 1 )) } # f_count_ifs $var_to_set string ... # # Sets $var_to_set to the number of words (split by the internal field # separator, IFS) following $var_to_set. # # Example 1: # # string="word1 word2 word3" # f_count_ifs count "$string" # count=[3] # f_count_ifs count $string # count=[3] # # Example 2: # # IFS=. f_count_ifs count www.freebsd.org # count=[3] # # NB: Make sure to use double-quotes if you are using a custom value for IFS # and you don't want the current value to effect the result. See example 3. # # Example 3: # # string="a-b c-d" # IFS=- f_count_ifs count "$string" # count=[3] # IFS=- f_count_ifs count $string # count=[4] # f_count_ifs() { local __var_to_set="$1" shift 1 set -- $* setvar "$__var_to_set" $# } ############################################################ MAIN # # Trap signals so we can recover gracefully # trap 'f_interrupt' SIGINT trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \ SIGFPE SIGTRAP SIGABRT SIGSEGV trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM # # Clone terminal stdout/stderr so we can redirect to it from within sub-shells # eval exec $TERMINAL_STDOUT_PASSTHRU\>\&1 eval exec $TERMINAL_STDERR_PASSTHRU\>\&2 # # Self-initialize unless requested otherwise # f_dprintf "%s: DEBUG_SELF_INITIALIZE=[%s]" \ dialog.subr "$DEBUG_SELF_INITIALIZE" case "$DEBUG_SELF_INITIALIZE" in ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; *) f_debug_init esac # # Log our operating environment for debugging purposes # f_dprintf "UNAME_S=[%s] UNAME_P=[%s] UNAME_R=[%s]" \ "$UNAME_S" "$UNAME_P" "$UNAME_R" f_dprintf "%s: Successfully loaded." common.subr fi # ! $_COMMON_SUBR Index: stable/9/usr.sbin/bsdconfig/share/media/http.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/share/media/http.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/share/media/http.subr (revision 267683) @@ -1,659 +1,691 @@ if [ ! "$_MEDIA_HTTP_SUBR" ]; then _MEDIA_HTTP_SUBR=1 # # Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." media/http.subr f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/media/common.subr f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/strings.subr f_include $BSDCFG_SHARE/struct.subr f_include $BSDCFG_SHARE/variable.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" f_include_lang $BSDCFG_LIBE/include/messages.subr ############################################################ GLOBALS HTTP_SKIP_RESOLV= URL_MAX=261261 # NOTE: This is according to actual fetch(1) test-results. We actually # use nc(1) to retrieve files, but it's still a good idea to keep the # URLs short enough that fetch(1) won't complain. HTTP_DIRS=" . releases/$UNAME_P snapshots/$UNAME_P pub/FreeBSD pub/FreeBSD/releases/$UNAME_P pub/FreeBSD/snapshots/$UNAME_P pub/FreeBSD-Archive/old-releases/$UNAME_P " # END-QUOTE ############################################################ FUNCTIONS # f_dialog_menu_media_http # # Prompt the user to select from a range of ``built-in'' HTTP servers or # specify their own. If the user makes a choice and doesn't cancel or press # Esc, stores the user's choice in VAR_FTP_PATH (see variable.subr) and returns # success. # f_dialog_menu_media_http() { f_dialog_title "$msg_please_select_a_freebsd_http_distribution_site" local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" f_dialog_title_restore local prompt="$msg_please_select_the_site_closest_to_you_or_other" local menu_list=" - '$msg_main_site' 'ftp.freebsd.org' + 'dist $msg_main_site' 'ftp.freebsd.org' + 'pkg $msg_main_site' 'pkg.freebsd.org' 'URL' '$msg_specify_some_other_http_site' " # END-QUOTE local hline="$msg_select_a_site_thats_close" local height width rows eval f_dialog_menu_size height width rows \ \"\$title\" \ \"\$btitle\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list local mtag mtag=$( eval $DIALOG \ --title \"\$title\" \ --backtitle \"\$btitle\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) || return $DIALOG_CANCEL f_dialog_data_sanitize mtag case "$mtag" in URL) setvar $VAR_HTTP_PATH "other" ;; *) local value value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list ) setvar $VAR_HTTP_PATH "http://$value" esac return $DIALOG_OK } # f_media_set_http # # Return success if we both found and set the media type to be an HTTP server. # # Variables from variable.subr that can be used to script user input: # # VAR_HTTP_PATH # URL containing host and optionally a target path to the release # repository on the HTTP server. Valid examples include: # http://myhost # http://somename:80/pub/ # http://192.168.2.3/pub/ # http://[::1]:8000/ # The default port if not specified is 80. # VAR_NAMESERVER [Optional] # If set, overrides resolv.conf(5) and sets the nameserver that # is used to convert names into addresses (when a name converts # into multiple addresses, the first address to successfully # connect is used). # # Meanwhile, the following variables from variable.subr are set after # successful execution: # # VAR_HTTP_HOST # The HTTP host to connect to, parsed from VAR_HTTP_PATH. In the # example case of IPv6 where VAR_HTTP_PATH is "http://[::1]" this # variable will be set to "::1" (the outer brackets are removed). # VAR_HTTP_PORT # The TCP port to connect to, parsed from VAR_HTTP_PATH. Usually # 80 unless VAR_HTTP_PATH was one of the following forms: # http://hostname:OTHER_PORT # http://hostname:OTHER_PORT/* # http://ip:OTHER_PORT # http://ip:OTHER_PORT/* # http://[ip6]:OTHER_PORT # http://[ip6]:OTHER_PORT/* # VAR_HTTP_DIR # If VAR_HTTP_PATH contained a directory element (e.g., # "http://localhost/pub") this variable contains only the # directory element (e.g., "/pub"). # f_media_set_http() { f_media_close local url f_getvar $VAR_HTTP_PATH url # If we've been through here before ... if f_struct device_network && [ "${url#$msg_other}" ]; then f_dialog_yesno "$msg_reuse_old_http_site_settings" || url= fi if [ ! "$url" ]; then f_dialog_menu_media_http || return $FAILURE f_getvar $VAR_HTTP_PATH url fi [ "$url" ] || return $FAILURE case "$url" in other) setvar $VAR_HTTP_PATH "http://" f_variable_get_value $VAR_HTTP_PATH \ "$msg_please_specify_url_of_freebsd_http_distribution" f_getvar $VAR_HTTP_PATH url if [ ! "${url#http://}" ]; then unset $VAR_HTTP_PATH return $FAILURE fi if [ ${#url} -gt ${URL_MAX:-261261} ]; then f_show_msg "$msg_length_of_specified_url_is_too_long" \ ${#url} ${URL_MAX:-261261} unset $VAR_HTTP_PATH return $FAILURE fi case "$url" in http://*) : valid URL ;; *) f_show_msg "$msg_sorry_invalid_url" "$url" unset $VAR_HTTP_PATH return $FAILURE esac esac case "$url" in http://*) : valid URL ;; *) f_show_msg "$msg_sorry_invalid_url" "$url" unset $VAR_HTTP_PATH return $FAILURE esac # Set the name of the HTTP device to the URL f_struct_new DEVICE device_http device_http set name "$url" if ! f_struct device_network || ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration" then f_struct device_network && f_device_shutdown device_network if ! f_device_select_tcp; then unset $VAR_HTTP_PATH return $FAILURE fi local dev if f_getvar $VAR_NETWORK_DEVICE if f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev f_struct_copy "$dev" device_network fi if ! f_device_init device_network; then f_dprintf "f_media_set_http: %s" "$msg_net_device_init_failed" unset $VAR_HTTP_PATH return $FAILURE fi local hostname="${url#*://}" port=80 dir=/ case "$hostname" in # # The order in-which the below individual cases appear is important! # "["*"]":*/*) # IPv6 address with port and directory f_dprintf "Looks like an IPv6 addr with port/dir: %s" \ "$hostname" hostname="${hostname#\[}" port="${hostname#*\]:}" port="${port%%[!0-9]*}" dir="/${hostname#*/}" hostname="${hostname%%\]:*}" ;; "["*"]":*) # IPv6 address with port f_dprintf "Looks like an IPv6 addr with port: %s" "$hostname" hostname="${hostname#\[}" port="${hostname#*\]:}" port="${port%%[!0-9]*}" hostname="${hostname%%\]:*}" ;; "["*"]"/*) # IPv6 address with directory f_dprintf "Looks like an IPv6 addr with dir: %s" "$hostname" hostname="${hostname#\[}" dir="/${hostname#*/}" hostname="${hostname%%\]*}" ;; "["*"]") # IPv6 address f_dprintf "Looks like an IPv6 addr: %s" "$hostname" hostname="${hostname#\[}" hostname="${hostname%\]}" ;; # # ^^^ IPv6 above / DNS Name or IPv4 below vvv # *:*/*) # DNS name or IPv4 address with port and directory f_dprintf "Looks like a %s with port/dir: %s" \ "DNS name or IPv4 addr" "$hostname" port="${hostname#*:}" port="${port%%[!0-9]*}" dir="/${hostname#*/}" hostname="${hostname%%:*}" ;; *:*) # DNS name or IPv4 address with port f_dprintf "Looks like a DNS name or IPv4 addr with port: %s" \ "$hostname" port="${hostname#*:}" hostname="${hostname%%:*}" ;; */*) # DNS name or IPv4 address with directory f_dprintf "Looks like a DNS name or IPv4 addr with dir: %s" \ "$hostname" dir="/${hostname#*/}" hostname="${hostname%%/*}" ;; *) # DNS name or IPv4 address f_dprintf "Looks like a DNS name or IPv4 addr: %s" "$hostname" : leave hostname as-is esac f_dprintf "hostname = \`%s'" "$hostname" f_dprintf "dir = \`%s'" "$dir" f_dprintf "port \# = \`%d'" "$port" local ns f_getvar $VAR_NAMESERVER ns [ "$ns" ] || f_resolv_conf_nameservers ns if [ "$ns" -a ! "$HTTP_SKIP_RESOLV" ] && ! { f_validate_ipaddr "$hostname" || f_validate_ipaddr6 "$hostname" }; then f_show_info "$msg_looking_up_host" "$hostname" f_dprintf "%s: Looking up hostname, %s, using host(1)" \ "f_media_set_http" "$hostname" if ! f_quietly f_host_lookup "$hostname"; then f_show_msg "$msg_cannot_resolve_hostname" "$hostname" f_struct device_network && f_device_shutdown device_network f_struct_free device_network unset $VAR_HTTP_PATH return $FAILURE fi f_dprintf "Found DNS entry for %s successfully." "$hostname" fi setvar $VAR_HTTP_HOST "$hostname" setvar $VAR_HTTP_PORT "$port" setvar $VAR_HTTP_DIR "$dir" device_http set type $DEVICE_TYPE_HTTP device_http set init f_media_init_http device_http set get f_media_get_http - device_http set shutdown : + device_http set shutdown f_media_shutdown_http device_http set private device_network f_struct_copy device_http device_media f_struct_free device_http return $SUCCESS } # f_http_check_access [$connect_only] # # Return success if able list a remote HTTP directory. If $connect_only is # present and non-null, then returns success if a connection can be made. # Variables from variable.subr that can be used to script user input: # # VAR_HTTP_HOST # The HTTP server host name, IPv4 address or IPv6 address. # Valid examples include: # myhost # 192.168.2.3 # ::1 # VAR_HTTP_PORT # The TCP port to connect to when communicating with the server. # VAR_HTTP_PATH # The HTTP path sent to the server. Unused if $connect_only is # present and non-NULL. # f_http_check_access() { local connect_only="$1" hosts= local http_host http_port f_getvar $VAR_HTTP_HOST http_host f_getvar $VAR_HTTP_PORT http_port if ! { f_validate_ipaddr "$http_host" || f_validate_ipaddr6 "$http_host" || { f_dprintf "%s: Looking up hostname, %s, using host(1)" \ "f_http_check_access" "$http_host" f_host_lookup "$http_host" hosts } }; then # All the above validations failed [ "$hosts" ] && f_dialog_msgbox "$hosts" unset $VAR_HTTP_HOST return $FAILURE elif [ ! "$hosts" ]; then # One of the first two validations passed hosts="$http_host" fi local host connected= for host in $hosts; do f_quietly nc -nz "$host" "$http_port" || continue connected=1; break done if [ ! "$connected" ]; then f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \ "$http_host" "$http_port" unset $VAR_HTTP_HOST return $FAILURE fi [ "$connect_only" ] && return $SUCCESS local http_path f_getvar $VAR_HTTP_PATH http_path f_show_info "$msg_checking_access_to" "$http_path" local rx case "$http_path" in http://*|/*) : valid request ;; *) http_path="/$http_path" # full URI requests only esac if ! rx=$( printf "GET %s/ HTTP/1.0\r\n\r\n" "${http_path%/}" | nc -n "$host" "$http_port" ); then f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \ "$http_host" "$http_port" unset $VAR_HTTP_HOST return $FAILURE fi local hdr hdr=$( echo "$rx" | awk '/^\r$/{exit}{print}' ) local http_found=$FAILURE if echo "$hdr" | awk ' BEGIN { found = 0 } /^HTTP.... 200 / { found = 1 exit } END { exit ! found } '; then http_found=$SUCCESS fi return $http_found } # f_media_init_http $device # # Initializes the HTTP media device. Returns success if able to confirm the # existence of at least one known HTTP server release path directly via HTTP # using f_http_check_access(), above. # # Variables from variable.subr that can be used to script user input: # # VAR_HTTP_HOST # The HTTP server to connect to. Must be set. Also see # f_http_check_access() for additional variables. # VAR_RELNAME # Usually set to `uname -r' but can be overridden. # VAR_HTTP_PATH # The HTTP path sent to the server. Usually set by calling # f_media_set_http(). # # Meanwhile, after successful execution, the following variables (also from # variable.subr) are set: # # VAR_HTTP_PATH # The [possibly] adjusted VAR_HTTP_PATH that was found to contain # a valid FreeBSD repository. # f_media_init_http() { local dev="$1" f_dprintf "Init routine called for HTTP device. dev=[%s]" "$dev" + if [ "$HTTP_INITIALIZED" ]; then + f_dprintf "HTTP device already initialized." + return $SUCCESS + fi + # # First verify access # local connect_only=1 f_http_check_access $connect_only local http_host f_getvar $VAR_HTTP_HOST http_host while [ ! "$http_host" ]; do f_media_set_http || return $FAILURE f_http_check_access $connect_only f_getvar $VAR_HTTP_HOST http_host done local http_path http_found=$FAILURE while :; do # # Now that we've verified that the path we're given is ok, # let's try to be a bit intelligent in locating the release we # are looking for. First off, if the release is specified as # "__RELEASE" or "any", then just assume that the current # directory is the one we want and give up. # local rel f_getvar $VAR_RELNAME rel f_dprintf "f_media_init_http: rel=[%s]" "$rel" case "$rel" in __RELEASE|any) f_getvar $VAR_HTTP_DIR $VAR_HTTP_PATH f_http_check_access http_found=$? ;; *) # # Ok, since we have a release variable, let's walk # through the list of directories looking for a release # directory. First successful path wins. # local fdir hp f_getvar $VAR_HTTP_PATH%/ hp - for fdir in $HTTP_DIRS; do - setvar $VAR_HTTP_PATH "$hp/$fdir/$rel" - if f_http_check_access; then - http_found=$SUCCESS - break - fi - done + setvar $VAR_HTTP_PATH "$hp/$PKG_ABI/latest" + if [ "$PKG_ABI" ] && f_http_check_access; then + http_found=$SUCCESS + setvar $VAR_HTTP_PATH "$hp" + else + for fdir in $HTTP_DIRS; do + setvar $VAR_HTTP_PATH "$hp/$fdir/$rel" + if f_http_check_access; then + http_found=$SUCCESS + break + fi + done + fi esac - [ $http_found -eq $SUCCESS ] && break + if [ $http_found -eq $SUCCESS ]; then + HTTP_INITIALIZED=YES + break + fi f_getvar $VAR_HTTP_PATH http_path f_show_msg "$msg_please_check_the_url_and_try_again" \ "$http_path" - unset $VAR_HTTP_PATH + unset HTTP_INITIALIZED $VAR_HTTP_PATH f_media_set_http || break done return $http_found } # f_media_get_http $device $file [$probe_type] # # Returns data from $file on an HTTP server using nc(1). Please note that # $device is unused but must be present (even if null). Information is instead # gathered from the environment. If $probe_type is both present and non-NULL, # this function exits after receiving the HTTP header response from the server # (if the HTTP response code is 200, success is returned; otherwise failure). # If $probe_type is equal to $PROBE_SIZE, prints the content-length in bytes # from the response (or -1 if not found) to standard-out. # # The variables used to configure the connection are as follows (all of which # are configured by f_media_set_http above): # # VAR_HTTP_HOST # HTTP server which to connect. Can be an IPv4 address, IPv6 # address, or DNS hostname of your choice. # VAR_HTTP_PORT # TCP port to connect on; see f_media_set_http above. # VAR_HTTP_PATH # Directory prefix to use when requesting $file. Default is `/' # unless f_media_init_http was able to use f_http_check_access # to validate one of the defaults in $HTTP_DIRS (see GLOBALS at # the top of this file); assuming VAR_RELNAME was not set to # either `__RELEASE' or `any' (indicating that the global set of # $HTTP_DIRS should be ignored). # # See variable.subr for additional information. # # Example usage: # f_media_set_http # f_media_get_http media $file # f_media_get_http() { local dev="$1" file="$2" probe_type="$3" hosts= local name $dev get name name f_dprintf "f_media_get_http: dev=[%s] file=[%s] probe_type=%s" \ "$name" "$file" "$probe_type" local http_host http_port f_getvar $VAR_HTTP_HOST http_host f_getvar $VAR_HTTP_PORT http_port + if [ ! "$HTTP_INITIALIZED" ]; then + f_dprintf "No HTTP connection open, can't get file %s" "$file" + return $FAILURE + fi + if ! { f_validate_ipaddr "$http_host" || f_validate_ipaddr6 "$http_host" || { f_dprintf "%s: Looking up hostname, %s, using host(1)" \ "f_media_get_http" "$http_host" f_host_lookup "$http_host" hosts } }; then # All the above validations failed [ "$hosts" ] && f_dialog_msgbox "$hosts" return $FAILURE elif [ ! "$hosts" ]; then # One of the first two validations passed hosts="$http_host" fi local host connected= for host in $hosts; do f_quietly nc -nz "$host" "$http_port" || continue connected=1; break done if [ ! "$connected" ]; then f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \ "$http_host" "$http_port" return $FAILURE fi local http_path f_getvar $VAR_HTTP_PATH%/ http_path case "$http_path" in http://*|/*) : valid request ;; *) http_path="/$http_path" # full URI requests only esac local url="$http_path/$file" rx f_dprintf "sending http request for: %s" "$url" f_dprintf "using nc to connect to: %s:%s" "$host" "$http_port" printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$http_port" | ( # # scan the headers of the response # this is extremely quick'n dirty # rv=0 length=-1 while read LINE; do case "$LINE" in HTTP*) f_dprintf "received response: %s" "$LINE" set -- $LINE; rv=$2 f_isinteger "$rv" || rv=0 ;; "Content-Length: "*) length="${LINE% }" length="${length#Content-Length: }" f_dprintf "received content-length: %s" \ "$length" ;; *) [ "${LINE% }" ] || break # End of headers esac done [ $rv -ge 500 ] && exit 5 [ $rv -eq 404 ] && exit 44 [ $rv -ge 400 ] && exit 4 [ $rv -ge 300 ] && exit 3 [ $rv -eq 200 ] || exit $FAILURE if [ ! "$probe_type" ]; then cat # output the rest ``as-is'' elif [ "$probe_type" = "$PROBE_SIZE" ]; then f_isinteger "$length" || length=-1 echo "$length" fi exit 200 ) local retval=$? [ $retval -eq 200 ] && return $SUCCESS [ "$probe_type" ] && return $FAILURE case "$retval" in 5) f_show_msg "$msg_server_error_when_requesting_url" "$url" ;; 44) f_show_msg "$msg_url_was_not_found" "$url" ;; 4) f_show_msg "$msg_client_error" ;; *) f_show_msg "$msg_error_when_requesting_url" "$url" ;; esac return $FAILURE +} + +# f_media_shutdown_http $device +# +# Shuts down the HTTP device. Return status should be ignored. Note that since +# we don't maintain an open connection to the HTTP server, nothing to do. +# +f_media_shutdown_http() +{ + [ "$HTTP_INITIALIZED" ] || return $SUCCESS + + unset HTTP_INITIALIZED } ############################################################ MAIN f_dprintf "%s: Successfully loaded." media/http.subr fi # ! $_MEDIA_HTTP_SUBR Index: stable/9/usr.sbin/bsdconfig/share/packages/index.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/share/packages/index.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/share/packages/index.subr (revision 267683) @@ -1,287 +1,473 @@ if [ ! "$_PACKAGES_INDEX_SUBR" ]; then _PACKAGES_INDEX_SUBR=1 # # Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." packages/index.subr f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/media/common.subr f_include $BSDCFG_SHARE/strings.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" f_include_lang $BSDCFG_LIBE/include/messages.subr ############################################################ GLOBALS PACKAGE_INDEX= _INDEX_INITTED= +# +# Default path to pkg(8) repo-packagesite.sqlite database +# +SQLITE_REPO="/var/db/pkg/repo-packagesite.sqlite" + +# +# Default path to on-disk cache INDEX file +# +PACKAGES_INDEX_CACHEFILE="/var/run/bsdconfig/packages_INDEX.cache" + +# +# INDEX format for FreeBSD-6.0 or higher: +# +# package|port-origin|install-prefix|comment|port-desc-file|maintainer| +# categories|build-deps|run-deps|www-site|reserve|reserve|reserve|disc +# +INDEX_FORMAT="%n-%v" # package +INDEX_FORMAT="$INDEX_FORMAT|/usr/ports/%o" # port-origin +INDEX_FORMAT="$INDEX_FORMAT|%p" # install-prefix +INDEX_FORMAT="$INDEX_FORMAT|%c" # comment +INDEX_FORMAT="$INDEX_FORMAT|/usr/ports/%o/pkg-descr" # port-desc-file +INDEX_FORMAT="$INDEX_FORMAT|%m" # maintainer +INDEX_FORMAT="$INDEX_FORMAT|@CATEGORIES@" # place-holder +INDEX_FORMAT="$INDEX_FORMAT|" # build-deps +INDEX_FORMAT="$INDEX_FORMAT|@RUNDEPS@" # place-holder +INDEX_FORMAT="$INDEX_FORMAT|%w" # www-site +INDEX_FORMAT="$INDEX_FORMAT|" # reserved +INDEX_FORMAT="$INDEX_FORMAT|" # reserved +INDEX_FORMAT="$INDEX_FORMAT|" # reserved +INDEX_FORMAT="$INDEX_FORMAT|" # disc + ############################################################ FUNCTIONS -# f_index_initialize $path [$var_to_set] +# f_index_initialize [$var_to_set] # -# Read and initialize the global index. $path is to be relative to the chosen -# media (not necessarily the filesystem; e.g. FTP) -- this is usually going to -# be `packages/INDEX'. Returns success unless media cannot be initialized for -# any reason (e.g. user cancels media selection dialog) or an error occurs. The -# index is sorted before being loaded into $var_to_set. +# Read and initialize the global index. Returns success unless media cannot be +# initialized for any reason (e.g. user cancels media selection dialog or an +# error occurs). The index is sorted before being loaded into $var_to_set. # # NOTE: The index is processed with f_index_read() [below] after being loaded. # f_index_initialize() { - local __path="$1" __var_to_set="${2:-PACKAGE_INDEX}" + local __funcname=f_index_initialize + local __var_to_set="${2:-PACKAGE_INDEX}" [ "$_INDEX_INITTED" ] && return $SUCCESS - [ "$__path" ] || return $FAILURE # Got any media? f_media_verify || return $FAILURE # Does it move when you kick it? f_device_init device_media || return $FAILURE - f_show_info "$msg_attempting_to_fetch_file_from_selected_media" \ - "$__path" - eval "$__var_to_set"='$( f_device_get device_media "$__path" )' - if [ $? -ne $SUCCESS ]; then - f_show_msg "$msg_unable_to_get_file_from_selected_media" \ - "$__path" + f_show_info "$msg_attempting_to_update_repository_catalogue" + + # + # Generate $PACKAGESITE variable for pkg(8) based on media type + # + local __type __data __site + device_media get type __type + device_media get private __data + case "$__type" in + $DEVICE_TYPE_DIRECTORY) + __site="file://$__data/packages/$PKG_ABI" ;; + $DEVICE_TYPE_FLOPPY) + __site="file://${__data:-$MOUNTPOINT}/packages/$PKG_ABI" ;; + $DEVICE_TYPE_FTP) + f_getvar $VAR_FTP_PATH __site + __site="$__site/packages/$PKG_ABI" ;; + $DEVICE_TYPE_HTTP) + f_getvar $VAR_HTTP_PATH __site + __site="$__site/$PKG_ABI/latest" ;; + $DEVICE_TYPE_HTTP_PROXY) + f_getvar $VAR_HTTP_PROXY_PATH __site + __site="$__site/packages/$PKG_ABI" ;; + $DEVICE_TYPE_CDROM) + __site="file://$MOUNTPOINT/packages/$PKG_ABI" + export REPOS_DIR="$MOUNTPOINT/packages/repos" ;; + *) # UFS, DISK, CDROM, USB, DOS, NFS, etc. + __site="file://$MOUNTPOINT/packages/$PKG_ABI" + esac + + export PACKAGESITE="$__site" + f_dprintf "PACKAGESITE=[%s]" "$PACKAGESITE" + if ! f_eval_catch $__funcname pkg "pkg update"; then + f_show_err "$msg_unable_to_update_pkg_from_selected_media" f_device_shutdown device_media return $FAILURE fi + + # + # Try to get contents from validated on-disk cache + # + + # + # Calculate digest used to determine if the on-disk persistant cache + # INDEX (containing this digest on the first line) is valid and can be + # used to quickly populate the environment. + # + local __sqlite_digest + if ! __sqlite_digest=$( md5 < "$SQLITE_REPO" 2> /dev/null ); then + f_show_err "$msg_no_pkg_database_found" + f_device_shutdown device_media + return $FAILURE + fi + + # + # Check to see if the persistant cache INDEX file exists + # + if [ -f "$PACKAGES_INDEX_CACHEFILE" ]; then + # + # Attempt to populate the environment with the (soon to be) + # validated on-disk cache. If validation fails, fall-back to + # generating a fresh cache. + # + if eval $__var_to_set='$( + ( # Get digest as the first word on first line + read digest rest_ignored + + # + # If the stored digest matches the calculated- + # one populate the environment from the on-disk + # cache and provide success exit status. + # + if [ "$digest" = "$__sqlite_digest" ]; then + cat + exit $SUCCESS + else + # Otherwise, return the current value + eval echo \"\$__var_to_set\" + exit $FAILURE + fi + ) < "$PACKAGES_INDEX_CACHEFILE" 2> /dev/null + )'; then + f_show_info \ + "$msg_located_index_now_reading_package_data_from_it" + if ! f_index_read "$__var_to_set"; then + f_show_err \ + "$msg_io_or_format_error_on_index_file" + return $FAILURE + fi + _INDEX_INITTED=1 + return $SUCCESS + fi + # Otherwise, fall-thru to create a fresh cache from scratch + fi + + # + # If we reach this point, we need to generate the data from scratch + # + + f_show_info "$msg_getting_package_categories_via_pkg_rquery" + if ! eval "$( pkg rquery "%n-%v %C" | awk ' + { categories[$1] = categories[$1] " " $2 } + END { + for (package in categories) + { + cats = categories[package] + sub(/^ /, "", cats) + gsub(/[^[:alnum:]_]/, "_", package) + printf "local _%s_categories=\"%s\";\n", package, cats + } + }' )"; then + f_show_err "$msg_unable_to_pkg_rquery_package_dependencies" + f_device_shutdown device_media + return $FAILURE + fi + + f_show_info "$msg_getting_package_dependencies_via_pkg_rquery" + if ! eval "$( pkg rquery "%n-%v %dn-%dv" | awk ' + { rundeps[$1] = rundeps[$1] " " $2 } + END { + for (package in rundeps) + { + deps = rundeps[package] + sub(/^ /, "", deps) + gsub(/[^[:alnum:]_]/, "_", package) + printf "local _%s_rundeps=\"%s\";\n", package, deps + } + }' )"; then + f_show_err "$msg_unable_to_pkg_rquery_package_dependencies" + f_device_shutdown device_media + return $FAILURE + fi + + f_show_info "$msg_generating_index_from_pkg_database" + eval "$__var_to_set"='$( pkg rquery "$INDEX_FORMAT" | + while read LINE; do + package="${LINE%%|*}"; + f_str2varname "$package" varpkg; + eval f_replaceall \"\$LINE\" \"\|@CATEGORIES@\|\" \ + \"\|\$_${varpkg}_categories\|\" LINE + eval f_replaceall \"\$LINE\" \"\|@RUNDEPS@\|\" \ + \"\|\$_${varpkg}_rundeps\|\" LINE + echo "$LINE" + done + )' # always returns true (status of last item in pipe-chain) eval "$__var_to_set"='$( debug= f_getvar "$__var_to_set" | sort )' + # + # Attempt to create the persistant on-disk cache + # + + # Create a new temporary file to write to + local __tmpfile + if f_eval_catch -dk __tmpfile $__funcname mktemp \ + 'mktemp -t "%s"' "$pgm" + then + # Write the temporary file contents + echo "$__sqlite_digest" > "$__tmpfile" + debug= f_getvar "$__var_to_set" >> "$__tmpfile" + + # Finally, move the temporary file into place + case "$PACKAGES_INDEX_CACHEFILE" in + */*) f_eval_catch -d $funcname mkdir \ + 'mkdir -p "%s"' "${PACKAGES_INDEX_CACHEFILE%/*}" + esac + f_eval_catch -d $__funcname mv 'mv -f "%s" "%s"' \ + "$__tmpfile" "$PACKAGES_INDEX_CACHEFILE" + fi + f_show_info "$msg_located_index_now_reading_package_data_from_it" if ! f_index_read "$__var_to_set"; then - f_show_msg "$msg_io_or_format_error_on_index_file" "$__path" + f_show_err "$msg_io_or_format_error_on_index_file" return $FAILURE fi _INDEX_INITTED=1 return $SUCCESS } # f_index_read [$var_to_get] # # Process the INDEX file (contents contained in $var_to_get) and... # # 1. create a list ($CATEGORY_MENU_LIST) of categories with package counts # 2. For convenience, create $_npkgs holding the total number of all packages # 3. extract associative categories for each package into $_categories_$varpkg # 4. extract runtime dependencies for each package into $_rundeps_$varpkg # 5. extract a [sorted] list of categories into $PACKAGE_CATEGORIES # 6. create $_npkgs_$varcat holding the total number of packages in category # # NOTE: $varpkg is the product of f_str2varname $package varpkg # NOTE: $package is the name as it appears in the INDEX (no archive suffix) # NOTE: We only show categories for which there are at least one package. # NOTE: $varcat is the product of f_str2varname $category varcat # f_index_read() { local var_to_get="${1:-PACKAGE_INDEX}" # Export variables required by awk(1) below export msg_no_description_provided export msg_all msg_all_desc export VALID_VARNAME_CHARS export msg_packages eval "$( debug= f_getvar "$var_to_get" | awk -F'|' ' function asorti(src, dest) { # Copy src indices to dest and calculate array length nitems = 0; for (i in src) dest[++nitems] = i # Sort the array of indices (dest) using insertion sort method for (i = 1; i <= nitems; k = i++) { idx = dest[i] while ((k > 0) && (dest[k] > idx)) { dest[k+1] = dest[k] k-- } dest[k+1] = idx } return nitems } function print_category(category, npkgs, desc) { cat = category # Accent the category if the first page has been # cached (also acting as a visitation indicator) if ( ENVIRON["_index_page_" varcat "_1"] ) cat = cat "*" printf "'\''%s'\'' '\''%s " packages "'\'' '\''%s'\''\n", cat, npkgs, desc } BEGIN { valid_chars = ENVIRON["VALID_VARNAME_CHARS"] default_desc = ENVIRON["msg_no_description_provided"] packages = ENVIRON["msg_packages"] tpkgs = 0 prefix = "" } { tpkgs++ varpkg = $1 gsub("[^" valid_chars "]", "_", varpkg) print "_categories_" varpkg "=\"" $7 "\"" split($7, pkg_categories, /[[:space:]]+/) for (pkg_category in pkg_categories) categories[pkg_categories[pkg_category]]++ print "_rundeps_" varpkg "=\"" $9 "\"" } END { print "_npkgs=" tpkgs # For convenience, total package count n = asorti(categories, categories_sorted) # Produce package counts for each category for (i = 1; i <= n; i++) { cat = varcat = categories_sorted[i] npkgs = categories[cat] gsub("[^" valid_chars "]", "_", varcat) print "_npkgs_" varcat "=\"" npkgs "\"" } # Create menu list and generate list of categories at same time print "CATEGORY_MENU_LIST=\"" print_category(ENVIRON["msg_all"], tpkgs, ENVIRON["msg_all_desc"]) category_list = "" for (i = 1; i <= n; i++) { cat = varcat = categories_sorted[i] npkgs = categories[cat] cur_prefix = tolower(substr(cat, 1, 1)) if ( prefix != cur_prefix ) prefix = cur_prefix else cat = " " cat gsub("[^" valid_chars "]", "_", varcat) desc = ENVIRON["_category_" varcat] if ( ! desc ) desc = default_desc print_category(cat, npkgs, desc) category_list = category_list " " cat } print "\"" # Produce the list of categories (calculated in above block) sub(/^ /, "", category_list) print "PACKAGE_CATEGORIES=\"" category_list "\"" }' )" # End-Quote } # f_index_extract_pages $var_to_get $var_basename $pagesize [$category] # # Extracts the package INDEX ($PACKAGE_INDEX by default if/when $var_to_get is # NULL; but should not be missing) into a series of sequential variables # corresponding to "pages" containing up to $pagesize packages. The package # INDEX data must be contained in the variable $var_to_get. The extracted pages # are stored in variables ${var_basename}_# -- where "#" is a the page number. # If $category is set, only packages for that category are extracted. # Otherwise, if $category is "All", missing, or NULL, all packages are # extracted and no filtering is done. # f_index_extract_pages() { local var_to_get="${1:-PACKAGE_INDEX}" var_basename="$2" pagesize="$3" local category="$4" # Optional eval "$( debug= f_getvar "$var_to_get" | awk -F'|' \ -v cat="$category" \ -v pagesize="$pagesize" \ -v var_basename="$var_basename" \ -v i18n_all="$msg_all" ' BEGIN { n = page = 0 } /'\''/{ gsub(/'\''/, "'\''\\'\'\''") } { if ( cat !~ "(^$|^" i18n_all "$)" && $7 !~ \ "(^|[[:space:]])" cat "([[:space:]]|$)" ) next starting_new_page = (n++ == (pagesize * page)) if ( starting_new_page ) printf "%s%s", ( n > 1 ? "'\''\n" : "" ), var_basename "_" ++page "='\''" printf "%s%s", ( starting_new_page ? "" : "\n" ), $0 } END { if ( n > 0 ) print "'\''" }' )" } # f_index_search $var_to_get $name [$var_to_set] # # Search the package INDEX ($PACKAGE_INDEX by default if/when $var_to_get is # NULL; but should not be missing) for $name, returning the first match. # Matches are strict (not regular expressions) and must match the beginning # portion of the package name to be considered a match. If $var_to_set is # missing or NULL, output is sent to standard output. If a match is found, # returns success; otherwise failure. # f_index_search() { local __var_to_get="${1:-PACKAGE_INDEX}" __pkg_basename="$2" local __var_to_set="$3" f_dprintf "f_index_search: Searching package data (in %s) for %s" \ "$__var_to_get" "$__pkg_basename" local __pkg= __pkg=$( debug= f_getvar "$__var_to_get" | awk -F'|' -v basename="$__pkg_basename" ' BEGIN { n = length(basename) } substr($1, 0, n) == basename { print $1; exit } ' ) if [ ! "$__pkg" ]; then f_dprintf "f_index_search: No packages matching %s found" \ "$__pkg_basename" return $FAILURE fi f_dprintf "f_index_search: Found package %s" "$__pkg" if [ "$__var_to_set" ]; then setvar "$__var_to_set" "$__pkg" else echo "$__pkg" fi return $SUCCESS } ############################################################ MAIN f_dprintf "%s: Successfully loaded." packages/index.subr fi # ! $_PACKAGES_INDEX_SUBR Index: stable/9/usr.sbin/bsdconfig/share/packages/packages.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/share/packages/packages.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/share/packages/packages.subr (revision 267683) @@ -1,1203 +1,1187 @@ if [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_SUBR=1 # # Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." "$0" f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/media/common.subr f_include $BSDCFG_SHARE/packages/categories.subr f_include $BSDCFG_SHARE/packages/index.subr f_include $BSDCFG_SHARE/strings.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" f_include_lang $BSDCFG_LIBE/include/messages.subr ############################################################ CONFIGURATION # # How many packages to display (maximum) per dialog menubox. # : ${PACKAGE_MENU_PAGESIZE:=2000} ############################################################ GLOBALS # # Package extensions to try # -PACKAGE_EXTENSIONS=".tbz .tbz2 .tgz" +PACKAGE_EXTENSIONS=".txz .tbz .tbz2 .tgz" # # Variables used to track runtime states # PACKAGES_DETECTED= # Boolean (NULL/non-NULL); detected installed packages? PACKAGE_CATEGORIES= # List of package categories parsed from INDEX SELECTED_PACKAGES= # Packages selected by user in [X]dialog(1) interface # # Options # [ "${SHOW_DESC+set}" ] || SHOW_DESC=1 ############################################################ FUNCTIONS # eval f_package_accent_category_menu $var_to_set $CATEGORY_MENU_LIST # # Accent the CATEGORY_MENU_LIST produced by f_index_read() (see # packages/index.subr). Accented information includes adding an asterisk to the # category name if its index has been cached, adding the number of installed # packages for each category, and adding the number _selected_ packages for # each category. # # NOTE: The reason `eval' is recommended/shown for the syntax above is because # the $CATEGORY_MENU_LIST generated by f_index_read() is meant to be expanded # prior to execution (it contains a series of pre-quoted strings which act as # the interpolated command arguments). # f_package_accent_category_menu() { local var_to_set="$1" category cat desc help varcat menu_buf n shift 1 # var_to_set while [ $# -gt 0 ]; do category="${1%\*}" desc="${2%%; *}" help="$3" shift 3 # cat/desc/help cat="${category# }" # Trim lead space inserted by sort-method f_str2varname "$cat" varcat # Add number of installed packages for this category (if any) n=0 case "$cat" in "$msg_all") debug= f_getvar "_All_ninstalled" n ;; *) debug= f_getvar "_${varcat}_ninstalled" n ;; esac && [ $n -ge 1 ] && desc="$desc; $n $msg_installed_lc" # Add number of selected packages for this category (if any) n=0 case "$cat" in "$msg_all") debug= f_getvar "_All_nselected" n ;; *) debug= f_getvar "_${varcat}_nselected" n ;; esac && [ $n -ge 1 ] && desc="$desc; $n $msg_selected" # Re-Add asterisk to the category if its index has been cached f_isset _index_page_${varcat}_1 && category="$category*" # Update buffer with modified elements menu_buf="$menu_buf '$category' '$desc' '$help'" # End-Quote done setvar "$var_to_set" "$menu_buf" # return our buffer } # f_package_select $package ... # # Add $package to the list of tracked/selected packages. If $package is already # being tracked (already apears in $SELECTED_PACKAGES), this function amounts # to having no effect. # f_package_select() { local package pkgsel while [ $# -gt 0 ]; do package="$1" shift 1 # package for pkgsel in $SELECTED_PACKAGES; do [ "$package" = "$pkgsel" ] && return $SUCCESS done SELECTED_PACKAGES="$SELECTED_PACKAGES $package" f_dprintf "Added %s to selection list" "$package" done SELECTED_PACKAGES="${SELECTED_PACKAGES# }" # Trim leading space } # f_package_deselect $package ... # # Remove $package from teh list of tracked/selected packages. If $package is # not being tracked (doesn't appear in $SELECTED_PACKAGES), this function # amounts to having no effet. # f_package_deselect() { local package pkgsel while [ $# -gt 1 ]; do local new_list="" package="$1" shift 1 # package for pkgsel in $SELECTED_PACKAGES; do [ "$pkgsel" = "$package" ] && continue new_list="$new_list${new_list:+ }$pkgsel" done SELECTED_PACKAGES="$new_list" f_dprintf "Removed %s from selection list" "$package" done } # f_package_detect_installed # -# Detect installed packages. Currently this searches /var/db/pkg for directory +# Detect installed packages. Currently this uses pkg-query(8) for querying # entries and marks each entry as an installed/selected package. # f_package_detect_installed() { - local installed package varpkg - # - # XXX KLUDGE ALERT! This makes evil assumptions about how XXX - # packages register themselves and should *really* be done with - # `pkg_info -e ' except that this is too slow for an - # item check routine.. :-( - # - # NOTE: When transitioning to pkgng, make a single fork to `pkg' to - # produce a list of all installed packages and parse _that_ - # - installed=$( find -s /var/db/pkg -mindepth 1 -maxdepth 1 -type d | - sed -e 's:/var/db/pkg/::' ) - for package in $installed; do + local package varpkg + for package in $( pkg query "%n-%v" ); do f_str2varname $package varpkg export _mark_$varpkg=X # exported for awk(1) ENVIRON[] f_package_select $package done } # f_package_calculate_totals # # Calculate number of installed/selected packages for each category listed in # $PACKAGE_CATEGORIES (the number of installed packages for $category is stored # as $_${varcat}_ninstalled -- where $varcat is the product of `f_str2varname # $category varcat' -- and number selected packages as $_${varcat}_nselected). # Also calculates the total number of installed/selected packages stored as # $_All_ninstalled and $_All_nselected. # # Calculations are peformed by checking "marks". A "mark" is stored as # $_mark_$varpkg -- where $varpkg is the product of `f_str2varname $package # varpkg'. A mark can be "X" for an installed package, `I' for a package that # is marked for installation, "R" for a package that is marked for re-install, # and "U" for a package that is marked for uninstallation. If a package mark is # NULL or a single space (e.g., " "), the package is considered to be NOT # selected (and therefore does not increment the counts calculated herein). # f_package_calculate_totals() { local pkg varpkg mark cat varcat pkgcat n tselected=0 tinstalled=0 for cat in $PACKAGE_CATEGORIES; do f_str2varname $cat varcat setvar _${varcat}_ninstalled=0 setvar _${varcat}_nselected=0 done for pkg in $SELECTED_PACKAGES; do f_str2varname $pkg varpkg mark= f_getvar _mark_$varpkg mark case "$mark" in ""|" ") : ;; X) tinstalled=$(( $tinstalled + 1 )) ;; *) tselected=$(( $tselected + 1 )) esac f_getvar _categories_$varpkg pkgcat for cat in $pkgcat; do f_str2varname $cat varcat case "$mark" in ""|" ") : ;; X) debug= f_getvar _${varcat}_ninstalled n setvar _${varcat}_ninstalled $(( $n + 1 )) ;; *) debug= f_getvar _${varcat}_nselected n setvar _${varcat}_nselected $(( $n + 1 )) esac done done _All_nselected=$tselected _All_ninstalled=$tinstalled } # f_package_calculate_rundeps # # Update package dependencies by first unmarking all dependencies and then # re-marking all dependencies of packages marked for either install ("I") or # re-install ("R"). # f_package_calculate_rundeps() { local pkg varpkg mark rundeps dep vardep # # First unmark all the existing run-dependencies # f_dprintf "Unselecting package run-dependencies..." for pkg in $SELECTED_PACKAGES; do f_str2varname $pkg varpkg mark= debug= f_getvar _mark_$varpkg mark # Only unmark if it's marked as a Dependency if [ "$mark" = "D" ]; then f_dprintf "%s unselected" $pkg unset _mark_$varpkg f_package_deselect $pkg fi done # # Processes selected packages, adding dependencies # f_dprintf "Re-selecting package run-dependencies..." for pkg in $SELECTED_PACKAGES; do f_str2varname $pkg varpkg mark= debug= f_getvar _mark_$varpkg mark # Skip pkg unless marked for [Re-]Install [ "$mark" = "I" -o "$mark" = "R" ] || continue f_getvar _rundeps_$varpkg rundeps for dep in $rundeps; do f_str2varname $dep vardep mark= debug= f_getvar _mark_$vardep mark # Skip dep if already marked [ "${mark:- }" = " " ] || continue export _mark_$vardep="D" f_package_select $dep done done f_dprintf "Finished recalculating dependencies." } # f_package_menu_categories $var_to_set $defaultitem # # Dislay the menu of package categories, complete with package counts for each # category, accents, and other miscellany. If $defaultitem is non-NULL and # matches one of the existing menu-items, it will be pre-highlighted in the # menu dialog (HINT: Use f_dialog_menutag_fetch() to populate a local variable # that is passed as $defaultitem to highlight the user's last selection). # f_package_menu_categories() { local var_to_get="$1" defaultitem="$2" local prompt="$msg_please_select_a_category_to_display" local menu_list=" '> $msg_review' '$msg_review_desc' '$msg_review_help' " # End-Quote local hline= f_package_calculate_rundeps # updates package mark variables and SELECTED_PACKAGES f_package_calculate_totals # creates _{varcat}_ninstalled and _{varcat}_nselected local category_list debug= f_getvar "$var_to_get" category_list || return $DIALOG_CANCEL # Accent the category menu list with ninstalled/nselected eval f_package_accent_category_menu category_list $category_list # Add list of categories to menu list menu_list="$menu_list $category_list" local height width rows eval f_dialog_menu_with_help_size height width rows \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list local menu_choice menu_choice=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --item-help \ --default-item \"\$defaultitem\" \ --ok-label \"$msg_select\" \ --cancel-label \"$msg_cancel\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_menutag_store -s "$menu_choice" return $retval } # f_package_index_get_page $category $page [$var_to_set [$var_to_get]] # # Obtain a [potentially cached] page of the INDEX file for a given $category. # If $page is 1 and the cache has not yet been generated, the cache-generating # function f_index_extract_pages() (above) is called to generate all pages # (not just the requested page) in cache before returning the requested page. # If $page is not 1 and there is no cached page, failure status is returned. # f_package_index_get_page() { local category="$1" page="$2" var_to_set="$3" var_to_get="$4" varcat f_str2varname "$category" varcat if ! debug= f_getvar "_index_page_${varcat}_$page" $var_to_set && [ "$page" = "1" ] then f_show_info "$msg_building_package_menus" local pagesize="$PACKAGE_MENU_PAGESIZE" f_index_extract_pages "${var_to_get:-PACKAGE_INDEX}" \ _index_page_${varcat} "$pagesize" "$category" debug= f_getvar _index_page_${varcat}_$page $var_to_set # Update category default-item because now we're cached [ $page -eq 1 ] && category_defaultitem="${category_defaultitem%\*}*" else return $FAILURE fi } # f_package_menu_select $category [$page [$defaultitem]] # # Display list of packages for $category, optionally $page N and with a default # item selected. If $page is omitted, the first page is displayed (but this # only matters if there are multiple pages; which is determined by the global # maximum $PACKAGE_MENU_PAGESIZE). # # On success, if the user doesn't press ESC or choose Cancel, use # f_dialog_menuitem_fetch() to populate a local variable with the item (not # tag) corresponding to the user's selection. The tag portion of the user's # selection is available through f_dialog_menutag_fetch(). # f_package_menu_select() { local category="$1" page="${2:-1}" local prompt= # Calculated below local menu_list # Calculated below local defaultitem="$3" local hline="$hline_arrows_tab_punc_enter" f_isinteger "$page" || return $DIALOG_CANCEL local varcat f_str2varname "$category" varcat # Get number of packages for this category local npkgs=0 case "$category" in "$msg_all"|"") npkgs="${_npkgs:-0}" ;; *) f_getvar _npkgs_$varcat npkgs esac # Calculate number of pages local npages=$(( ${npkgs:=0} / $PACKAGE_MENU_PAGESIZE )) # Add a page to the pagecount if not evenly divisible [ $(( $npages * $PACKAGE_MENU_PAGESIZE )) -lt $npkgs ] && npages=$(( $npages + 1 )) # Print some debugging information f_dprintf "f_package_menu_select: category=[%s] npkgs=%u npages=%u" \ "$category" "$npkgs" "$npages" local add_prev="" add_next="" local previous_page="$msg_previous_page" next_page="$msg_next_page" if [ $page -gt 1 ]; then add_prev=1 # Accent the `Previous Page' item with an asterisk # if the page-before-previous is loaded/cached f_isset _index_page_${varcat}_$(( $page - 1 )) && previous_page="$previous_page*" fi if [ $page -lt $npages ]; then add_next=1 # Accent the `Next Page' item with an asterisk # if the page-after-next is loaded/cached f_isset _index_page_${varcat}_$(( $page + 1 )) && next_page="$next_page*" fi local index_page f_package_index_get_page "$category" $page index_page menu_list=" ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} $( export SHOW_DESC export VALID_VARNAME_CHARS echo "$index_page" | awk -F'|' -v view="port" ' BEGIN { valid_chars = ENVIRON["VALID_VARNAME_CHARS"] prefix = "" } { cur_prefix = tolower(substr($1, 1, 1)) printf "'\''" if ( prefix != cur_prefix ) prefix = cur_prefix else printf " " package = $1 if ( view == "port" ) desc = $2 varpkg = package gsub("[^" valid_chars "]", "_", varpkg) mark = ENVIRON["_mark_" varpkg] if ( ! mark ) mark = " " printf "%s'\'' '\''[%c] %s'\''", package, mark, desc if ( ENVIRON["SHOW_DESC"] ) { help = $4 gsub(/'\''/, "'\''\\'\'\''", help) printf " '\''%s'\''", help } printf "\n" }' ) ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}} ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}} " # End-Quote # Accept/Translate i18n "All" but other category names must # match tree definitions from INDEX, ports, FTP, etc. case "$category" in "$msg_all"|"") f_category_desc_get "All" prompt ;; *) f_category_desc_get "$category" prompt ;; esac f_sprintf prompt "%s $msg_page_of_npages" "$prompt" "$page" "$npages" local mheight mwidth mrows eval f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \ \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \"\$hline\" $menu_list local iheight iwidth f_dialog_infobox_size iheight iwidth \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \ "$msg_processing_selection" local menu_choice menu_choice=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --keep-tite \ --ok-label \"$msg_select\" \ --cancel-label \"$msg_back\" \ ${SHOW_DESC:+--item-help} \ --default-item \"\$defaultitem\" \ --menu \"\$prompt\" \ $mheight $mwidth $mrows \ $menu_list \ --and-widget \ ${USE_XDIALOG:+--no-buttons} \ --infobox \"\$msg_processing_selection\" \ $iheight $iwidth \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_data_sanitize menu_choice f_dialog_menutag_store "$menu_choice" if [ $retval -eq $DIALOG_OK ]; then local item item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \ \"\$menu_choice\" $menu_list ) f_dialog_menuitem_store "$item" fi return $retval } # f_package_menu_deselect $package # # Display a menu, asking the user what they would like to do with $package # with regard to "deselecting" an already installed package. Choices include # uninstall, re-install, or cancel (leave $package marked as installed). # Returns success if the user does not press ESC or choose Cnacel. Use the # f_dialog_menutag_fetch() function upon success to retrieve the user's choice. # f_package_menu_deselect() { local package="$1" local prompt # Calculated below local menu_list=" 'X $msg_installed' '$msg_installed_desc' 'R $msg_reinstall' '$msg_reinstall_desc' 'U $msg_uninstall' '$msg_uninstall_desc' " # End-Quote local hline="$hline_alnum_arrows_punc_tab_enter" f_sprintf prompt "$msg_what_would_you_like_to_do_with" "$package" local height width rows eval f_dialog_menu_size height width rows \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list local menu_choice menu_choice=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"$msg_select\" \ --cancel-label \"$msg_cancel\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_menutag_store -s "$menu_choice" return $retval } # f_package_review # # Display a review screen, showing selected packages and what they are marked # for, before proceeding (if the user does not press ESC or choose Cancel) to # operate on each selection. Returns error if no packages have been selected, # or the user has pressed ESC, or if they have chosen Cancel. # f_package_review() { local funcname=f_package_review local prompt # Calculated below local menu_list # Calculated below local hline="$hline_alnum_arrows_punc_tab_enter" f_dprintf "$funcname: SELECTED_PACKAGES=[%s]" "$SELECTED_PACKAGES" f_sprintf prompt "$msg_reviewing_selected_packages" "$_All_nselected" local package varpkg mark for package in $SELECTED_PACKAGES; do mark= f_str2varname "$package" varpkg f_getvar _mark_$varpkg mark [ "$mark" -a ! "${mark#[IRUD]}" ] || continue menu_list="$menu_list '$mark' '$package' " # End-Quote done if [ ! "$menu_list" ]; then f_show_msg "$msg_no_packages_were_selected_for_extraction" return $DIALOG_CANCEL # Might have selected this by accident fi menu_list=$( echo "$menu_list" | sort ) local height width rows eval f_dialog_menu_size height width rows \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list # Show the review menu (ignore menu choice) eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_proceed\" \ --cancel-label \"\$msg_cancel\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2> /dev/null || return $? # Return if the user pressed ESC or chose Cancel/No # # Process each of the selected packages: # + First, process packages marked for Install. # + Second, process packages marked for Re-install. # + Finally, process packages marked for Uninstall. # for package in $SELECTED_PACKAGES; do mark= f_str2varname "$package" varpkg debug= f_getvar _mark_$varpkg mark [ "$mark" = "I" ] || continue f_dprintf "$funcname: Installing %s package" "$package" f_package_add "$package" done for package in $SELECTED_PACKAGES; do mark= f_str2varname "$package" varpkg debug= f_getvar _mark_$varpkg mark [ "$mark" = "R" ] || continue f_dprintf "$funcname: Reinstalling %s package" "$package" f_package_reinstall "$package" done for package in $SELECTED_PACKAGES; do mark= f_str2varname "$package" varpkg debug= f_getvar _mark_$varpkg mark [ "$mark" = "U" ] || continue f_dprintf "$funcname: Uninstalling %s package" "$package" f_package_delete "$package" || continue f_package_deselect "$package" done return $DIALOG_OK } # f_package_config # # Allow the user to configure packages and install them. Initially, a list of # package categories is loaded/displayed. When the user selects a category, # the menus for that category are built (unlike sysinstall which built all # category menus up-front -- which also took forever, despite the fact that # few people visit more than a couple of categories each time). # f_package_config() { # Did we get an INDEX? f_index_initialize packages/INDEX || return $FAILURE # Creates following variables (indirectly via f_index_read()) # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} # PACKAGE_CATEGORIES _npkgs # Detect installed packages (updates marks/SELECTED_PACKAGES) f_package_detect_installed export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] local retval category varcat defaultitem category_defaultitem="" while :; do # Display the list of package categories f_package_menu_categories \ CATEGORY_MENU_LIST "$category_defaultitem" retval=$? f_dialog_menutag_fetch category f_dprintf "retval=%u mtag=[%s]" $retval "$category" category_defaultitem="$category" [ $retval -eq $DIALOG_OK ] || break # Maybe the user chose an action (like `Review') case "$category" in "> $msg_review") f_package_review && break continue ;; "> "*) continue esac # Anything else is a package category category=${category# } # Trim leading space if present category=${category%\*} # Trim trailing asterisk if present f_str2varname "$category" varcat local page package varpkg mark menu_choice while :; do # Display the list of packages for selected category page=1 defaultitem="" f_getvar _defaultitem_$varcat defaultitem f_getvar _defaultpage_$varcat page f_package_menu_select \ "$category" "${page:=1}" "$defaultitem" retval=$? f_dialog_menutag_fetch menu_choice f_dprintf "retval=%u mtag=[%s]" $retval "$menu_choice" # NOTE: When --and-widget is used only ESC will cause # dialog(1) to return without going to the next widget. # This is alright in our case as we can still detect # the Cancel button because stdout will be NULL. # Alternatively, Xdialog(1) will terminate with 1 # if/when Cancel is chosen on any widget. if [ $retval -eq $DIALOG_ESC -o ! "$menu_choice" ] then break elif [ $retval -eq $DIALOG_CANCEL ]; then # Using X11, Xdialog(1) returned 1 for Cancel f_show_msg "%s" "$menu_choice" break elif [ $retval -ne $DIALOG_OK ]; then # X11-related error occurred using Xdialog(1) f_show_msg "%s" "$menu_choice" break fi defaultitem="$menu_choice" # NOTE: f_package_menu_select() does not show the # `Previous Page' or `Next Page' items unless needed case "$menu_choice" in "> $msg_previous_page"|"> $msg_previous_page*") page=$(( $page - 1 )) setvar _defaultpage_$varcat $page # Update default-item to match accent that will # be applied by f_package_menu_select(); if the # page-before-prev is cached, add an asterisk. if f_isset \ _index_page_${varcat}_$(( $page - 1 )) then defaultitem="${defaultitem%\*}*" else defaultitem="${defaultitem%\*}" fi setvar _defaultitem_$varcat "$defaultitem" continue ;; "> $msg_next_page"|"> $msg_next_page*") page=$(( $page + 1 )) setvar _defaultpage_$varcat $page # Update default-item to match accent that will # be applied by f_package_menu_select(); if the # page-after-next is cached, add an asterisk. if f_isset \ _index_page_${varcat}_$(( $page + 1 )) then defaultitem="${defaultitem%\*}*" else defaultitem="${defaultitem%\*}" fi setvar _defaultitem_$varcat "$defaultitem" continue ;; "> "*) # Unknown navigation/action item setvar _defaultpage_$varcat $page continue ;; # Do not treat as a package *) setvar _defaultitem_$varcat "$defaultitem" esac # Treat any other selection as a package package="${menu_choice# }" # Trim leading space f_str2varname $package varpkg f_dialog_menuitem_fetch mark mark="${mark#?}" mark="${mark%%\] *}" case "$mark" in "I") mark=" " f_package_deselect $package ;; " "|"D") mark="I" f_package_select $package ;; "X"|"R"|"U") f_package_menu_deselect $package || continue f_dialog_menutag_fetch menu_choice case "$menu_choice" in "X $msg_installed") f_package_deselect "$package" mark="X" ;; "R $msg_reinstall") f_package_select "$package" mark="R" ;; "U $msg_uninstall") f_package_select "$package" mark="U" ;; esac ;; esac export _mark_$varpkg="$mark" # NOTE: exported for awk(1) ENVIRON[] done done } # f_package_add $package_name [$depended] # # Like f_package_extract(), but assumes current media device and chases deps. # Note that $package_name should not contain the archive suffix (e.g., `.tbz'). # If $depended is present and non-NULL, the package is treated as a dependency # (in this function, dependencies are not handled any differently, but the # f_package_extract() function is passed this value and it displays a different # message when installing a dependency versus non-dependency). # f_package_add() { local name="$1" depended="$2" status=$SUCCESS retval local alert=f_show_msg no_confirm= f_getvar $VAR_NO_CONFIRM no_confirm [ "$no_confirm" ] && alert=f_show_info if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; } then f_dprintf "packageAdd: %s" \ "$msg_no_package_name_passed_in_package_variable" return $FAILURE fi { # Verify and initialize device media if-defined f_media_verify && f_device_init device_media && f_index_initialize packages/INDEX } || return $FAILURE # Now we have (indirectly via f_index_read()): # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} # PACKAGE_CATEGORIES _npkgs local varpkg f_str2varname "$name" varpkg # Just as-in the user-interface (opposed to scripted-use), only allow # packages with at least one category to be recognized. # local pkgcat= if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then # $pkg may be a partial name, search the index (this is slow) f_index_search PACKAGE_INDEX $name name if [ ! "$name" ]; then f_show_msg \ "$msg_sorry_package_was_not_found_in_the_index" \ "$name" return $FAILURE fi f_str2varname "$name" varpkg fi # If invoked through the scripted interface, we likely have not yet # detected the installed packages -- something we should do only once. # if [ ! "$PACKAGES_DETECTED" ]; then f_dprintf "f_package_add: Detecting installed packages" f_package_detect_installed export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] fi # Now we have: _mark_{varpkg}=X for all installed packages # # Since we're maintaining data structures for installed packages, # short-circuit the package dependency checks if the package is already # installed. This prevents wasted cycles, minor delays between package # extractions, and worst-case an infinite loop with a certain faulty # INDEX file. # local mark= f_getvar _mark_$varpkg mark && [ "$mark" = "X" ] && return $SUCCESS local dep vardep rundeps= f_getvar _rundeps_$varpkg rundeps for dep in $rundeps; do f_str2varname "$dep" vardep # Skip dependency if already installed mark= f_getvar _mark_$vardep mark && [ "$mark" = "X" ] && continue # Just as-in the user-interface (opposed to scripted-use), only # allow packages with at least one category to be recognized. # local depcat= if ! f_getvar _categories_$vardep depcat || [ ! "$depcat" ] then $alert "$msg_required_package_not_found" "$dep" [ "$no_confirm" ] && sleep 2 fi f_package_add "$dep" retval=$? if [ $retval -ne $SUCCESS ]; then status=$(( $status | $retval )) # XXX package could be on a future disc volume # XXX (not supporting multiple disc volumes yet) $alert "$msg_loading_of_dependent_package_failed" \ "$dep" [ "$no_confirm" ] && sleep 2 fi done [ $status -eq $SUCCESS ] || return $status # # Done with the deps? Try to load the real m'coy. # f_package_extract device_media "$name" "$depended" retval=$? if [ $retval -ne $SUCCESS ]; then status=$(( $status | $retval )) else setvar _mark_$varpkg X fi return $status } # f_package_extract $device $name [$depended] # # Extract a package based on a namespec and media device. If $depended is # present and non-NULL, the notification displayed while installing the package # has "as a dependency" appended. # f_package_extract() { local funcname=f_package_extract local device="$1" name="$2" depended="$3" local devname= $device get name devname f_dprintf "$funcname: device=[%s] name=[%s] depended=[%s]" \ "$devname" "$name" "$depended" # Check to make sure it's not already there local varpkg mark= f_str2varname "$name" varpkg f_getvar _mark_$varpkg mark [ "$mark" = "X" ] && return $SUCCESS if ! f_device_init $device; then f_show_msg \ "$msg_unable_to_initialize_media_type_for_package_extract" return $FAILURE fi # If necessary, initialize the ldconfig hints [ -f "/var/run/ld-elf.so.hints" ] || f_quietly ldconfig /usr/lib /usr/lib/compat /usr/local/lib # Make a couple paranoid locations for temp # files to live if user specified none local tmpdir f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir f_quietly mkdir -p -m 1777 "$tmpdir" - local path + local path device_type + $device get type device_type case "$name" in */*) path="$name" ;; *) - case "$name" in - *-*|*_*) path="packages/All/$name" ;; - *) path="packages/Latest/$name" - esac + if [ "$device_type" = "$DEVICE_TYPE_HTTP" ]; then + path="$PKG_ABI/latest/All/$name" + else + path="packages/$PKG_ABI/All/$name" + fi esac - # We have a path, call the device strategy routine to get the file + # We have a path, call the device strategy routine to check the file local pkg_ext found= for pkg_ext in "" $PACKAGE_EXTENSIONS; do if f_device_get $device "$path$pkg_ext" $PROBE_EXIST; then path="$path$pkg_ext" - f_dprintf "$funcname: found path=[%s] dev=[%s]" \ - "$path" "$device" found=1 break + elif [ "$device_type" = "$DEVICE_TYPE_HTTP" ] && + f_device_get $device \ + "packages/$PKG_ABI/All/$name$pkg_ext" $PROBE_EXIST + then + # Mirroring physical media over HTTP + path="packages/$PKG_ABI/All/$name$pkg_ext" + found=1 + break fi done [ "$found" ] && f_dprintf "$funcname: found path=[%s] dev=[%s]" \ "$path" "$devname" local alert=f_show_msg no_confirm= f_getvar $VAR_NO_CONFIRM no_confirm [ "$no_confirm" ] && alert=f_show_info if [ ! "$found" ]; then f_dprintf "$funcname: No such %s file on %s device" \ "$path" "$devname" $alert "$msg_unable_to_fetch_package_from_selected_media" \ "$name" [ "$no_confirm" ] && sleep 2 return $FAILURE fi if [ "$depended" ]; then f_show_info "$msg_adding_package_as_a_dependency_from_media" \ "$name" "$devname" else f_show_info "$msg_adding_package_from_media" "$name" "$devname" fi - # Get package data and pipe into pkg_add(1) while providing feedback - { - if ! f_device_get $device "$path"; then - $alert "$msg_io_error_while_reading_in_the_package" \ - "$name" \ - >&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null - [ "$no_confirm" ] && sleep 2 - else - f_show_info \ - "$msg_package_read_successfully_waiting_for_pkg_add" \ - "$name" >&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null - fi - } | { - if f_debugging; then - /usr/sbin/pkg_add -v - - else - f_quietly /usr/sbin/pkg_add - - fi - } + # Request the package be added via pkg-install(8) + if f_debugging; then + f_eval_catch $funcname pkg 'pkg -d install -y "%s"' "$name" + else + f_eval_catch $funcname pkg 'pkg install -y "%s"' "$name" + fi if [ $? -ne $SUCCESS ]; then - $alert "$msg_pkg_add_apparently_did_not_like_the_package" \ + $alert "$msg_pkg_install_apparently_did_not_like_the_package" \ "$name" [ "$no_confirm" ] && sleep 2 else f_show_info "$msg_package_was_added_successfully" "$name" sleep 1 fi return $SUCCESS } # f_package_delete $name # # Delete package by full $name (lacks archive suffix; e.g., `.tbz'). # f_package_delete() { local funcname=f_package_delete local name="$1" if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; } then f_dprintf "packageDelete: %s" \ "$msg_no_package_name_passed_in_package_variable" return $FAILURE fi f_dprintf "$funcname: name=[%s]" "$name" [ "$name" ] || return $FAILURE { # Verify and initialize device media if-defined f_media_verify && f_device_init device_media && f_index_initialize packages/INDEX } || return $FAILURE # Now we have (indirectly via f_index_read()): # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} # PACKAGE_CATEGORIES _npkgs local varpkg f_str2varname "$name" varpkg # Just as-in the user-interface (opposed to scripted-use), only allow # packages with at least one category to be recognized. # local pkgcat= if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then # $pkg may be a partial name, search the index (this is slow) f_index_search PACKAGE_INDEX "$name" name if [ ! "$name" ]; then f_show_msg \ "$msg_sorry_package_was_not_found_in_the_index" \ "$name" return $FAILURE fi f_str2varname "$name" varpkg fi # If invoked through the scripted interface, we likely have not yet # detected the installed packages -- something we should do only once. # if [ ! "$PACKAGES_DETECTED" ]; then f_dprintf "$funcname: Detecting installed packages" f_package_detect_installed export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[] fi # Now we have: _mark_{varpkg}=X for all installed packages # # Return failure if the package is not already installed. # local pkgmark= f_getvar _mark_$varpkg pkgmark if ! [ "$pkgmark" -a ! "${pkgmark#[XUR]}" ]; then f_show_msg "$msg_package_not_installed_cannot_delete" "$name" return $FAILURE fi # # Check for dependencies # local pkgsel depc=0 udeps= for pkgsel in $SELECTED_PACKAGES; do local mark= f_str2varname $pkgsel varpkg debug= f_getvar _mark_$varpkg mark [ "$mark" -a ! "${mark#[XUR]}" ] || continue local dep rundeps= debug= f_getvar _rundeps_$varpkg rundeps for dep in $rundeps; do if [ "$dep" = "$name" ]; then # Maybe this package is marked for deletion too if [ "$mark" = "U" ]; then udeps="$udeps $pkgsel" else depc=$(( $depc + 1 )) fi break fi done done if [ $depc -gt 0 ]; then local grammatical_s= [ $depc -gt 1 ] && grammatical_s=s f_show_msg \ "$msg_package_is_needed_by_other_installed_packages" \ "$name" "$depc" "$grammatical_s" return $FAILURE fi # # Chase dependencies that are marked for uninstallation # for pkgsel in $udeps; do f_dprintf "$funcname: Uninstalling dependency %s (%s)" \ "$pkgsel" "marked for delete" f_package_delete "$pkgsel" done # # OK to perform the delete (no other packages depend on it)... # f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name" if f_debugging; then - pkg_delete -v "$name" + f_eval_catch $funcname pkg 'pkg -d delete -y "%s"' "$name" else - f_quietly pkg_delete "$name" + f_eval_catch $funcname pkg 'pkg delete -y "%s"' "$name" fi if [ $? -ne $SUCCESS ]; then f_show_msg "$msg_pkg_delete_failed" "$name" return $FAILURE else f_dprintf "$funcname: pkg-delete(8) of %s successful" "$name" f_str2varname "$name" varpkg setvar _mark_$varpkg "" fi } # f_package_reinstall $name # # A simple wrapper to f_package_delete() + f_package_add() # f_package_reinstall() { f_package_delete "$1" && f_package_add "$1" } ############################################################ MAIN f_dprintf "%s: Successfully loaded." packages/packages.subr fi # ! $_PACKAGES_PACKAGES_SUBR Index: stable/9/usr.sbin/bsdconfig/share/variable.subr =================================================================== --- stable/9/usr.sbin/bsdconfig/share/variable.subr (revision 267682) +++ stable/9/usr.sbin/bsdconfig/share/variable.subr (revision 267683) @@ -1,315 +1,315 @@ if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1 # # Copyright (c) 2012-2014 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." variable.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/strings.subr ############################################################ GLOBALS VARIABLES= # # Default behavior is to call f_variable_set_defaults() when loaded. # : ${VARIABLE_SELF_INITIALIZE=1} # # File to write when f_dump_variables() is called. # : ${VARIABLE_DUMPFILE:=/etc/bsdconfig.vars} ############################################################ FUNCTIONS # f_variable_new $handle $variable # # Register a new variable named $variable with the given reference-handle # $handle. The environment variable $handle is set to $variable allowing you to # use the f_getvar() function (from common.subr) with $handle to get the value # of environment variable $variable. For example: # # f_variable_new VAR_ABC abc # # allows the later indirection: # # f_getvar $VAR_ABC # # to return the value of environment variable `abc'. Variables registered in # this manner are recorded in the $VARIABLES environment variable for later # allowing dynamic enumeration of so-called `registered/advertised' variables. # f_variable_new() { local handle="$1" variable="$2" [ "$handle" ] || return $FAILURE f_dprintf "variable.subr: New variable %s -> %s" "$handle" "$variable" setvar $handle $variable VARIABLES="$VARIABLES${VARIABLES:+ }$handle" } # f_variable_get_value $var [ $fmt [ $opts ... ] ] # # Unless nonInteractive is set, prompt the user with a given value (pre-filled # with the value of $var) and give them the chance to change the value. # # Unlike f_getvar() (from common.subr) which can return a variable to the # caller on standard output, this function has no [meaningful] output. # # Returns success unless $var is either NULL or missing. # f_variable_get_value() { local var="$1" cp [ "$var" ] || return $FAILURE if ! { f_getvar $var cp && ! f_interactive; }; then shift 1 # var f_dialog_input cp "$( printf "$@" )" "$cp" && setvar $var "$cp" fi return $SUCCESS } # f_variable_set_defaults # # Installs sensible defaults for registered/advertised variables. # f_variable_set_defaults() { f_dprintf "f_variable_set_defaults: Initializing defaults..." # # Initialize various user-edittable values to their defaults # setvar $VAR_EDITOR "${EDITOR:-/usr/bin/ee}" setvar $VAR_FTP_STATE "auto" setvar $VAR_FTP_USER "ftp" setvar $VAR_HOSTNAME "$( hostname )" setvar $VAR_MEDIA_TIMEOUT "300" setvar $VAR_NFS_SECURE "NO" setvar $VAR_NFS_TCP "NO" setvar $VAR_NFS_V3 "YES" setvar $VAR_PKG_TMPDIR "/var/tmp" setvar $VAR_RELNAME "$UNAME_R" # # Debugging # if f_debugging; then local var for var in \ $VAR_EDITOR \ $VAR_FTP_STATE \ $VAR_FTP_USER \ $VAR_HOSTNAME \ $VAR_MEDIA_TIMEOUT \ $VAR_NFS_SECURE \ $VAR_NFS_TCP \ $VAR_NFS_V3 \ $VAR_PKG_TMPDIR \ $VAR_RELNAME \ ; do f_quietly f_getvar $var done fi f_dprintf "f_variable_set_defaults: Defaults initialized." } # f_dump_variables # # Dump a list of registered/advertised variables and their respective values to # $VARIABLE_DUMPFILE. Returns success unless the file couldn't be written. If # an error occurs, it is displayed using f_dialog_msgbox() (from dialog.subr). # f_dump_variables() { local err if ! err=$( ( for handle in $VARIABLES; do f_getvar $handle var || continue f_getvar $var value || continue f_shell_escape "$value" value printf "%s='%s'\n" "$var" "$value" done > "$VARIABLE_DUMPFILE" ) 2>&1 ); then f_dialog_msgbox "$err" return $FAILURE fi } # f_debugging # # Are we in debug mode? Returns success if extra DEBUG information has been # requested (by setting $debug to non-NULL), otherwise false. # f_debugging() { local value f_getvar $VAR_DEBUG value && [ "$value" ] } # f_interactive # # Are we running interactively? Return error if $nonInteractive is set and non- # NULL, otherwise return success. # f_interactive() { local value ! f_getvar $VAR_NONINTERACTIVE value || [ ! "$value" ] } # f_netinteractive # # Has the user specifically requested the network-portion of configuration and # setup to be performed interactively? Returns success if the user has asked # for the network configuration to be done interactively even if perhaps over- # all non-interactive mode has been requested (by setting nonInteractive). # # Returns success if $netInteractive is set and non-NULL. # f_netinteractive() { local value f_getvar $VAR_NETINTERACTIVE value && [ "$value" ] } -# f_zfsinteractive() +# f_zfsinteractive # # Has the user specifically requested the ZFS-portion of configuration and # setup to be performed interactively? Returns success if the user has asked # for the ZFS configuration to be done interactively even if perhaps overall # non-interactive mode has been requested (by setting nonInteractive). # # Returns success if $zfsInteractive is set and non-NULL. # f_zfsinteractive() { local value f_getvar $VAR_ZFSINTERACTIVE value && [ "$value" ] } ############################################################ MAIN # # Variables that can be tweaked from config files # # Handle Variable Name f_variable_new VAR_CONFIG_FILE configFile f_variable_new VAR_DEBUG debug f_variable_new VAR_DEBUG_FILE debugFile f_variable_new VAR_DIRECTORY_PATH _directoryPath f_variable_new VAR_DOMAINNAME domainname f_variable_new VAR_EDITOR editor f_variable_new VAR_EXTRAS ifconfig_ f_variable_new VAR_FTP_DIR ftpDirectory f_variable_new VAR_FTP_HOST ftpHost f_variable_new VAR_FTP_PASS ftpPass f_variable_new VAR_FTP_PATH _ftpPath f_variable_new VAR_FTP_PORT ftpPort f_variable_new VAR_FTP_STATE ftpState f_variable_new VAR_FTP_USER ftpUser f_variable_new VAR_GATEWAY defaultrouter f_variable_new VAR_GROUP group f_variable_new VAR_GROUP_GID groupGid f_variable_new VAR_GROUP_MEMBERS groupMembers f_variable_new VAR_GROUP_PASSWORD groupPassword f_variable_new VAR_HOSTNAME hostname f_variable_new VAR_HTTP_DIR httpDirectory f_variable_new VAR_HTTP_FTP_MODE httpFtpMode f_variable_new VAR_HTTP_HOST httpHost f_variable_new VAR_HTTP_PATH _httpPath f_variable_new VAR_HTTP_PORT httpPort f_variable_new VAR_HTTP_PROXY httpProxy f_variable_new VAR_HTTP_PROXY_HOST httpProxyHost f_variable_new VAR_HTTP_PROXY_PATH _httpProxyPath f_variable_new VAR_HTTP_PROXY_PORT httpProxyPort f_variable_new VAR_IFCONFIG ifconfig_ f_variable_new VAR_IPADDR ipaddr f_variable_new VAR_IPV6ADDR ipv6addr f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces f_variable_new VAR_KEYMAP keymap f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT f_variable_new VAR_MEDIA_TYPE mediaType f_variable_new VAR_NAMESERVER nameserver f_variable_new VAR_NETINTERACTIVE netInteractive f_variable_new VAR_NETMASK netmask f_variable_new VAR_NETWORK_DEVICE netDev f_variable_new VAR_NFS_HOST nfsHost f_variable_new VAR_NFS_PATH nfsPath f_variable_new VAR_NFS_SECURE nfs_reserved_port_only f_variable_new VAR_NFS_TCP nfs_use_tcp f_variable_new VAR_NFS_V3 nfs_use_v3 f_variable_new VAR_NONINTERACTIVE nonInteractive f_variable_new VAR_NO_CONFIRM noConfirm f_variable_new VAR_NO_ERROR noError f_variable_new VAR_NO_INET6 noInet6 f_variable_new VAR_PACKAGE package f_variable_new VAR_PKG_TMPDIR PKG_TMPDIR f_variable_new VAR_PORTS_PATH ports f_variable_new VAR_RELNAME releaseName f_variable_new VAR_SLOW_ETHER slowEthernetCard f_variable_new VAR_TRY_DHCP tryDHCP f_variable_new VAR_TRY_RTSOL tryRTSOL f_variable_new VAR_UFS_PATH ufs f_variable_new VAR_USER user f_variable_new VAR_USER_ACCOUNT_EXPIRE userAccountExpire f_variable_new VAR_USER_DOTFILES_CREATE userDotfilesCreate f_variable_new VAR_USER_GECOS userGecos f_variable_new VAR_USER_GID userGid f_variable_new VAR_USER_GROUPS userGroups f_variable_new VAR_USER_GROUP_DELETE userGroupDelete f_variable_new VAR_USER_HOME userHome f_variable_new VAR_USER_HOME_CREATE userHomeCreate f_variable_new VAR_USER_HOME_DELETE userHomeDelete f_variable_new VAR_USER_LOGIN_CLASS userLoginClass f_variable_new VAR_USER_PASSWORD userPassword f_variable_new VAR_USER_PASSWORD_EXPIRE userPasswordExpire f_variable_new VAR_USER_SHELL userShell f_variable_new VAR_USER_UID userUid f_variable_new VAR_ZFSINTERACTIVE zfsInteractive # # Self-initialize unless requested otherwise # f_dprintf "%s: VARIABLE_SELF_INITIALIZE=[%s]" \ variable.subr "$VARIABLE_SELF_INITIALIZE" case "$VARIABLE_SELF_INITIALIZE" in ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; *) f_variable_set_defaults esac f_dprintf "%s: Successfully loaded." variable.subr fi # ! $_VARIABLE_SUBR Index: stable/9/usr.sbin/bsdconfig =================================================================== --- stable/9/usr.sbin/bsdconfig (revision 267682) +++ stable/9/usr.sbin/bsdconfig (revision 267683) Property changes on: stable/9/usr.sbin/bsdconfig ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.sbin/bsdconfig:r257795,257817,257819,257937-257938,258264-258265,258267,258854,259113,259427