From owner-svn-src-all@FreeBSD.ORG Sun Jun 23 10:48:28 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 45D7733F; Sun, 23 Jun 2013 10:48:28 +0000 (UTC) (envelope-from dteske@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 36D751840; Sun, 23 Jun 2013 10:48:28 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r5NAmSNA002682; Sun, 23 Jun 2013 10:48:28 GMT (envelope-from dteske@svn.freebsd.org) Received: (from dteske@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r5NAmQA8002673; Sun, 23 Jun 2013 10:48:26 GMT (envelope-from dteske@svn.freebsd.org) Message-Id: <201306231048.r5NAmQA8002673@svn.freebsd.org> From: Devin Teske Date: Sun, 23 Jun 2013 10:48:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r252112 - in head/usr.sbin/bsdconfig: include share share/media X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Jun 2013 10:48:28 -0000 Author: dteske Date: Sun Jun 23 10:48:26 2013 New Revision: 252112 URL: http://svnweb.freebsd.org/changeset/base/252112 Log: Merge r248313 from stable/9 sysinstall(8) to head bsdconfig(8): Add support for installation directly via HTTP. While we're here, remove the menu-item for Passive FTP (since moving to ftp(1) and switching FTPMODE to `auto' by default -- see r251613 -- the single remaining FTP menu-item works for both ftp.f.o and ftp-archive.f.o; previously each requiring separately active versus passive both work with the `auto' setting). In scripting you still have mediaSetFTPActive and mediaSetFTPPassive but the remaining FTP menu-item uses mediaSetFTP which defaults to `auto' (aforementioned SVN r251613). Added: head/usr.sbin/bsdconfig/share/media/http.subr (contents, props changed) Modified: head/usr.sbin/bsdconfig/include/media.hlp head/usr.sbin/bsdconfig/include/messages.subr head/usr.sbin/bsdconfig/share/device.subr head/usr.sbin/bsdconfig/share/media/Makefile head/usr.sbin/bsdconfig/share/media/any.subr head/usr.sbin/bsdconfig/share/media/options.subr head/usr.sbin/bsdconfig/share/script.subr head/usr.sbin/bsdconfig/share/variable.subr Modified: head/usr.sbin/bsdconfig/include/media.hlp ============================================================================== --- head/usr.sbin/bsdconfig/include/media.hlp Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/include/media.hlp Sun Jun 23 10:48:26 2013 (r252112) @@ -25,13 +25,11 @@ You can install from the following types FTP Get the distribution files from an anonymous ftp server (you will be presented with a list). Please note that - you may invoke FTP in "Active" mode, "Passive" mode, or + you may invoke FTP in "Active"/"Passive" auto-mode, or via an HTTP proxy. - Active mode is the standard way of fetching files and - Passive mode is for use when you're behind a firewall or - some other security mechanism that blocks active FTP - connections. Using an HTTP proxy is sometimes necessary + By default, ftp(1) will automatically use the best mode + for the server. Using an HTTP proxy is sometimes necessary for firewalls which block all FTP connections. If you chose to enter your own URL in the FTP menu, please @@ -41,6 +39,14 @@ You can install from the following types Options screen. + HTTP Direct + Get the distribution files directly from an HTTP server. + + If you chose to enter your own URL in the HTTP Direct menu, + please note that all paths are *relative* to the root + directory of the web server. + + NFS Get the distribution files from an NFS server somewhere (make sure that permissions on the server allow this!). If this install method hangs on you or refuses to work Modified: head/usr.sbin/bsdconfig/include/messages.subr ============================================================================== --- head/usr.sbin/bsdconfig/include/messages.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/include/messages.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -87,6 +87,7 @@ msg_could_not_unmount_the_nfs_partition= 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_croatia="Croatia" @@ -148,7 +149,7 @@ msg_hebrew_desc="Ported software for Heb 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="HTTP" +msg_http_direct="HTTP Direct" msg_http_proxy="HTTP Proxy" msg_hungarian_desc="Ported software for the Hungarian market." msg_hungary="Hungary" @@ -161,6 +162,7 @@ msg_install_from_a_usb_drive="Install fr 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" @@ -270,6 +272,7 @@ msg_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." @@ -280,6 +283,7 @@ msg_please_specify_the_name_of_the_text_ 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." @@ -302,6 +306,7 @@ 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" @@ -334,6 +339,7 @@ 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." Modified: head/usr.sbin/bsdconfig/share/device.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/device.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/device.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -73,6 +73,7 @@ setvar DEVICE_TYPE_UFS 9 setvar DEVICE_TYPE_NFS 10 setvar DEVICE_TYPE_ANY 11 setvar DEVICE_TYPE_HTTP_PROXY 12 +setvar DEVICE_TYPE_HTTP 13 # # Default behavior is to call f_device_get_all() automatically when loaded. Modified: head/usr.sbin/bsdconfig/share/media/Makefile ============================================================================== --- head/usr.sbin/bsdconfig/share/media/Makefile Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/media/Makefile Sun Jun 23 10:48:26 2013 (r252112) @@ -4,8 +4,8 @@ NO_OBJ= FILESDIR= ${SHAREDIR}/bsdconfig/media FILES= any.subr cdrom.subr common.subr directory.subr dos.subr \ - floppy.subr ftp.subr httpproxy.subr network.subr nfs.subr \ - options.subr tcpip.subr ufs.subr usb.subr + floppy.subr ftp.subr http.subr httpproxy.subr network.subr \ + nfs.subr options.subr tcpip.subr ufs.subr usb.subr beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} Modified: head/usr.sbin/bsdconfig/share/media/any.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/media/any.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/media/any.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -37,6 +37,7 @@ f_include $BSDCFG_SHARE/media/directory. f_include $BSDCFG_SHARE/media/dos.subr f_include $BSDCFG_SHARE/media/floppy.subr f_include $BSDCFG_SHARE/media/ftp.subr +f_include $BSDCFG_SHARE/media/http.subr f_include $BSDCFG_SHARE/media/httpproxy.subr f_include $BSDCFG_SHARE/media/nfs.subr f_include $BSDCFG_SHARE/media/options.subr @@ -71,9 +72,9 @@ f_media_get_type() local menu_list=" '1 $msg_cd_dvd' '$msg_install_from_a_freebsd_cd_dvd' '2 $msg_ftp' '$msg_install_from_an_ftp_server' - '3 $msg_ftp_passive' - '$msg_install_from_an_ftp_server_thru_firewall' - '4 $msg_http' '$msg_install_from_an_ftp_server_thru_proxy' + '3 $msg_http_proxy' + '$msg_install_from_an_ftp_server_thru_proxy' + '4 $msg_http_direct' '$msg_install_from_an_http_server' '5 $msg_directory' '$msg_install_from_the_existing_filesystem' '6 $msg_nfs' '$msg_install_over_nfs' '7 $msg_dos' '$msg_install_from_a_dos_partition' @@ -123,8 +124,8 @@ f_media_get_type() case "$mtag" in ?" $msg_cd_dvd") f_media_set_cdrom ;; ?" $msg_ftp") f_media_set_ftp ;; - ?" $msg_ftp_passive") f_media_set_ftp_passive ;; - ?" $msg_http") f_media_set_http_proxy ;; + ?" $msg_http_proxy") f_media_set_http_proxy ;; + ?" $msg_http_direct") f_media_set_http ;; ?" $msg_directory") f_media_set_directory ;; ?" $msg_dos") f_media_set_dos ;; ?" $msg_nfs") f_media_set_nfs ;; Added: head/usr.sbin/bsdconfig/share/media/http.subr ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/bsdconfig/share/media/http.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -0,0 +1,635 @@ +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 (INLUDING, 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=" + '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 $FAILURE + 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 $SUCCESS +} + +# 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 network + if ! f_device_select_tcp; then + unset $VAR_HTTP_PATH + return $FAILURE + fi + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + if ! f_device_init 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 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 f_media_shutdown_http + device_http set private 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 + 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" + + # + # 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) + setvar $VAR_HTTP_PATH "$VAR_HTTP_DIR" + 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 + esac + + [ $http_found -eq $SUCCESS ] && break + + f_getvar $VAR_HTTP_PATH http_path + f_show_msg "$msg_please_check_the_url_and_try_again" \ + "$http_path" + + unset $VAR_HTTP_PATH + f_media_set_http || break + done + + return $http_found +} + +# f_media_get_http $device $file [$probe_only] +# +# 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_only 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). +# +# 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_only="$3" hosts= + + f_dprintf "f_media_get_http: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + 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_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 + local url="/$http_path/$file" rx + + f_dprintf "sending http request for: %s" "$url" + 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 + while read LINE; do + case "$LINE" in + HTTP*) + f_dprintf "received response: %s" "$LINE" + set -- $LINE; rv=$2 + f_isinteger "$rv" || rv=0 + ;; + *) + [ "${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_only" ]; then + cat # output the rest ``as-is'' + fi + exit 200 + ) + local retval=$? + [ $retval -eq 200 ] && return $SUCCESS + [ "$probe_only" ] && 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 +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/http.subr + +fi # ! $_MEDIA_HTTP_SUBR Modified: head/usr.sbin/bsdconfig/share/media/options.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/media/options.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/media/options.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -158,14 +158,15 @@ f_media_options_menu() case "$cp" in $DEVICE_TYPE_UFS|$DEVICE_TYPE_DISK) cp="$msg_file_system" ;; - $DEVICE_TYPE_DIRECTORY) cp="$msg_directory" ;; - $DEVICE_TYPE_FLOPPY) cp="$msg_floppy" ;; - $DEVICE_TYPE_FTP) cp="$msg_ftp" ;; - $DEVICE_TYPE_HTTP_PROXY) cp="$msg_http_proxy" ;; - $DEVICE_TYPE_CDROM) cp="$msg_cdrom" ;; - $DEVICE_TYPE_USB) cp="$msg_usb" ;; - $DEVICE_TYPE_DOS) cp="$msg_dos" ;; - $DEVICE_TYPE_NFS) cp="$msg_nfs" ;; + $DEVICE_TYPE_DIRECTORY) cp="$msg_directory" ;; + $DEVICE_TYPE_FLOPPY) cp="$msg_floppy" ;; + $DEVICE_TYPE_FTP) cp="$msg_ftp" ;; + $DEVICE_TYPE_HTTP_PROXY) cp="$msg_http_proxy" ;; + $DEVICE_TYPE_HTTP) cp="$msg_http_direct" ;; + $DEVICE_TYPE_CDROM) cp="$msg_cdrom" ;; + $DEVICE_TYPE_USB) cp="$msg_usb" ;; + $DEVICE_TYPE_DOS) cp="$msg_dos" ;; + $DEVICE_TYPE_NFS) cp="$msg_nfs" ;; *) cp="<$msg_unknown>" esac Modified: head/usr.sbin/bsdconfig/share/script.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/script.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/script.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -181,8 +181,10 @@ f_resword_new mediaSetFTPActive f_media f_resword_new mediaSetFTPPassive f_media_set_ftp_passive f_resword_new mediaSetFTPUserPass f_media_set_ftp_userpass +# media/http.subr +f_resword_new mediaSetHTTP f_media_set_http + # media/httpproxy.subr -f_resword_new mediaSetHTTP f_media_set_http_proxy f_resword_new mediaSetHTTPProxy f_media_set_http_proxy # packages/packages.subr Modified: head/usr.sbin/bsdconfig/share/variable.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/variable.subr Sun Jun 23 10:16:14 2013 (r252111) +++ head/usr.sbin/bsdconfig/share/variable.subr Sun Jun 23 10:48:26 2013 (r252112) @@ -204,7 +204,11 @@ f_variable_new VAR_FTP_STATE ftpState f_variable_new VAR_FTP_USER ftpUser f_variable_new VAR_GATEWAY defaultrouter 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