diff options
author | dteske <dteske@FreeBSD.org> | 2013-02-25 19:55:32 +0000 |
---|---|---|
committer | dteske <dteske@FreeBSD.org> | 2013-02-25 19:55:32 +0000 |
commit | 1f658c88bed0f72839a6caee6fdc9731cfd3a516 (patch) | |
tree | cd0ba840ab0526258652c2740f9e0c046edb8374 /usr.sbin | |
parent | 66bd226a8bcd9c32e76c9a7c414af10c393e50d8 (diff) | |
download | FreeBSD-src-1f658c88bed0f72839a6caee6fdc9731cfd3a516.zip FreeBSD-src-1f658c88bed0f72839a6caee6fdc9731cfd3a516.tar.gz |
Import media selection/preparation framework (sysinstall inspired). Makes
accessing files from various types of media nice and abstracted away from
the wet-work involved in preparing, validating, and initializing those
types of media. This will be used for the package management system module
and other modules that need access to files and want to allow the user to
decide where those files come from (either in a scripted fashion, prompted
fashion, or any combination thereof).
Heavily inspired by sysinstall and even uses the same reserved words so
that scripts are portable. Coded over months, tested continuously through-
out, and reviewed several times.
Some notes about the changes:
- Move network-setting acquisition/validation routines to media/tcpip.subr
- The options screen from sysinstall has been converted to a dialog menu
- The "UFS" media choice is renamed to "Directory" to reflect how sysinstall
treats the choice and a new [true] "UFS" media choice has been added that
acts on real UFS partitions (such as external disks with disklabels).
- Many more help files have been resurrected from sysinstall (I noticed that
some of the content seems a bit dated; I gave them a once-over but they
could really use an update).
- A total of 10 media choices are presented (via mediaGetType) including:
CD/DVD, FTP, FTP Passive, HTTP Proxy, Directory, NFS, DOS, UFS, Floppy, USB
- Novel struct/device management layer for managing the issue of passing
more information than can comfortably fit in an argument list.
Diffstat (limited to 'usr.sbin')
37 files changed, 6766 insertions, 553 deletions
diff --git a/usr.sbin/bsdconfig/include/Makefile b/usr.sbin/bsdconfig/include/Makefile index cb4b1b6..ee21cec 100644 --- a/usr.sbin/bsdconfig/include/Makefile +++ b/usr.sbin/bsdconfig/include/Makefile @@ -3,7 +3,8 @@ NO_OBJ= FILESDIR= ${LIBEXECDIR}/bsdconfig/include -FILES= bsdconfig.hlp messages.subr usage.hlp +FILES= bsdconfig.hlp media.hlp messages.subr network_device.hlp \ + options.hlp tcp.hlp usage.hlp beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/include/media.hlp b/usr.sbin/bsdconfig/include/media.hlp new file mode 100644 index 0000000..6df5b03 --- /dev/null +++ b/usr.sbin/bsdconfig/include/media.hlp @@ -0,0 +1,48 @@ +You can install from the following types of media: + + CDROM requires one of the following supported CDROM drives: + ATAPI - Any standard ATAPI CDROM drive hooked to + a supported controller (see Hardware Guide). + SCSI - Any standard SCSI CDROM drive hooked to + a supported controller (see Hardware Guide). + + + DOS A DOS primary partition with the required FreeBSD + distribution files copied onto it (e.g. C:\FREEBSD\) + + + UFS Assuming a disk or partition with an existing + FreeBSD file system and distribution set on it, + get the distribution files from there. + + + Floppy Get distribution files from one or more DOS or UFS + formatted floppies. Such floppies are assumed to + contain the appropriate distribution pieces - see + ABOUT.TXT for more information about making floppy + distribution media. + + + 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 + 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 + for firewalls which block all FTP connections. + + If you chose to enter your own URL in the FTP menu, please + note that all paths are *relative* to the home directory + of the user being logged in as. By default, this is the + user "ftp" (anonymous ftp) but you may change this in the + Options screen. + + + 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 + properly, you may need to set some special options for + your NFS server. See the Options screen for more details. diff --git a/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr index dc7c246..82afb6d 100644 --- a/usr.sbin/bsdconfig/include/messages.subr +++ b/usr.sbin/bsdconfig/include/messages.subr @@ -1,5 +1,5 @@ # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,39 +27,251 @@ field_username="Username:" field_password="Password:" +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_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types" +msg_accept_continue="Accept/Continue" msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s" +msg_argentina="Argentina" +msg_assume_network_is_already_configured="Running multi-user, assume that the network is already configured?" +msg_attempt_automatic_dhcp_configuration="Attempt automatic DHCP configuration of interfaces" +msg_attempt_ipv6_configuration_of_interfaces="Attempt IPv6 configuration of interfaces" +msg_australia="Australia" +msg_austria="Austria" msg_becoming_root_via_sudo="Becoming root via sudo(8)..." +msg_brazil="Brazil" +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_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_partition="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_configuration_for_interface="Configuration for Interface" +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_proxy="Couldn't connect to proxy" +msg_couldnt_connect_to_ftp_server="Couldn't connect to FTP server" +msg_couldnt_open_ftp_connection="Couldn't open FTP connection to %s:\n %s." msg_created_path="Created %s" +msg_croatia="Croatia" +msg_czech_republic="Czech Republic" +msg_debugging="Debugging" +msg_denmark="Denmark" +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 <up>/<down> 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_done="Done" +msg_dos="DOS" +msg_editor="Editor" +msg_emit_extra_debugging_output="Emit extra debugging output" +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_finland="Finland" +msg_floppy="Floppy" +msg_france="France" +msg_ftp="FTP" +msg_ftp_passive="FTP Passive" +msg_ftp_username="FTP username" +msg_germany="Germany" +msg_greece="Greece" +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_proxy="HTTP Proxy" +msg_hungary="Hungary" +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_usb_drive="Install from a USB drive" +msg_install_from_a_ufs_partition="Install from a UFS partition" +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_the_existing_filesystem="Install from the existing filesystem" +msg_install_over_nfs="Install over NFS" +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_ipv4_address="IPv4 Address" +msg_ipv4_gateway="IPv4 Gateway" +msg_ipv6="IPv6" +msg_ipv6_ready="IPv6 ready" +msg_ireland="Ireland" +msg_israel="Israel" +msg_italy="Italy" +msg_japan="Japan" +msg_korea="Korea" +msg_lithuania="Lithuania" +msg_length_of_specified_url_is_too_long="Length of specified URL is %u characters. Allowable maximum is %u." +msg_logging_in_to_user_at_host="Logging in to %s@%s.." +msg_looking_up_host="Looking up host %s" msg_main_menu="Main Menu" +msg_main_site="Main Site" +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_missing_ftp_host_or_directory="Missing FTP host or directory specification. FTP media not initialized." 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_device_init_failed="Net device init failed." +msg_netmask="Netmask" +msg_netherlands="Netherlands" +msg_network_configuration="Network Configuration" +msg_network_interface_information_required="Network interface information required" 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_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_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_permission_denied="%s: %s: Permission denied" +msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again." msg_please_enter_password="Please enter your password for sudo(8):" msg_please_enter_username_password="Please enter a username and 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_insert_floppy_in_drive="Please insert floppy in %s" +msg_please_insert_floppy_containing="Please insert floppy containing %s in %s" +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_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_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_select_a_usb_drive="You have more than one USB drive. Please choose which drive\nyou would like to use." +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_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://<hostname>/<path>\nWhere <path> is relative to the anonymous ftp directory or the\nhome directory of the user being logged in as." +msg_poland="Poland" +msg_portugal="Portugal" msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors" +msg_primary="Primary" +msg_probing_devices_please_wait_this_can_take_a_while="Probing devices, please wait (this can take a while)..." msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu system" +msg_release_name="Release Name" +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_romania="Romania" +msg_russia="Russia" +msg_scanning_for_dhcp_servers="Scanning for DHCP servers..." +msg_scanning_for_ra_servers="Scanning for RA servers..." msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!" msg_secure_mode_requires_root="Secure-mode requires root-access!" +msg_select_a_site_thats_close="Select a site that's close!" +msg_server_error_when_requesting_url="Server error when requesting %s, you could try an other server" +msg_singapore="Singapore" +msg_slovak_republic="Slovak Republic" +msg_slovenia="Slovenia" +msg_snapshots_server_japan="Snapshots Server Japan" +msg_snapshots_server_sweden="Snapshots Server Sweden" +msg_sorry_invalid_url="Sorry, %s is an invalid URL!" msg_sorry_try_again="Sorry, try again." +msg_south_africa="South Africa" +msg_spain="Spain" +msg_specify_some_other_ftp_site="Specify some other ftp site by URL" +msg_sweden="Sweden" +msg_switzerland="Switzerland" +msg_taiwan="Taiwan" +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_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_turkey="Turkey" +msg_ufs="UFS" +msg_uk="UK" +msg_ukraine="Ukraine" +msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used." +msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized." +msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!" msg_unable_to_open="Unable to open %s" +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_view_set_various_media_options="View/Set various media options" +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_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?" msg_yes="Yes" 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?" +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" diff --git a/usr.sbin/bsdconfig/include/network_device.hlp b/usr.sbin/bsdconfig/include/network_device.hlp new file mode 100644 index 0000000..affa86a --- /dev/null +++ b/usr.sbin/bsdconfig/include/network_device.hlp @@ -0,0 +1,58 @@ +You can do network installations over 3 types of communications links: + + Serial port: SLIP / PPP + Parallel port: PLIP (laplink cable) + Ethernet: A standard Ethernet controller (includes some + PCMCIA networking cards). + +SLIP support is rather primitive and limited primarily to directly +connected links, such as a serial cable running between a laptop +computer and another PC. The link must be hard-wired as the SLIP +installation doesn't currently offer a dialing capability (that +facility is offered by the PPP utility, which should be used in +preference to SLIP whenever possible). When you choose the SLIP +option, you'll be given the option of later editing the slattach +command before it's run on the serial line. It is expected that +you'll run slattach (or some equivalent command) on the other end of +the link at that time and bring up the line. FreeBSD will then +install itself at serial speeds of up to 115.2K/baud (the recommended +speed for a hardwired cable). + +If you're using a modem then PPP is almost certainly your only choice. +Make sure that you have your service provider's information handy as +you'll need to know it fairly early in the installation process. You +will need to know your service provider's IP address, the IP address +of your provider's DNS server, and possibly your own IP address unless +your ISP supports dynamic negotiation, most do. If you do not choose +a PAP or CHAP login you will also need to know how to use the various +"AT commands" to dial the ISP with your particular brand of modem as +the PPP dialer provides only a very simple terminal emulator and has no +"modem capabilities database". If you choose a PAP or CHAP login you +can simply enter `dial' (without the quotes) at the ppp prompt if your +modem uses the Hayes compatible AT command set. + +If a hard-wired connection to another FreeBSD (2.0R or later) machine +is available, you might also consider installing over a "laplink" +parallel port cable. The data rate over the parallel port is much +higher than what is typically possible over a serial line, and speeds +of over 50KB/sec are not uncommon. + +Finally, for the fastest possible network installation, an Ethernet +adaptor is always a good choice! FreeBSD supports most common PC +Ethernet cards, a table of which is provided in the FreeBSD Hardware +Guide (see the `Documentation' entry in the main menu). If you are +using one of the supported PCMCIA Ethernet cards, also be sure that +it's plugged in BEFORE the laptop is powered on! Sysinstall does not, +unfortunately, currently support "hot insertion" of PCMCIA cards. + +You will also need to know your IP address on the network, the +"netmask" value for your address class, and the name of your machine. +Your system administrator can tell you which values to use for your +particular network setup. If you will be referring to other hosts by +name rather than IP address, you'll also need a name server and +possibly the address of a gateway (if you're using PPP, it's your +provider's IP address) to use in talking to it. If you do not know +the answers to all or most of these questions then you should really +probably talk to your system administrator FIRST before trying this +type of installation! Choosing the wrong IP address on a busy network +will NOT make you popular with your systems administrator! :-) diff --git a/usr.sbin/bsdconfig/include/options.hlp b/usr.sbin/bsdconfig/include/options.hlp new file mode 100644 index 0000000..674e48d --- /dev/null +++ b/usr.sbin/bsdconfig/include/options.hlp @@ -0,0 +1,98 @@ +The following options may be set from this screen. + +NFS Secure: NFS server talks only on a secure port + + This is most commonly used when talking to Sun workstations, which + will not talk NFS over "non privileged" ports. + + +NFS Slow: User is using a slow PC or Ethernet card + + Use this option if you have a slow PC (386) or an Ethernet card + with poor performance being "fed" by NFS on a higher-performance + workstation. This will throttle the workstation back to prevent + the PC from becoming swamped with data. + + +NFS TCP: Use TCP for the NFS mount + + This option can be used if your NFS server supports TCP + connections; not all do! This may be useful if your NFS server + is at a remote site in which case it may offer some additional + stability. + + +NFS version 3: Use NFS version 3 + + This option forces the use of NFS version 3 and is on by default. + If your NFS server only supports NFS version 2, disable this option. + + +Debugging: Turn on the extra debugging flag + + This turns on a lot of extra noise in between dialogs (unless + debugFile has been set, sending the data to a logfile instead). + Optionally, if debugFile begins with a plus sign (`+'), output will + occur both on standard output and to debugFile (minus leading plus). + If your installation should fail for any reason, PLEASE turn this + flag on when attempting to reproduce the problem. It will provide a + lot of extra debugging at the failure point and may be very helpful + to the developers in tracking such problems down! + + +DHCP: Enable DHCP configuration of interfaces + + This option specifies whether DHCP configuration of interfaces + may be attempted. The default setting is to interactively ask + the user. + + +IPv6: Enable IPv6 router solicitation configuration + + This option specifies whether automatic configuration of IPv6 + interfaces may be attempted. This uses the router solicitation + method of automatic configuration. The default setting is to + interactively ask the user. + + +FTP username: Specify username and password instead of anonymous. + + By default, the installation attempts to log in as the + anonymous user. If you wish to log in as someone else, + specify the username and password with this option. + + +Editor: Specify which screen editor to use. + + At various points during the installation it may be necessary + to customize some text file, at which point the user will be + thrown unceremoniously into a screen editor. A relatively + simplistic editor which shows its command set on-screen is + selected by default, but UNIX purists may wish to change this + setting to `/usr/bin/vi'. + + +Release Name: Which release to attempt to load from installation media. + + You should only change this option if you're really sure you know + what you are doing! This will change the release name used by + bsdconfig when fetching components of any distributions, and + is a useful way of using a more recent installation boot floppy + with an older release (say, on CDROM). + + +Media Type: Which media type is being used. + + This is mostly informational and indicates which media type (if any) + was last selected in the Media menu. It's also a convenient short-cut + to the media menu itself. + + +Re-scan Devices: + + Reprobe the system for devices. + + +Use Defaults: Use default values. + + Reset all options back to their default values. diff --git a/usr.sbin/bsdconfig/networking/include/tcp.hlp b/usr.sbin/bsdconfig/include/tcp.hlp index 6d0ba10..6d0ba10 100644 --- a/usr.sbin/bsdconfig/networking/include/tcp.hlp +++ b/usr.sbin/bsdconfig/include/tcp.hlp diff --git a/usr.sbin/bsdconfig/networking/devices b/usr.sbin/bsdconfig/networking/devices index 443294f..f9c27b4 100755 --- a/usr.sbin/bsdconfig/networking/devices +++ b/usr.sbin/bsdconfig/networking/devices @@ -1,6 +1,6 @@ #!/bin/sh #- -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ f_dprintf "%s: loading includes..." "$0" f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/mustberoot.subr f_include $BSDCFG_SHARE/sysrc.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/device.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr f_include $BSDCFG_SHARE/networking/media.subr diff --git a/usr.sbin/bsdconfig/networking/include/Makefile b/usr.sbin/bsdconfig/networking/include/Makefile index be6cacb..c93d486 100644 --- a/usr.sbin/bsdconfig/networking/include/Makefile +++ b/usr.sbin/bsdconfig/networking/include/Makefile @@ -3,7 +3,7 @@ NO_OBJ= FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking/include -FILES= messages.subr tcp.hlp +FILES= messages.subr beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/networking/share/common.subr b/usr.sbin/bsdconfig/networking/share/common.subr index e501a9c..1a37a9c 100644 --- a/usr.sbin/bsdconfig/networking/share/common.subr +++ b/usr.sbin/bsdconfig/networking/share/common.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_COMMON_SUBR" ]; then _NETWORKING_COMMON_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,17 +33,6 @@ BSDCFG_SHARE="/usr/share/bsdconfig" ############################################################ FUNCTIONS -# f_mounted $local_directory -# -# Return success if a filesystem is mounted on a particular directory. -# -f_mounted() -{ - local dir="$1" - [ -d "$dir" ] || return $FAILURE - mount | grep -Eq " on $dir \([^)]+\)$" -} - # f_jailed # # Returns true if the current process is jail(8)ed. diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr index 23ac83b..cac8ef5 100644 --- a/usr.sbin/bsdconfig/networking/share/device.subr +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,8 +31,10 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1 BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." networking/device.subr +f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/sysrc.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr f_include $BSDCFG_SHARE/networking/media.subr @@ -43,8 +45,6 @@ f_include $BSDCFG_SHARE/networking/routing.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking" f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr -TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp - ############################################################ GLOBALS # @@ -55,133 +55,6 @@ TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp ############################################################ FUNCTIONS -# f_device_desc $device_name -# -# Print a description for a device name (eg., `fxp0'). -# -f_device_desc() -{ - local device="$1" d="[1234567890]" desc="" - - # Check variables - [ "$device" ] || return $SUCCESS - - # - # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, - # otherwise fall through to below static list. - # - if f_have sysctl; then - local devname devunit - devname="${device%%$d*}" - devunit="${device#$devname}" - devunit="${devunit%%[a-zA-Z_]*}" - sysctl -n "dev.$devname.$devunit.%desc" 2> /dev/null && - return $SUCCESS - fi - - case "$device" in - # Network devices - ae$d) desc="Attansic/Atheros L2 Fast Ethernet";; - age$d) desc="Attansic/Atheros L1 Gigabit Ethernet";; - alc$d) desc="Atheros AR8131/AR8132 PCIe Ethernet";; - ale$d) desc="Atheros AR8121/AR8113/AR8114 PCIe Ethernet";; - an$d) desc="Aironet 4500/4800 802.11 wireless adapter";; - ath$d) desc="Atheros IEEE 802.11 wireless adapter";; - aue$d) desc="ADMtek USB Ethernet adapter";; - axe$d) desc="ASIX Electronics USB Ethernet adapter";; - bce$d) desc="Broadcom NetXtreme II Gigabit Ethernet card";; - bfe$d) desc="Broadcom BCM440x PCI Ethernet card";; - bge$d) desc="Broadcom BCM570x PCI Gigabit Ethernet card";; - bm$d) desc="Apple BMAC Built-in Ethernet";; - bwn$d) desc="Broadcom BCM43xx IEEE 802.11 wireless adapter";; - cas$d) desc="Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet";; - cc3i$d) desc="SDL HSSI sync serial PCI card";; - cue$d) desc="CATC USB Ethernet adapter";; - cxgb$d) desc="Chelsio T3 10Gb Ethernet card";; - dc$d) desc="DEC/Intel 21143 (and clones) PCI Fast Ethernet card";; - de$d) desc="DEC DE435 PCI NIC or other DC21040-AA based card";; - disc$d) desc="Software discard network interface";; - ed$d) desc="Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA";; - el$d) desc="3Com 3C501 Ethernet card";; - em$d) desc="Intel(R) PRO/1000 Ethernet card";; - en$d) desc="Efficient Networks ATM PCI card";; - ep$d) desc="3Com 3C509 Ethernet card/3C589 PCMCIA";; - et$d) desc="Agere ET1310 based PCI Express Gigabit Ethernet card";; - ex$d) desc="Intel EtherExpress Pro/10 Ethernet card";; - fe$d) desc="Fujitsu MB86960A/MB86965A Ethernet card";; - fpa$d) desc="DEC DEFPA PCI FDDI card";; - fwe$d) desc="FireWire Ethernet emulation";; - fwip$d) desc="IP over FireWire";; - fxp$d) desc="Intel EtherExpress Pro/100B PCI Fast Ethernet card";; - gem$d) desc="Apple GMAC or Sun ERI/GEM Ethernet adapter";; - hme$d) desc="Sun HME (Happy Meal Ethernet) Ethernet adapter";; - ie$d) desc="AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210";; - igb$d) desc="Intel(R) PRO/1000 PCI Express Gigabit Ethernet card";; - ipw$d) desc="Intel PRO/Wireless 2100 IEEE 802.11 adapter";; - iwi$d) desc="Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter";; - iwn$d) desc="Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter";; - ix$d) desc="Intel Etherexpress Ethernet card";; - ixgb$d) desc="Intel(R) PRO/10Gb Ethernet card";; - ixgbe$d) desc="Intel(R) PRO/10Gb Ethernet card";; - jme$d) desc="JMicron JMC250 Gigabit/JMC260 Fast Ethernet";; - kue$d) desc="Kawasaki LSI USB Ethernet adapter";; - le$d) desc="AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter";; - lge$d) desc="Level 1 LXT1001 Gigabit Ethernet card";; - lnc$d) desc="Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet";; - lp$d) desc="Parallel Port IP (PLIP) peer connection";; - lo$d) desc="Loop-back (local) network interface";; - malo$d) desc="Marvell Libertas 88W8335 802.11 wireless adapter";; - msk$d) desc="Marvell/SysKonnect Yukon II Gigabit Ethernet";; - mxge$d) desc="Myricom Myri10GE 10Gb Ethernet card";; - nfe$d) desc="NVIDIA nForce MCP Ethernet";; - ng${d}_*|ng$d${d}_*|ng$d$d${d}_*|ng$d$d$d${d}_*|ng$d$d$d$d${d}_*) - desc="Vimage netgraph(4) bridged Ethernet device";; - nge$d) desc="NatSemi PCI Gigabit Ethernet card";; - nve$d) desc="NVIDIA nForce MCP Ethernet";; - nxge$d) desc="Neterion Xframe 10GbE Server/Storage adapter";; - pcn$d) desc="AMD Am79c79x PCI Ethernet card";; - plip$d) desc="Parallel Port IP (PLIP) peer connection";; - ral$d) desc="Ralink Technology IEEE 802.11 wireless adapter";; - ray$d) desc="Raytheon Raylink 802.11 wireless adapter";; - re$d) desc="RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter";; - rl$d) desc="RealTek 8129/8139 PCI Ethernet card";; - rue$d) desc="RealTek USB Ethernet card";; - rum$d) desc="Ralink Technology USB IEEE 802.11 wireless adapter";; - sf$d) desc="Adaptec AIC-6915 PCI Ethernet card";; - sge$d) desc="Silicon Integrated Systems SiS190/191 Ethernet";; - sis$d) desc="SiS 900/SiS 7016 PCI Ethernet card";; - sk$d) desc="SysKonnect PCI Gigabit Ethernet card";; - sn$d) desc="SMC/Megahertz Ethernet card";; - snc$d) desc="SONIC Ethernet card";; - sr$d) desc="SDL T1/E1 sync serial PCI card";; - ste$d) desc="Sundance ST201 PCI Ethernet card";; - stge$d) desc="Sundance/Tamarack TC9021 Gigabit Ethernet";; - ti$d) desc="Alteon Networks PCI Gigabit Ethernet card";; - tl$d) desc="Texas Instruments ThunderLAN PCI Ethernet card";; - tx$d) desc="SMC 9432TX Ethernet card";; - txp$d) desc="3Com 3cR990 Ethernet card";; - uath$d) desc="Atheros AR5005UG and AR5005UX USB wireless adapter";; - upgt$d) desc="Conexant/Intersil PrismGT USB wireless adapter";; - ural$d) desc="Ralink Technology RT2500USB 802.11 wireless adapter";; - urtw$d) desc="Realtek 8187L USB wireless adapter";; - vge$d) desc="VIA VT612x PCI Gigabit Ethernet card";; - vlan$d|vlan$d$d|vlan$d$d$d|vlan$d$d$d$d|vlan$d$d$d$d$d) - desc="IEEE 802.1Q VLAN network interface";; - vr$d) desc="VIA VT3043/VT86C100A Rhine PCI Ethernet card";; - vx$d) desc="3COM 3c590 / 3c595 Ethernet card";; - wb$d) desc="Winbond W89C840F PCI Ethernet card";; - wi$d) desc="Lucent WaveLAN/IEEE 802.11 wireless adapter";; - wpi$d) desc="Intel 3945ABG IEEE 802.11 wireless adapter";; - wx$d) desc="Intel Gigabit Ethernet (82452) card";; - xe$d) desc="Xircom/Intel EtherExpress Pro100/16 Ethernet card";; - xl$d) desc="3COM 3c90x / 3c90xB PCI Ethernet card";; - zyd$d) desc="ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter";; - # Unknown device - *) desc="<unknown network interface type>";; - esac - printf "%s\n" "$desc" -} - # f_dialog_menu_netdev # # Display a list of network devices with descriptions. diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr index b276059..61df2b4 100644 --- a/usr.sbin/bsdconfig/networking/share/hostname.subr +++ b/usr.sbin/bsdconfig/networking/share/hostname.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_HOSTNAME_SUBR" ]; then _NETWORKING_HOSTNAME_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -41,63 +41,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_validate_hostname $hostname -# -# Returns zero if the given argument (a fully-qualified hostname) is compliant -# with standards set-forth in RFC's 952 and 1123 of the Network Working Group: -# -# RFC 952 - DoD Internet host table specification -# http://tools.ietf.org/html/rfc952 -# -# RFC 1123 - Requirements for Internet Hosts - Application and Support -# http://tools.ietf.org/html/rfc1123 -# -# See http://en.wikipedia.org/wiki/Hostname for a brief overview. -# -# The return status for invalid hostnames is one of: -# 255 Entire hostname exceeds the maximum length of 255 characters. -# 63 One or more individual labels within the hostname (separated by -# dots) exceeds the maximum of 63 characters. -# 1 One or more individual labels within the hostname contains one -# or more invalid characters. -# 2 One or more individual labels within the hostname starts or -# ends with a hyphen (hyphens are allowed, but a label cannot -# begin or end with a hyphen). -# 3 One or more individual labels within the hostname are null. -# -# If the hostname is determined to be invalid, the appropriate error will be -# displayed using the f_show_msg function. -# -f_validate_hostname() -{ - local fqhn="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Return error if the hostname exceeds 255 characters - [ ${#fqhn} -gt 255 ] && exit 255 - - IFS="." # Split on `dot' - for label in $fqhn; do - - # Return error if the label exceeds 63 characters - [ ${#label} -gt 63 ] && exit 63 - - # Return error if the label is null - [ "$label" ] || exit 3 - - # Return error if label begins/ends with dash - case "$label" in - -*|*-) exit 2 - esac - - # Return error if the label contains any invalid chars - echo "$label" | grep -q '^[[:alnum:]-]*$' || exit 1 - - done - ) -} - # f_dialog_hnerror $error $hostname # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr index d5398e5..4b39dd2 100644 --- a/usr.sbin/bsdconfig/networking/share/ipaddr.subr +++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,75 +40,10 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_ifconfig_inet $interface -# -# Returns the IPv4 address associated with $interface. -# -f_ifconfig_inet() -{ - local interface="$1" - ifconfig "$interface" 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "inet" ) \ - { - print $2 - found = 1 - exit - } - END { exit ! found } - ' -} - -# f_validate_ipaddr $ipaddr -# -# Returns zero if the given argument (an IP address) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual octets within the IP address (separated -# by dots) contains one or more invalid characters. -# 2 One or more individual octets within the IP address are null -# and/or missing. -# 3 One or more individual octets within the IP address exceeds the -# maximum of 255 (or 2^8, being an octet comprised of 8 bits). -# 4 The IP address has either too few or too many octets. -# -f_validate_ipaddr() -{ - local ip="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Track number of octets for error checking - noctets=0 - - IFS="." # Split on `dot' - for octet in $ip; do - - # Return error if the octet is null - [ "$octet" ] || exit 2 - - # Return error if not a whole integer - f_isinteger "$octet" || exit 1 - - # Return error if not a positive integer - [ $octet -ge 0 ] || exit 1 - - # Return error if the octet exceeds 255 - [ $octet -gt 255 ] && exit 3 - - noctets=$(( $noctets + 1 )) - - done - - [ $noctets -eq 4 ] || exit 4 - ) -} - # f_dialog_iperror $error $ipaddr # # Display a msgbox with the appropriate error message for an error returned by -# the f_validate_ipaddr function above. +# the f_validate_ipaddr function. # f_dialog_iperror() { @@ -144,141 +79,6 @@ f_dialog_validate_ipaddr() return $retval } -# f_validate_ipaddr6 $ipv6_addr -# -# Returns zero if the given argument (an IPv6 address) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual segments within the IP address -# (separated by colons) contains one or more invalid characters. -# Segments must contain only combinations of the characters 0-9, -# A-F, or a-f. -# 2 Too many/incorrect null segments. A single null segment is -# allowed within the IP address (separated by colons) but not -# allowed at the beginning or end (unless a double-null segment; -# i.e., "::*" or "*::"). -# 3 One or more individual segments within the IP address -# (separated by colons) exceeds the length of 4 hex-digits. -# 4 The IP address entered has either too few (less than 3), too -# many (more than 8), or not enough segments, separated by -# colons. -# 5* The IPv4 address at the end of the IPv6 address is invalid. -# * When there is an error with the dotted-quad IPv4 address at the -# end of the IPv6 address, the return value of 5 is OR'd with a -# bit-shifted (<< 4) return of f_validate_ipaddr. -# -f_validate_ipaddr6() -{ - local ip="$1" - - ( # Operate within a sub-shell to protect the parent environment - - IFS=":" # Split on `colon' - set -- $ip: - - # Return error if too many or too few segments - # Using 9 as max in case of leading or trailing null spanner - [ $# -gt 9 -o $# -lt 3 ] && exit 4 - - h="[0-9A-Fa-f]" - nulls=0 - nsegments=$# - contains_ipv4_segment= - - while [ $# -gt 0 ]; do - - segment="${1%:}" - shift - - # - # Return error if this segment makes one null too-many. - # A single null segment is allowed anywhere in the - # middle as well as double null segments are allowed at - # the beginning or end (but not both). - # - if [ ! "$segment" ]; then - nulls=$(( $nulls + 1 )) - if [ $nulls -eq 3 ]; then - # Only valid syntax for 3 nulls is `::' - [ "$ip" = "::" ] || exit 2 - elif [ $nulls -eq 2 ]; then - # Only valid if begins/ends with `::' - case "$ip" in - ::*|*::) : fall thru ;; - *) exit 2 - esac - fi - continue - fi - - # - # Return error if not a valid hexadecimal short - # - case "$segment" in - $h|$h$h|$h$h$h|$h$h$h$h) - : valid segment of 1-4 hexadecimal digits - ;; - *[!0-9A-Fa-f]*) - # Segment contains at least one invalid char - - # Return error immediately if not last segment - [ $# -eq 0 ] || exit 1 - - # Otherwise, check for legacy IPv4 notation - case "$segment" in - *[!0-9.]*) - # Segment contains at least one invalid - # character even for an IPv4 address - exit 1 - esac - - # Return error if not enough segments - if [ $nulls -eq 0 ]; then - [ $nsegments -eq 7 ] || exit 4 - fi - - contains_ipv4_segment=1 - - # Validate the IPv4 address - f_validate_ipaddr "$segment" || - exit $(( 5 | $? << 4 )) - ;; - *) - # Segment characters are all valid but too many - exit 3 - esac - - done - - if [ $nulls -eq 1 ]; then - # Single null segment cannot be at beginning/end - case "$ip" in - :*|*:) exit 2 - esac - fi - - # - # A legacy IPv4 address can span the last two 16-bit segments, - # reducing the amount of maximum allowable segments by-one. - # - maxsegments=8 - if [ "$contains_ipv4_segment" ]; then - maxsegments=7 - fi - - case $nulls in - # Return error if missing segments with no null spanner - 0) [ $nsegments -eq $maxsegments ] || exit 4 ;; - # Return error if null spanner with too many segments - 1) [ $nsegments -le $maxsegments ] || exit 4 ;; - # Return error if leading/trailing `::' with too many segments - 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;; - esac - - exit $SUCCESS - ) -} - # f_dialog_ip6error $error $ipv6_addr # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/netmask.subr b/usr.sbin/bsdconfig/networking/share/netmask.subr index 3a8665d..e6838e5 100644 --- a/usr.sbin/bsdconfig/networking/share/netmask.subr +++ b/usr.sbin/bsdconfig/networking/share/netmask.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,87 +40,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_ifconfig_netmask $interface -# -# Returns the IPv4 subnet mask associated with $interface. -# -f_ifconfig_netmask() -{ - local interface="$1" octets - octets=$( ifconfig "$interface" 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "inet" ) \ - { - printf "%s %s %s %s\n", - substr($4,3,2), - substr($4,5,2), - substr($4,7,2), - substr($4,9,2) - found = 1 - exit - } - END { exit ! found } - ' ) || return $FAILURE - - local octet netmask= - for octet in $octets; do - netmask="$netmask${netmask:+.}$( printf "%u" "0x$octet" )" - done - echo $netmask -} - -# f_validate_netmask $netmask -# -# Returns zero if the given argument (a subnet mask) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual fields within the subnet mask (separated -# by dots) contains one or more invalid characters. -# 2 One or more individual fields within the subnet mask are null -# and/or missing. -# 3 One or more individual fields within the subnet mask exceeds -# the maximum of 255 (a full 8-bit register). -# 4 The subnet mask has either too few or too many fields. -# 5 One or more individual fields within the subnet mask is an -# invalid integer (only 0,128,192,224,240,248,252,254,255 are -# valid integers). -# -f_validate_netmask() -{ - local mask="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Track number of fields for error checking - nfields=0 - - IFS="." # Split on `dot' - for field in $mask; do - - # Return error if the field is null - [ "$field" ] || exit 2 - - # Return error if not a whole positive integer - f_isinteger "$field" || exit 1 - - # Return error if the field exceeds 255 - [ $field -gt 255 ] && exit 3 - - # Return error if the field is an invalid integer - case "$field" in - 0|128|192|224|240|248|252|254|255) :;; - *) exit 5;; - esac - - nfields=$(( $nfields + 1 )) - - done - - [ $nfields -eq 4 ] || exit 4 - ) -} - # f_dialog_maskerror $error $netmask # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr index 7d9af3b..b525a4d 100644 --- a/usr.sbin/bsdconfig/networking/share/resolv.subr +++ b/usr.sbin/bsdconfig/networking/share/resolv.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" f_dprintf "%s: loading includes..." networking/resolv.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr @@ -42,11 +43,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ CONFIGURATION # -# Path to resolv.conf(5). -# -: ${RESOLV_CONF:="/etc/resolv.conf"} - -# # When updating resolv.conf(5), should we populate the `search' directive with # all possible sub-domains? In example, if the domain is "sub.domain.com", when # the below option is set to 1, include both "sub.domain.com" and "domain.com" @@ -103,25 +99,6 @@ f_resolv_conf_search() ' } -# f_resolv_conf_nameservers -# -# Returns nameserver(s) configured in resolv.conf(5). -# -f_resolv_conf_nameservers() -{ - awk \ - ' - BEGIN { found = 0 } - ( $1 == "nameserver" ) \ - { - print $2 - found = 1 - } - END { exit ! found } - ' \ - "$RESOLV_CONF" 2> /dev/null -} - # f_dialog_resolv_conf_update $hostname # # Updates the search/domain directives in resolv.conf(5) given a valid fully- diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr index 4207ab2..2d8cafc 100644 --- a/usr.sbin/bsdconfig/networking/share/routing.subr +++ b/usr.sbin/bsdconfig/networking/share/routing.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_ROUTING_SUBR" ]; then _NETWORKING_ROUTING_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" f_dprintf "%s: loading includes..." networking/routing.subr f_include $BSDCFG_SHARE/sysrc.subr f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr @@ -41,25 +42,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_route_get_default -# -# Returns the IP address of the currently active default router. -# -f_route_get_default() -{ - route -n get default 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "gateway:" ) \ - { - print $2 - found = 1 - exit - } - END { exit ! found } - ' -} - # f_dialog_input_defaultrouter # # Edits the default router. diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile index cd56dfc..4c20c2b 100644 --- a/usr.sbin/bsdconfig/share/Makefile +++ b/usr.sbin/bsdconfig/share/Makefile @@ -2,9 +2,11 @@ NO_OBJ= +SUBDIR= media + FILESDIR= ${SHAREDIR}/bsdconfig -FILES= common.subr dialog.subr mustberoot.subr script.subr \ - strings.subr sysrc.subr variable.subr +FILES= common.subr device.subr dialog.subr mustberoot.subr \ + script.subr strings.subr struct.subr sysrc.subr variable.subr beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr index c66a54f..cb9096f 100644 --- a/usr.sbin/bsdconfig/share/common.subr +++ b/usr.sbin/bsdconfig/share/common.subr @@ -1,7 +1,7 @@ if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 # # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -127,15 +127,15 @@ f_have() # f_getvar() { - local var_to_get="$1" var_to_set="$2" - [ "$var_to_set" ] || local value - eval ${var_to_set:-value}=\"\${$var_to_get}\" - eval [ \"\${$var_to_get+set}\" ] - local retval=$? + local __var_to_get="$1" __var_to_set="$2" + [ "$__var_to_set" ] || local value + eval ${__var_to_set:-value}=\"\${$__var_to_get}\" + eval [ \"\${$__var_to_get+set}\" ] + local __retval=$? 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 + \"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval + [ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; } + return $__retval } # f_die [ $status [ $fmt [ $opts ... ]]] @@ -574,6 +574,30 @@ f_index_menusel_command() echo "$command" } +# 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 +# +# Return success if a filesystem is mounted on a particular directory. +# +f_mounted() +{ + local dir="$1" + [ -d "$dir" ] || return $FAILURE + mount | grep -Eq " on $dir \([^)]+\)$" +} + ############################################################ MAIN # diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr new file mode 100644 index 0000000..473838b --- /dev/null +++ b/usr.sbin/bsdconfig/share/device.subr @@ -0,0 +1,799 @@ +if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_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..." device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/struct.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DEVICES= +DEVICE_NAMES= + +# A "device" from sysinstall's point of view +f_struct_define DEVICE \ + name \ + desc \ + devname \ + type \ + enabled \ + init \ + get \ + shutdown \ + flags \ + private \ + volume + +# Network devices have their `private' property set to this +f_struct_define DEVICE_INFO \ + use_rtsol use_dhcp ipaddr ipv6addr netmask extras + +setvar DEVICE_TYPE_NONE 1 +setvar DEVICE_TYPE_DISK 2 +setvar DEVICE_TYPE_FLOPPY 3 +setvar DEVICE_TYPE_FTP 4 +setvar DEVICE_TYPE_NETWORK 5 +setvar DEVICE_TYPE_CDROM 6 +setvar DEVICE_TYPE_USB 7 +setvar DEVICE_TYPE_DOS 8 +setvar DEVICE_TYPE_UFS 9 +setvar DEVICE_TYPE_NFS 10 +setvar DEVICE_TYPE_ANY 11 +setvar DEVICE_TYPE_HTTP_PROXY 12 + +# +# Default behavior is to call f_device_get_all() automatically when loaded. +# +: ${DEVICE_SELF_SCAN_ALL=1} + +############################################################ FUNCTIONS + +# f_device_try $name [$i [$var_path]] +# +# Test a particular device. If $i is given, then $name is expected to contain a +# single "%d" where $i will be inserted using printf. If $var_path is given, +# it is used as a variable name to provide the caller the device pathname. +# +# Returns success if the device path exists and is a cdev. +# +f_device_try() +{ + local name="$1" i="$2" var_path="$3" unit + if [ "$i" ]; then + unit=$( printf "$name" "$i" ) + else + unit="$name" + fi + case "$unit" in + /dev/*) : good ;; # already qualified + *) unit="/dev/$unit" ;; + esac + [ "$var_path" ] && setvar "$var_path" "$unit" + f_dprintf "f_device_try: making sure %s is a device node" "$unit" + if [ -c "$unit" ]; then + f_dprintf "f_device_try: %s is a cdev [good]" "$unit" + return $SUCCESS + else + f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit" + return $FAILURE + fi +} + +# f_device_register $name $desc $devname $type $enabled $init_function \ +# $get_function $shutdown_function $private +# +# Register a device. A `structure' (see struct.subr) is created with the name +# device_$name (so make sure $name contains only alpha-numeric characters or +# the underscore, `_'). The remaining arguments after $name correspond to the +# properties of the `DEVICE' structure-type (defined above). +# +# If not already registered, the device is then appended to the DEVICES +# environment variable, a space-separated list of all registered devices. +# +f_device_register() +{ + local name="$1" desc="$2" devname="$3" type="$4" enabled="$5" + local init_func="$6" get_func="$7" shutdown_func="$8" private="$9" + + f_struct_new DEVICE "device_$name" || return $FAILURE + device_$name set name "$name" + device_$name set desc "$desc" + device_$name set devname "$devname" + device_$name set type "$type" + device_$name set enabled "$enabled" + device_$name set init "$init_func" + device_$name set get "$get_func" + device_$name set shutdown "$shutdown_func" + device_$name set private "$private" + + # Scan our global register to see if it needs ammending + local dev found= + for dev in $DEVICES; do + [ "$dev" = "$name" ] || continue + found=1 && break + done + [ "$found" ] || DEVICES="$DEVICES $name" + + return $SUCCESS +} + +# f_device_reset +# +# Reset the registered device chain. +# +f_device_reset() +{ + local dev + for dev in $DEVICES; do + f_device_shutdown $dev + + # + # XXX this potentially leaks $dev->private if it's being + # used to point to something dynamic, but you're not supposed + # to call this routine at such times that some open instance + # has its private member pointing somewhere anyway. XXX + # + f_struct_free device_$dev + done + DEVICES= +} + +# f_device_get_all +# +# Get all device information for devices we have attached. +# +f_device_get_all() +{ + local devname desc + + f_dprintf "f_device_get_all: Probing devices..." + f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while" + + # First go for the network interfaces + for devname in $( ifconfig -l ); do + # Eliminate network devices that don't make sense + case "$devname" in + lo*) continue ;; + esac + + # Try and find its description + f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc + + f_dprintf "Found a network device named %s" "$devname" + f_device_register $devname \ + "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \ + f_media_init_network "" f_media_shutdown_network "" + done + + # Next, try to find all the types of devices one might use + # as a media source for content + # + + local dev desc type max n=0 + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + # Get the desc, type, and max (with debugging disabled) + # NOTE: Bypassing f_device_name_get() for efficiency + debug= f_getvar _device_desc$n desc + debug= f_getvar _device_type$n type + debug= f_getvar _device_max$n max + + local k=0 + while [ $k -lt ${max:-0} ]; do + i=$k k=$(( $k + 1 )) + devname="" + case "$type" in + $DEVICE_TYPE_CDROM) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_FLOPPY) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_FLOPPY 1 \ + f_media_init_floppy \ + f_media_get_floppy \ + f_media_shutdown_floppy "" + f_dprintf "Found a floppy device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_USB) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_USB 1 \ + f_media_init_usb f_media_get_usb \ + f_media_shutdown_usb "" + f_dprintf "Found a USB disk for %s" "$devname" + ;; + esac + done + done + + # Register ISO9660 providers as CDROM devices + for devname in /dev/iso9660/*; do + f_device_try "$devname" || continue + f_device_register "${devname##*/}" "ISO9660 file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + done + + # Scan for mdconfig(8)-created md(4) devices + local filename + for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do + f_device_try "$devname" || continue + + # See if the md(4) device is a vnode type backed by a file + filename=$( sysctl kern.geom.conftxt | + awk -v devname="${devname##*/}" \ + ' + ( $2 == "MD" ) && \ + ( $3 == devname ) && \ + ( $(NF-2) == "vnode" ) && \ + ( $(NF-1) == "file" ) \ + { + print $NF + } + ' ) + case "$filename" in + *.iso) # Register the device as an ISO9660 provider + f_device_register "${devname##*/}" \ + "md(4) vnode file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + ;; + esac + done + + # Finally go get the disks and look for partitions to register + local diskname slices index type rest slice part + for diskname in $( sysctl -n kern.disks ); do + + case "$diskname" in + cd*) + # XXX + # Due to unknown reasons, kern.disks returns SCSI + # CDROM as a valid disk. This will prevent bsdconfig + # from presenting SCSI CDROMs as available disks in + # various menus. Why GEOM treats SCSI CDROM as a disk + # is beyond me and that should be investigated. + # For temporary workaround, ignore SCSI CDROM device. + # + continue ;; + esac + + # Try to create a list of partitions and their types, + # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06"). + if ! slices=$( fdisk -p "$diskname" 2> /dev/null | + awk '( $1 == "p" ) { print $2","$3 }' ) + then + f_dprintf "Unable to open disk %s" "$diskname" + continue + fi + + f_device_register "$diskname" "" \ + "/dev/$diskname" $DEVICE_TYPE_DISK 0 + f_dprintf "Found a disk device named %s" "$diskname" + + # Look for existing partitions to register + for slice in $slices; do + index="${slice%%,*}" type="${slice#*,}" + slice=${diskname}s$index + case "$type" in + 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef) + # DOS partitions to add as "DOS media devices" + f_device_register "$slice" "" \ + "/dev/$slice" $DEVICE_TYPE_DOS 1 \ + f_media_init_dos f_media_get_dos \ + f_media_shutdown_dos "" + f_dprintf "Found a DOS partition %s" "$slice" + ;; + 0xa5) # FreeBSD partition + for part in $( + bsdlabel -r $slice 2> /dev/null | + awk -v slice="$slice" ' + ( $1 ~ /[abdefgh]:/ ) { + printf "%s%s\n", + slice, + substr($1,1,1) + }' + ); do + f_quietly dumpfs -m /dev/$part || + continue + f_device_register \ + "$part" "" "/dev/$part" \ + $DEVICE_TYPE_UFS 1 \ + f_media_init_ufs \ + f_media_get_ufs \ + f_media_shutdown_ufs "" + f_dprintf "Found a UFS partition %s" \ + "$part" + done # parts + ;; + esac + done # slices + + done # disks +} + +# f_device_name_get $type $name type|desc|max [$var_to_set] +# +# Fetch the device type (type), description (desc), or maximum number of +# devices to scan for (max) associated with device $name and $type. If $type is +# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used. +# Returns success if a match was found, otherwise failure. +# +# If $var_to_set is missing or NULL, the device name is printed to standard out +# for capturing in a sub-shell (which is less-recommended because of +# performance degredation; for example, when called in a loop). +# +f_device_name_get() +{ + local __type="$1" __name="$2" __prop="$3" __var_to_set="$4" + local __dev __devtype __n=0 + + # Return failure if no $name or $prop is an unknown property + [ "$__name" ] || return $FAILURE + case "$__prop" in type|desc|max) : good ;; + *) return $FAILURE; esac + + [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type= + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + [ "$__dev" = "$__name" ] || continue + f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + f_getvar _device_$__prop$__n $__var_to_set + return $? + done + return $FAILURE +} + +# f_device_name_set $type $name $desc [$max] +# +# Store a description (desc) and [optionally] maximum number of devices to scan +# for (max) in-association with device $type and $name. Returns success. Use +# the f_device_name_get() routine with the same $name and [optionally] $type to +# retrieve one of type, desc, or max properties. +# +f_device_name_set() +{ + local type="$1" name="$2" desc="$3" max="$4" + local dev devtype n=0 found= + [ "$name" ] || return $FAILURE + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + [ "$dev" = "$name" ] || continue + if f_getvar _device_type$n devtype; then + # Allow multiple entries with same name but diff type + [ "$devtype" = "$type" ] || continue + fi + found=1 && break + done + if [ ! "$found" ]; then + DEVICE_NAMES="$DEVICE_NAMES $name" + n=$(( $n + 1 )) + fi + setvar _device_type$n "$type" + setvar _device_desc$n "$desc" + [ "${4+set}" ] && setvar _device_max$n "$max" + return $SUCCESS +} + +# f_device_desc $device_name $device_type [$var_to_set] +# +# Print a description for a device name (eg., `fxp0') given a specific device +# type/class. +# +# If $var_to_set is missing or NULL, the device description is printed to +# standard out for capturing in a sub-shell (which is less-recommended because +# of performance degredation; for example, when called in a loop). +# +f_device_desc() +{ + local __name="$1" __type="$2" __var_to_set="$3" + local __devname __devunit __cp + + # Check variables + [ "$__name" ] || return $SUCCESS + [ "$__type" = "$DEVICE_TYPE_ANY" ] && type= + [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; } + + # + # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, + # otherwise fall through to below static list. + # + if f_have sysctl; then + __devname="${__name%%[0-9]*}" + __devunit="${__name#$__devname}" + __devunit="${__devunit%%[!0-9]*}" + if [ "$__var_to_set" ]; then + if __cp=$( + sysctl -n "dev.$__devname.$__devunit.%desc" \ + 2> /dev/null + ); then + setvar "$__var_to_set" "$__cp" && + return $SUCCESS + fi + else + sysctl -n "dev.$__devname.$__devunit.%desc" \ + 2> /dev/null && return $SUCCESS + fi + fi + + local __dev __devtype __n=0 + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + debug= f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then + __devname=$( f_substr "$__name" 0 ${#__dev} ) + [ "$__devname" = "$__dev" ] || continue + else + __devname="${__name%%[0-9]*}" + __devunit="${__name#$__devname}" + __devunit="${__devunit%%[!0-9]*}" + __devname=$( printf "$__dev" $__devunit ) + [ "$__devname" = "$__name" ] || continue + fi + debug= f_getvar _device_desc$__n $__var_to_set + return $? + done + + # + # Sensible fall-backs for specific types + # + case "$__type" in + $DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>";; + $DEVICE_TYPE_DISK) __cp="<unknown disk device type>";; + $DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>";; + $DEVICE_TYPE_USB) __cp="<unknown usb storage device type>";; + $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>";; + *) + __cp="<unknown device type>" + esac + + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__cp" + else + echo "$__cp" + fi + + return $FAILURE +} + +# f_device_rescan +# +# Rescan all devices, after closing previous set - convenience function. +# +f_device_rescan() +{ + f_device_reset + f_device_get_all +} + +# f_device_find $name [$type [$var_to_set]] +# +# Find one or more registered devices by name, type, or both. Returns a space- +# separated list of devices matching the search criterion. +# +# If $var_to_set is missing or NULL, the device name(s) are printed to standard +# out for capturing in a sub-shell (which is less-recommended because of +# performance degredation; for example, when called in a loop). +# +f_device_find() +{ + local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3" + local __dev __devname __devtype __found= + for __dev in $DEVICES; do + device_$__dev get name __devname + device_$__dev get type __devtype + if [ "$__name" = "$__devname" -o ! "$__name" ] && + [ "$__type" = "$DEVICE_TYPE_ANY" -o \ + "$__type" = "$__devtype" ] + then + __found="$__found $__dev" + fi + done + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "${__found# }" + else + echo $__found + fi + [ "$__found" ] # Return status +} + +# f_device_init $name +# +# Initialize a device by evaluating its `init' function. +# +f_device_init() +{ + local name="$1" init_func + device_$name get init init_func || return + ${init_func:-:} $name +} + +# f_device_get $name $file [$probe] +# +# Read $file by evaluating the device's `get' function. The file is commonly +# produced on standard output (but it truly depends on the function called). +# +f_device_get() +{ + local name="$1" file="$2" probe="$3" get_func + device_$name get get get_func || return + ${get_func:-:} $name "$file" ${3+"$probe"} +} + +# f_device_shutdown $name +# +# Shutdown a device by evaluating its `shutdown' function. +# +f_device_shutdown() +{ + local name="$1" shutdown_func + device_$name get shutdown shutdown_func || return + ${shutdown_func:-:} $name +} + +# f_device_menu $title $prompt $hline $device_type [$helpfile] +# +# Display a menu listing all the devices of a certain type in the system. +# +f_device_menu() +{ + f_dialog_title "$1" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + + local prompt="$2" hline="$3" type="$4" helpfile="$5" + + local dev devtype devs= + for dev in $DEVICES; do + device_$dev get type devtype || continue + [ "$devtype" = "$type" ] || continue + devs="$devs $dev" + done + [ "$devs" ] || return $FAILURE + + local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }" + + local desc menu_list= + for dev in $devs; do + device_$dev get desc desc + desc=$( echo "$desc" | awk "$sanitize_awk" ) + menu_list="$menu_list '$dev' '$desc'" + done + + local size mtag + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local errexit= + case $- in *e*) errexit=1; esac + set +e + + while :; do + mtag=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + ${helpfile:+ \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + } \ + --menu \"\$prompt\" $size \ + $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + + [ $retval -ne 2 ] && break + # Otherwise, the Help button was pressed + f_show_help "$helpfile" + # Loop back to menu + done + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + [ "$errexit" ] && set -e + + [ $retval -eq 0 ] && echo "$mtag" >&2 + + return $retval +} + +# +# Short-hand +# +f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; } +f_disk() { f_device_name_set $DEVICE_TYPE_DISK "$1" "$2" "$3"; } +f_floppy() { f_device_name_set $DEVICE_TYPE_FLOPPY "$1" "$2" "$3"; } +f_serial() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3"; } +f_usb() { f_device_name_set $DEVICE_TYPE_USB "$1" "$2" "$3"; } +f_network() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2"; } + +############################################################ MAIN + +# CDROM, Disk, Floppy, Serial, and USB devices/names +f_cdrom "acd%d" "ATAPI/IDE CDROM" 4 +f_cdrom "cd%d" "SCSI CDROM drive" 4 +f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive" 4 +f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type" 4 +f_disk "aacd%d" "Adaptec FSA RAID array" 4 +f_disk "ad%d" "ATA/IDE disk device" 16 +f_disk "ada%d" "SATA disk device" 16 +f_disk "afd%d" "ATAPI/IDE floppy device" 4 +f_disk "amrd%d" "AMI MegaRAID drive" 4 +f_disk "ar%d" "ATA/IDE RAID device" 16 +f_disk "da%d" "SCSI disk device" 16 +f_disk "idad%d" "Compaq RAID array" 4 +f_disk "ipsd%d" "IBM ServeRAID RAID array" 4 +f_disk "mfid%d" "LSI MegaRAID SAS array" 4 +f_disk "mlxd%d" "Mylex RAID disk" 4 +f_disk "twed%d" "3ware ATA RAID array" 4 +f_floppy "fd%d" "Floppy Drive unit A" 4 +f_serial "cuau%d" "%s on device %s (COM%d)" 16 +f_usb "da%da" "USB Mass Storage Device" 16 + +# Network interfaces/names +f_network "ae" "Attansic/Atheros L2 Fast Ethernet" +f_network "age" "Attansic/Atheros L1 Gigabit Ethernet" +f_network "alc" "Atheros AR8131/AR8132 PCIe Ethernet" +f_network "ale" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet" +f_network "an" "Aironet 4500/4800 802.11 wireless adapter" +f_network "ath" "Atheros IEEE 802.11 wireless adapter" +f_network "aue" "ADMtek USB Ethernet adapter" +f_network "axe" "ASIX Electronics USB Ethernet adapter" +f_network "bce" "Broadcom NetXtreme II Gigabit Ethernet card" +f_network "bfe" "Broadcom BCM440x PCI Ethernet card" +f_network "bge" "Broadcom BCM570x PCI Gigabit Ethernet card" +f_network "bm" "Apple BMAC Built-in Ethernet" +f_network "bwn" "Broadcom BCM43xx IEEE 802.11 wireless adapter" +f_network "cas" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet" +f_network "cc3i" "SDL HSSI sync serial PCI card" +f_network "cue" "CATC USB Ethernet adapter" +f_network "cxgb" "Chelsio T3 10Gb Ethernet card" +f_network "dc" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card" +f_network "de" "DEC DE435 PCI NIC or other DC21040-AA based card" +f_network "disc" "Software discard network interface" +f_network "ed" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA" +f_network "el" "3Com 3C501 Ethernet card" +f_network "em" "Intel(R) PRO/1000 Ethernet card" +f_network "en" "Efficient Networks ATM PCI card" +f_network "ep" "3Com 3C509 Ethernet card/3C589 PCMCIA" +f_network "et" "Agere ET1310 based PCI Express Gigabit Ethernet card" +f_network "ex" "Intel EtherExpress Pro/10 Ethernet card" +f_network "fe" "Fujitsu MB86960A/MB86965A Ethernet card" +f_network "fpa" "DEC DEFPA PCI FDDI card" +f_network "fwe" "FireWire Ethernet emulation" +f_network "fwip" "IP over FireWire" +f_network "fxp" "Intel EtherExpress Pro/100B PCI Fast Ethernet card" +f_network "gem" "Apple GMAC or Sun ERI/GEM Ethernet adapter" +f_network "hme" "Sun HME (Happy Meal Ethernet) Ethernet adapter" +f_network "ie" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210" +f_network "igb" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card" +f_network "ipw" "Intel PRO/Wireless 2100 IEEE 802.11 adapter" +f_network "iwi" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter" +f_network "iwn" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter" +f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card" +f_network "ixgb" "Intel(R) PRO/10Gb Ethernet card" +f_network "ix" "Intel Etherexpress Ethernet card" + # Maintain sequential order of above(3): ixgbe ixgb ix +f_network "jme" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet" +f_network "kue" "Kawasaki LSI USB Ethernet adapter" +f_network "le" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter" +f_network "lge" "Level 1 LXT1001 Gigabit Ethernet card" +f_network "lnc" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet" +f_network "lo" "Loop-back (local) network interface" +f_network "lp" "Parallel Port IP (PLIP) peer connection" +f_network "malo" "Marvell Libertas 88W8335 802.11 wireless adapter" +f_network "msk" "Marvell/SysKonnect Yukon II Gigabit Ethernet" +f_network "mxge" "Myricom Myri10GE 10Gb Ethernet card" +f_network "nfe" "NVIDIA nForce MCP Ethernet" +f_network "nge" "NatSemi PCI Gigabit Ethernet card" +f_network "ng" "Vimage netgraph(4) bridged Ethernet device" + # Maintain sequential order of above(2): nge ng +f_network "nve" "NVIDIA nForce MCP Ethernet" +f_network "nxge" "Neterion Xframe 10GbE Server/Storage adapter" +f_network "pcn" "AMD Am79c79x PCI Ethernet card" +f_network "plip" "Parallel Port IP (PLIP) peer connection" +f_network "ral" "Ralink Technology IEEE 802.11 wireless adapter" +f_network "ray" "Raytheon Raylink 802.11 wireless adapter" +f_network "re" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter" +f_network "rl" "RealTek 8129/8139 PCI Ethernet card" +f_network "rue" "RealTek USB Ethernet card" +f_network "rum" "Ralink Technology USB IEEE 802.11 wireless adapter" +f_network "sf" "Adaptec AIC-6915 PCI Ethernet card" +f_network "sge" "Silicon Integrated Systems SiS190/191 Ethernet" +f_network "sis" "SiS 900/SiS 7016 PCI Ethernet card" +f_network "sk" "SysKonnect PCI Gigabit Ethernet card" +f_network "snc" "SONIC Ethernet card" +f_network "sn" "SMC/Megahertz Ethernet card" + # Maintain sequential order of above(2): snc sn +f_network "sr" "SDL T1/E1 sync serial PCI card" +f_network "ste" "Sundance ST201 PCI Ethernet card" +f_network "stge" "Sundance/Tamarack TC9021 Gigabit Ethernet" +f_network "ti" "Alteon Networks PCI Gigabit Ethernet card" +f_network "tl" "Texas Instruments ThunderLAN PCI Ethernet card" +f_network "txp" "3Com 3cR990 Ethernet card" +f_network "tx" "SMC 9432TX Ethernet card" + # Maintain sequential order of above(2): txp tx +f_network "uath" "Atheros AR5005UG and AR5005UX USB wireless adapter" +f_network "upgt" "Conexant/Intersil PrismGT USB wireless adapter" +f_network "ural" "Ralink Technology RT2500USB 802.11 wireless adapter" +f_network "urtw" "Realtek 8187L USB wireless adapter" +f_network "vge" "VIA VT612x PCI Gigabit Ethernet card" +f_network "vlan" "IEEE 802.1Q VLAN network interface" +f_network "vr" "VIA VT3043/VT86C100A Rhine PCI Ethernet card" +f_network "vx" "3COM 3c590 / 3c595 Ethernet card" +f_network "wb" "Winbond W89C840F PCI Ethernet card" +f_network "wi" "Lucent WaveLAN/IEEE 802.11 wireless adapter" +f_network "wpi" "Intel 3945ABG IEEE 802.11 wireless adapter" +f_network "wx" "Intel Gigabit Ethernet (82452) card" +f_network "xe" "Xircom/Intel EtherExpress Pro100/16 Ethernet card" +f_network "xl" "3COM 3c90x / 3c90xB PCI Ethernet card" +f_network "zyd" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter" + +f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \ + "$( set -- $DEVICE_NAMES; echo $# )" + +# +# Scan for the above devices unless requeted otherwise +# +f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL" +case "$DEVICE_SELF_SCAN_ALL" in +""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; +*) f_device_get_all +esac + +f_dprintf "%s: Successfully loaded." device.subr + +fi # ! $_DEVICE_SUBR diff --git a/usr.sbin/bsdconfig/share/media/Makefile b/usr.sbin/bsdconfig/share/media/Makefile new file mode 100644 index 0000000..ebd7c96 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +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 + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdconfig/share/media/any.subr b/usr.sbin/bsdconfig/share/media/any.subr new file mode 100644 index 0000000..f64710f --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/any.subr @@ -0,0 +1,152 @@ +if [ ! "$_MEDIA_ANY_SUBR" ]; then _MEDIA_ANY_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/any.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/media/cdrom.subr +f_include $BSDCFG_SHARE/media/directory.subr +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/httpproxy.subr +f_include $BSDCFG_SHARE/media/nfs.subr +f_include $BSDCFG_SHARE/media/options.subr +f_include $BSDCFG_SHARE/media/ufs.subr +f_include $BSDCFG_SHARE/media/usb.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +MEDIA_HELPFILE=$BSDCFG_LIBE/include/media.hlp + +############################################################ FUNCTIONS + +# f_media_get_type +# +# Prompt the user to select amongst the known media types (included above). +# +# If the user does not cancel or press Esc, invokes the f_media_set_* function +# associated with the chosen media type. If after all that we have a struct +# named `device_media' then success is returned, otherwise failure. +# +# NOTE: The f_media_set_* function should create the `device_media' struct. +# See `struct.subr' and the above `media/*.subr' includes for more details. +# +f_media_get_type() +{ + f_dialog_title "$msg_choose_installation_media" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + local prompt="$msg_choose_installation_media_description" + local hline="$hline_choose_help_for_more_information_on_media_types" + local menu_list size + + 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' + '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' + '8 $msg_ufs' '$msg_install_from_a_ufs_partition' + '9 $msg_floppy' '$msg_install_from_a_floppy_disk_set' + 'A $msg_usb' '$msg_install_from_a_usb_drive' + 'X $msg_options' '$msg_view_set_various_media_options' + " # END-QUOTE + + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu + + while :; do + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + --menu \"\$prompt\" $size $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + + local mtag + mtag=$( f_dialog_menutag ) + f_dprintf "retval=%s mtag=[%s]" $retval "$mtag" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$MEDIA_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + return $FAILURE + fi + + case "$mtag" in + ?" $msg_cd_dvd") f_media_set_cdrom ;; + ?" $msg_ftp") f_media_set_ftp_active ;; + ?" $msg_ftp_passive") f_media_set_ftp_passive ;; + ?" $msg_http") f_media_set_http_proxy ;; + ?" $msg_directory") f_media_set_directory ;; + ?" $msg_dos") f_media_set_dos ;; + ?" $msg_nfs") f_media_set_nfs ;; + ?" $msg_ufs") f_media_set_ufs ;; + ?" $msg_floppy") f_media_set_floppy ;; + ?" $msg_usb") f_media_set_usb ;; + ?" $msg_options") + f_media_options_menu + continue + ;; + esac + break + done + + f_struct device_media || return $FAILURE +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/any.subr + +fi # ! $_MEDIA_ANY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/cdrom.subr b/usr.sbin/bsdconfig/share/media/cdrom.subr new file mode 100644 index 0000000..f22ebd2 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/cdrom.subr @@ -0,0 +1,210 @@ +if [ ! "$_MEDIA_CDROM_SUBR" ]; then _MEDIA_CDROM_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/cdrom.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +CDROM_MOUNTED= +CDROM_PREVIOUSLY_MOUNTED= +CDROM_INIT_QUIET= + +############################################################ FUNCTIONS + +# f_media_set_cdrom +# +# Return success if we both found and set the media type to be a CD. +# +f_media_set_cdrom() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_CDROM devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_dialog_msgbox "$msg_no_cd_dvd_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_cd_dvd_type" + local prompt="$msg_please_select_a_cd_dvd_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_CDROM \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_CDROM devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_cdrom $device +# +# Initializes the CDROM media device. Returns success if able to mount the CD +# device using mount_cd9660(8). +# +f_media_init_cdrom() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for CDROM device. devname=[%s]" \ + "$devname" + + if [ "$CDROM_MOUNTED" ]; then + f_dprintf "CDROM device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_cd9660 "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_cd9660: }"; err="${err#$devname: }" + case "$err" in + "Device busy") + # Perhaps the CDROM drive is already mounted as /cdrom + if f_mounted /cdrom; then + CDROM_PREVIOUSLY_MOUNTED=1 + MOUNTPOINT=/cdrom + err= + fi + ;; + esac + case "$err" in + "") : good ;; # no error + *) + [ "$CDROM_INIT_QUIET" ] || + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + esac + fi + CDROM_MOUNTED=1 + + : xxx # /cdrom.inf has been deprecated since 9.0-R + + # No other CDROM media validation at this time + + return $SUCCESS +} + +# f_media_get_cdrom $device $file [$probe_only] +# +# Returns data from $file on a mounted CDROM device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_cdrom() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_cdrom $device +# +# Shuts down the CDROM device and ejects the media using f_media_eject_cdrom(), +# below. Return status should be ignored. +# +f_media_shutdown_cdrom() +{ + local dev="$1" err + + [ "$CDROM_MOUNTED" ] || return + + if [ "$CDROM_PREVIOUSLY_MOUNTED" ]; then + CDROM_MOUNTED= + return $SUCCESS + fi + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_cdrom_dvd" \ + "$MOUNTPOINT" "$err" + else + CDROM_MOUNTED= + fi + + f_media_eject_cdrom "$dev" +} + +# f_media_eject_cdrom $device +# +# Eject the media from the CDROM device. Returns success. +# +f_media_eject_cdrom() +{ + local dev="$1" devname err + device_$dev get name devname || return $SUCCESS + case "$devname" in /dev/iso9660/*) return $SUCCESS; esac + f_dprintf "Ejecting CDROM/DVD at %s" "$devname" + if ! err=$( cdcontrol -f "$devname" eject 2>&1 ); then + f_dprintf "Could not eject the CDROM/DVD from %s: %s" \ + "$devname" "${err#cdcontrol: }" + fi + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/cdrom.subr + +fi # ! $_MEDIA_CDROM_SUBR diff --git a/usr.sbin/bsdconfig/share/media/common.subr b/usr.sbin/bsdconfig/share/media/common.subr new file mode 100644 index 0000000..589bbdc --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/common.subr @@ -0,0 +1,109 @@ +if [ ! "$_MEDIA_COMMON_SUBR" ]; then _MEDIA_COMMON_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/common.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr + +############################################################ GLOBALS + +# +# Where to mount media +# +MOUNTPOINT=/dist + +############################################################ FUNCTIONS + +# f_media_open +# +# Returms success if able to initialize the media device. +# +f_media_open() +{ + { # Verify and initialize device media if-defined + f_struct device_media && + f_media_verify && + f_device_init media + } || return $FAILURE +} + +# f_media_close +# +# Shuts down the media device, see f_device_shutdown() from device.subr for +# more details. +# +f_media_close() +{ + f_struct device_media && + f_device_shutdown media + f_struct_free device_media +} + +# f_media_verify +# +# Returns success if the media device is available, and if not, prompts the +# user to select a media type. See f_media_get_type() from media/any.subr for +# more details. +# +f_media_verify() +{ + f_struct device_media || f_media_get_type +} + +# f_media_generic_get $base $file +# +# A generic open which follows a well-known "path" of places to look. +# +f_media_generic_get() +{ + local base="$1" file="$2" rel path + + f_getvar $VAR_RELNAME rel + for path in \ + "$base/$file" \ + "$base/FreeBSD/$file" \ + "$base/releases/$file" \ + "$base/$rel/$file" \ + ; do + if [ -f "$path" -a -r "$path" ]; then + cat "$path" + return + fi + done + cat "$base/releases/$rel/$file" # Final path to try +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/common.subr + +fi # ! $_MEDIA_COMMON_SUBR diff --git a/usr.sbin/bsdconfig/share/media/directory.subr b/usr.sbin/bsdconfig/share/media/directory.subr new file mode 100644 index 0000000..3831140 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/directory.subr @@ -0,0 +1,146 @@ +if [ ! "$_MEDIA_DIRECTORY_SUBR" ]; then _MEDIA_DIRECTORY_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/directory.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DIRECTORY_CHECKED= + +############################################################ FUNCTIONS + +# f_media_set_directory +# +# Return success if we both found and set the media type to be a local +# directory. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_DIRECTORY_PATH +# Path to an existing directory containing the FreeBSD +# distribution files. +# +f_media_set_directory() +{ + local path + + f_media_close + + f_variable_get_value $VAR_DIRECTORY_PATH \ + "$msg_enter_a_fully_qualified_pathname_for_the_directory" + f_getvar $VAR_DIRECTORY_PATH path + [ "$path" ] || return $FAILURE + + f_struct_new DEVICE device_directory + device_directory set get f_media_get_directory + device_directory set init f_media_init_directory + device_directory set shutdown f_media_shutdown_directory + device_directory set private "$path" + + f_struct_copy device_directory device_media + f_struct_free device_directory + + f_struct device_media || return $FAILURE +} + +# f_media_init_directory $device +# +# Initializes the Directory media device. Returns success if the directory path +# both exists and is a directory. +# +f_media_init_directory() +{ + local dev="$1" path + + device_$dev get private path || return $FAILURE + f_dprintf "Init routine called for Directory device. path=[%s]" \ + "$path" + + # Track whether we've been through here before (for remote filesystems + # mounted in the directory path, not repeating these queries saves us + # valuable time for slow/uncooperative links). + if [ "$DIRECTORY_CHECKED" ]; then + f_dprintf "Directory device already checked." + return $SUCCESS + fi + + if [ ! -e "$path" ]; then + f_show_msg "$msg_no_such_file_or_directory" \ + "f_media_init_directory" "$path" + return $FAILURE + elif [ ! -d "$path" ]; then + f_show_msg "$msg_not_a_directory" \ + "f_media_init_directory" "$path" + return $FAILURE + fi + DIRECTORY_CHECKED=1 + return $SUCCESS +} + +# f_media_get_directory $device $file [$probe_only] +# +# Returns data from $file in the existing/current filesystem. Similar to +# cat(1). $probe_only is currently unused by this media type. +# +f_media_get_directory() +{ + local dev="$1" file="$2" probe_only="$3" path + + f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + device_$dev get private path + f_media_generic_get "$path" "$file" +} + +# f_media_shutdown_directory $device +# +# Shuts down the Directory device. Return status should be ignored. +# +f_media_shutdown_directory() +{ + DIRECTORY_CHECKED= +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/directory.subr + +fi # ! $_MEDIA_DIRECTORY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/dos.subr b/usr.sbin/bsdconfig/share/media/dos.subr new file mode 100644 index 0000000..3e59fb6 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/dos.subr @@ -0,0 +1,164 @@ +if [ ! "$_MEDIA_DOS_SUBR" ]; then _MEDIA_DOS_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/dos.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DOS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_dos +# +# Return success if we both found and set the media type to be a DOS partition. +# +f_media_set_dos() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_DOS devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_dos_primary_partitions_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_dos_partition" + local prompt="$msg_please_select_dos_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_DOS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_DOS devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_dos $device +# +# Initializes the DOS media device. Returns success if able to mount the DOS +# partition device using mount_msdosfs(8). +# +f_media_init_dos() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for DOS device. devname=[%s]" \ + "$devname" + + if [ "$DOS_MOUNTED" ]; then + f_dprintf "DOS device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_msdosfs "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_msdosfs: }"; err="${err#$devname: }" + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + fi + DOS_MOUNTED=1 + return $SUCCESS +} + +# f_media_get_dos $device $file [$probe_only] +# +# Returns data from $file on a mounted DOS partition device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_dos() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_dos $device +# +# Shuts down the DOS partition device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_dos() +{ + local dev="$1" err + + [ "$DOS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_dos_partition" \ + "$MOUNTPOINT" "$err" + else + DOS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/dos.subr + +fi # ! $_MEDIA_DOS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/floppy.subr b/usr.sbin/bsdconfig/share/media/floppy.subr new file mode 100644 index 0000000..c874c61 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/floppy.subr @@ -0,0 +1,214 @@ +if [ ! "$_MEDIA_FLOPPY_SUBR" ]; then _MEDIA_FLOPPY_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/floppy.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +FLOPPY_MOUNTED= +FLOPPY_DISTWANTED= + +############################################################ FUNCTIONS + +# f_media_set_floppy +# +# Return success if we both found and set the media type to be a floppy. +# +f_media_set_floppy() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_FLOPPY devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_dialog_msgbox "$msg_no_floppy_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_floppy_drive" + local prompt="$msg_please_select_a_floppy_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_FLOPPY \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_FLOPPY devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media && + device_media unset private + + f_struct device_media || return $FAILURE +} + +# f_media_init_floppy $device +# +# Initializes the Floppy media device. Returns success if able to mount the +# Floppy disk device using either mount_msdosfs(8) or mount(8) (tried in that +# order). +# +f_media_init_floppy() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init floppy called for %s distribution. devname=[%s]" \ + "${FLOPPY_DISTWANTED:-some}" "$devname" + + if [ "$FLOPPY_MOUNTED" ]; then + f_dprintf "Floppy device already mounted." + return $SUCCESS + fi + + local mp + device_$dev get private mp + if [ ! -e "${mp:=$MOUNTPOINT}" ] && ! f_quietly mkdir -p "$mp"; then + f_show_msg "$msg_unable_to_make_directory_mountpoint" \ + "$mp" "$devname" + return $FAILURE + fi + + if f_interactive; then + local desc + device_$dev get desc desc + if [ "$FLOPPY_DISTWANTED" ]; then + f_show_msg "$msg_please_insert_floppy_in_drive" "$desc" + else + f_show_msg "$msg_please_insert_floppy_containing" \ + "$FLOPPY_DISTWANTED" "$desc" + fi + fi + + if ! { + f_quietly mount_msdosfs -o ro -m 0777 -u 0 -g 0 "$devname" "$mp" || + err=$( mount -o ro "$devname" "$mp" 2>&1 ) + }; then + err="${err#mount: }"; err="${err#*: }" + local name + device_$dev get name name + f_show_msg "$msg_error_mounting_floppy_device" \ + "$name" "$devname" "$mp" "$err" + return $FAILURE + fi + FLOPPY_MOUNTED=1 + FLOPPY_DISTWANTED= + return $SUCCESS +} + +# f_media_get_floppy $device $file [$probe_only] +# +# Returns data from $file on a mounted Floppy disk device. Similar to cat(1). +# If $probe_only is present and non-null, limits retries to zero. +# +f_media_get_floppy() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + # + # floppies don't use f_media_generic_get() because it's too expensive + # to speculatively open files on a floppy disk. Make user get it + # right or give up with floppies. + # + local mp + device_$dev get private mp + local fp="${mp:=$MOUNTPOINT}/$file" + if ! [ -f "$fp" -a -r "$fp" ]; then + local nretries=4 + [ "$probe_only" ] && return $FAILURE + while ! [ -f "$fp" -a -r "$fp" ]; do + if [ $nretries -eq 0 ]; then + f_show_msg "$msg_failed_to_get_floppy_file" \ + "$fp" + return $FAILURE + fi + FLOPPY_DISTWANTED="$fp" + f_media_shutdown_floppy "$dev" + f_media_init_floppy "$dev" || return $FAILURE + nretries=$(( $nretries - 1 )) + done + fi + cat "$fp" +} + +# f_media_shutdown_floppy $device +# +# Shuts down the Floppy disk device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_floppy() +{ + local dev="$1" err mp + + [ "$FLOPPY_MOUNTED" ] || return + + device_$dev get private mp + if ! err=$( umount -f "${mp:=$MOUNTPOINT}" 2>&1 ); then + err="${err#umount: }"; err="${err#*:}" + f_dprintf "Umount of floppy on %s failed: %s" "$mp" "$err" + else + FLOPPY_MOUNTED= + if f_interactive && [ "$_systemState" != "fixit" ]; then + local desc + device_$dev get desc desc + f_show_msg "$msg_you_may_remove_the_floppy" "$desc" + fi + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/floppy.subr + +fi # ! $_MEDIA_FLOPPY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/ftp.subr b/usr.sbin/bsdconfig/share/media/ftp.subr new file mode 100644 index 0000000..ecc7724 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ftp.subr @@ -0,0 +1,893 @@ +if [ ! "$_MEDIA_FTP_SUBR" ]; then _MEDIA_FTP_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/ftp.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr +f_include $BSDCFG_SHARE/media/tcpip.subr +f_include $BSDCFG_SHARE/media/network.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +FTP_SKIP_RESOLV= + +URL_MAX=261261 # according to actual fetch(1) test-results + +FTP_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_ftp +# +# Prompt the user to select from a range of ``built-in'' FTP 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 variables.subr) and returns success. +# +f_dialog_menu_media_ftp() +{ + f_dialog_title "$msg_please_select_a_freebsd_ftp_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 hline="$msg_select_a_site_thats_close" + local menu_list=" + '$msg_main_site' 'ftp.freebsd.org' + 'URL' '$msg_specify_some_other_ftp_site' + '$msg_snapshots_server_japan' + 'snapshots.jp.freebsd.org' + '$msg_snapshots_server_sweden' + 'snapshots.se.freebsd.org' + 'IPv6 $msg_main_site' 'ftp.freebsd.org' + ' IPv6 $msg_ireland' 'ftp3.ie.freebsd.org' + ' IPv6 $msg_israel' 'ftp.il.freebsd.org' + ' IPv6 $msg_japan' 'ftp2.jp.freebsd.org' + ' IPv6 $msg_usa' 'ftp4.us.freebsd.org' + ' IPv6 $msg_turkey' 'ftp2.tr.freebsd.org' + '$msg_primary' 'ftp1.freebsd.org' + ' $msg_primary #2' 'ftp2.freebsd.org' + ' $msg_primary #3' 'ftp3.freebsd.org' + ' $msg_primary #4' 'ftp4.freebsd.org' + ' $msg_primary #5' 'ftp5.freebsd.org' + ' $msg_primary #6' 'ftp6.freebsd.org' + ' $msg_primary #7' 'ftp7.freebsd.org' + ' $msg_primary #8' 'ftp8.freebsd.org' + ' $msg_primary #9' 'ftp9.freebsd.org' + ' $msg_primary #10' 'ftp10.freebsd.org' + ' $msg_primary #11' 'ftp11.freebsd.org' + ' $msg_primary #12' 'ftp12.freebsd.org' + ' $msg_primary #13' 'ftp13.freebsd.org' + ' $msg_primary #14' 'ftp14.freebsd.org' + '$msg_argentina' 'ftp.ar.freebsd.org' + '$msg_australia' 'ftp.au.freebsd.org' + ' $msg_australia #2' 'ftp2.au.freebsd.org' + ' $msg_australia #3' 'ftp3.au.freebsd.org' + '$msg_austria' 'ftp.at.freebsd.org' + ' $msg_austria #2' 'ftp2.at.freebsd.org' + '$msg_brazil' 'ftp.br.freebsd.org' + ' $msg_brazil #2' 'ftp2.br.freebsd.org' + ' $msg_brazil #3' 'ftp3.br.freebsd.org' + ' $msg_brazil #4' 'ftp4.br.freebsd.org' + ' $msg_brazil #5' 'ftp5.br.freebsd.org' + ' $msg_brazil #6' 'ftp6.br.freebsd.org' + ' $msg_brazil #7' 'ftp7.br.freebsd.org' + '$msg_canada' 'ftp.ca.freebsd.org' + '$msg_china' 'ftp.cn.freebsd.org' + ' $msg_china #2' 'ftp2.cn.freebsd.org' + '$msg_croatia' 'ftp.hr.freebsd.org' + '$msg_czech_republic' 'ftp.cz.freebsd.org' + '$msg_denmark' 'ftp.dk.freebsd.org' + ' $msg_denmark #2' 'ftp2.dk.freebsd.org' + '$msg_estonia' 'ftp.ee.freebsd.org' + '$msg_finland' 'ftp.fi.freebsd.org' + '$msg_france' 'ftp.fr.freebsd.org' + ' $msg_france #2' 'ftp2.fr.freebsd.org' + ' $msg_france #3' 'ftp3.fr.freebsd.org' + ' $msg_france #5' 'ftp5.fr.freebsd.org' + ' $msg_france #6' 'ftp6.fr.freebsd.org' + ' $msg_france #8' 'ftp8.fr.freebsd.org' + '$msg_germany' 'ftp.de.freebsd.org' + ' $msg_germany #2' 'ftp2.de.freebsd.org' + ' $msg_germany #3' 'ftp3.de.freebsd.org' + ' $msg_germany #4' 'ftp4.de.freebsd.org' + ' $msg_germany #5' 'ftp5.de.freebsd.org' + ' $msg_germany #6' 'ftp6.de.freebsd.org' + ' $msg_germany #7' 'ftp7.de.freebsd.org' + ' $msg_germany #8' 'ftp8.de.freebsd.org' + '$msg_greece' 'ftp.gr.freebsd.org' + ' $msg_greece #2' 'ftp2.gr.freebsd.org' + '$msg_hungary' 'ftp.hu.freebsd.org' + '$msg_iceland' 'ftp.is.freebsd.org' + '$msg_ireland' 'ftp.ie.freebsd.org' + ' $msg_ireland #2' 'ftp2.ie.freebsd.org' + ' $msg_ireland #3' 'ftp3.ie.freebsd.org' + '$msg_israel' 'ftp.il.freebsd.org' + '$msg_italy' 'ftp.it.freebsd.org' + '$msg_japan' 'ftp.jp.freebsd.org' + ' $msg_japan #2' 'ftp2.jp.freebsd.org' + ' $msg_japan #3' 'ftp3.jp.freebsd.org' + ' $msg_japan #4' 'ftp4.jp.freebsd.org' + ' $msg_japan #5' 'ftp5.jp.freebsd.org' + ' $msg_japan #6' 'ftp6.jp.freebsd.org' + ' $msg_japan #7' 'ftp7.jp.freebsd.org' + ' $msg_japan #8' 'ftp8.jp.freebsd.org' + ' $msg_japan #9' 'ftp9.jp.freebsd.org' + '$msg_korea' 'ftp.kr.freebsd.org' + ' $msg_korea #2' 'ftp2.kr.freebsd.org' + '$msg_lithuania' 'ftp.lt.freebsd.org' + '$msg_netherlands' 'ftp.nl.freebsd.org' + ' $msg_netherlands #2' 'ftp2.nl.freebsd.org' + '$msg_norway' 'ftp.no.freebsd.org' + ' $msg_norway #3' 'ftp3.no.freebsd.org' + '$msg_poland' 'ftp.pl.freebsd.org' + ' $msg_poland #2' 'ftp2.pl.freebsd.org' + ' $msg_poland #5' 'ftp5.pl.freebsd.org' + '$msg_portugal' 'ftp.pt.freebsd.org' + ' $msg_portugal #2' 'ftp2.pt.freebsd.org' + ' $msg_portugal #4' 'ftp4.pt.freebsd.org' + '$msg_romania' 'ftp.ro.freebsd.org' + '$msg_russia' 'ftp.ru.freebsd.org' + ' $msg_russia #2' 'ftp2.ru.freebsd.org' + ' $msg_russia #3' 'ftp3.ru.freebsd.org' + ' $msg_russia #4' 'ftp4.ru.freebsd.org' + '$msg_singapore' 'ftp.sg.freebsd.org' + '$msg_slovak_republic' 'ftp.sk.freebsd.org' + '$msg_slovenia' 'ftp.si.freebsd.org' + ' $msg_slovenia #2' 'ftp2.si.freebsd.org' + '$msg_south_africa' 'ftp.za.freebsd.org' + ' $msg_south_africa #2' 'ftp2.za.freebsd.org' + ' $msg_south_africa #3' 'ftp3.za.freebsd.org' + ' $msg_south_africa #4' 'ftp4.za.freebsd.org' + '$msg_spain' 'ftp.es.freebsd.org' + ' $msg_spain #2' 'ftp2.es.freebsd.org' + ' $msg_spain #3' 'ftp3.es.freebsd.org' + '$msg_sweden' 'ftp.se.freebsd.org' + ' $msg_sweden #2' 'ftp2.se.freebsd.org' + ' $msg_sweden #3' 'ftp3.se.freebsd.org' + ' $msg_sweden #4' 'ftp4.se.freebsd.org' + ' $msg_sweden #5' 'ftp5.se.freebsd.org' + '$msg_switzerland' 'ftp.ch.freebsd.org' + ' $msg_switzerland #2' 'ftp2.ch.freebsd.org' + '$msg_taiwan' 'ftp.tw.freebsd.org' + ' $msg_taiwan #2' 'ftp2.tw.freebsd.org' + ' $msg_taiwan #3' 'ftp3.tw.freebsd.org' + ' $msg_taiwan #4' 'ftp4.tw.freebsd.org' + ' $msg_taiwan #6' 'ftp6.tw.freebsd.org' + ' $msg_taiwan #11' 'ftp11.tw.freebsd.org' + '$msg_turkey' 'ftp.tr.freebsd.org' + ' $msg_turkey #2' 'ftp2.tr.freebsd.org' + '$msg_uk' 'ftp.uk.freebsd.org' + ' $msg_uk #2' 'ftp2.uk.freebsd.org' + ' $msg_uk #3' 'ftp3.uk.freebsd.org' + ' $msg_uk #4' 'ftp4.uk.freebsd.org' + ' $msg_uk #5' 'ftp5.uk.freebsd.org' + ' $msg_uk #6' 'ftp6.uk.freebsd.org' + '$msg_ukraine' 'ftp.ua.freebsd.org' + ' $msg_ukraine #2' 'ftp2.ua.freebsd.org' + ' $msg_ukraine #5' 'ftp5.ua.freebsd.org' + ' $msg_ukraine #6' 'ftp6.ua.freebsd.org' + ' $msg_ukraine #7' 'ftp7.ua.freebsd.org' + ' $msg_ukraine #8' 'ftp8.ua.freebsd.org' + '$msg_usa #1' 'ftp1.us.freebsd.org' + ' $msg_usa #2' 'ftp2.us.freebsd.org' + ' $msg_usa #3' 'ftp3.us.freebsd.org' + ' $msg_usa #4' 'ftp4.us.freebsd.org' + ' $msg_usa #5' 'ftp5.us.freebsd.org' + ' $msg_usa #6' 'ftp6.us.freebsd.org' + ' $msg_usa #7' 'ftp7.us.freebsd.org' + ' $msg_usa #8' 'ftp8.us.freebsd.org' + ' $msg_usa #9' 'ftp9.us.freebsd.org' + ' $msg_usa #10' 'ftp10.us.freebsd.org' + ' $msg_usa #11' 'ftp11.us.freebsd.org' + ' $msg_usa #12' 'ftp12.us.freebsd.org' + ' $msg_usa #13' 'ftp13.us.freebsd.org' + ' $msg_usa #14' 'ftp14.us.freebsd.org' + ' $msg_usa #15' 'ftp15.us.freebsd.org' + " # END-QUOTE + + local size + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu retval mtag value + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$prompt\" $size \ + $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + mtag=$( f_dialog_menutag ) + + [ $retval -eq 0 ] || return $FAILURE + + case "$mtag" in + URL) setvar $VAR_FTP_PATH "other" ;; + *) + value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list ) + setvar $VAR_FTP_PATH "ftp://$value" + esac + + return $SUCCESS +} + +# f_media_set_ftp +# +# Return success if we both found and set the media type to be an FTP server. +# Variables from variable.subr that can be used to script user input: +# +# VAR_FTP_PATH +# Can be a URL (including "ftp://" protocol-prefix) or "other" +# (user is prompted to enter FTP URL). If a URL, can optionally +# contain directory prefix after hostname/port. Valid examples +# include: +# ftp://myhost +# ftp://somename:21/pub/ +# ftp://192.168.2.3/pub/ +# ftp://[::1]:21/ +# The default port if not specified is 21. +# 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_FTP_HOST +# The FTP host to connect to, parsed from VAR_FTP_PATH. In the +# example case of IPv6 where VAR_FTP_PATH is a "ftp://[::1]" this +# variable will be set to "::1" (the outer brackets are removed). +# VAR_FTP_PORT +# The TCP port to connect to, parsed from VAR_FTP_PATH. Usually +# 21 unless VAR_FTP_PATH was of one of the following forms: +# ftp://hostname:OTHER_PORT +# ftp://hostname:OTHER_PORT/* +# ftp://ip:OTHER_PORT +# ftp://ip:OTHER_PORT/* +# ftp://[ip6]:OTHER_PORT +# ftp://[ip6]:OTHER_PORT/* +# VAR_FTP_DIR +# If VAR_FTP_PATH contained a directory element (e.g., +# "ftp://localhost/pub") this variable contains only the +# directory element (e.g., "/pub"). +# +f_media_set_ftp() +{ + f_media_close + + local url + f_getvar $VAR_FTP_PATH url + + # If we've been through here before ... + if f_struct device_network && [ "${url#$msg_other}" ]; then + f_dialog_yesno "$msg_reuse_old_ftp_site_selection_values" || + url= + fi + + if [ ! "$url" ]; then + f_dialog_menu_media_ftp || return $FAILURE + f_getvar $VAR_FTP_PATH url + fi + [ "$url" ] || return $FAILURE + + case "$url" in + other) + setvar $VAR_FTP_PATH "ftp://" + f_variable_get_value $VAR_FTP_PATH \ + "$msg_please_specify_url_of_a_freebsd_distribution" + f_getvar $VAR_FTP_PATH url + if [ ! "${url#ftp://}" ]; then + unset $VAR_FTP_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_FTP_PATH + return $FAILURE + fi + case "$url" in + ftp://*) : valid URL ;; + *) + f_show_msg "$msg_sorry_invalid_url" "$url" + unset $VAR_FTP_PATH + return $FAILURE + esac + esac + case "$url" in + ftp://*) : valid URL ;; + *) + f_show_msg "$msg_sorry_invalid_url" "$url" + unset $VAR_FTP_PATH + return $FAILURE + esac + + # Set the name of the FTP device to the URL + f_struct_new DEVICE device_ftp + device_ftp 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_FTP_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_ftp: %s" "$msg_net_device_init_failed" + unset $VAR_FTP_PATH + return $FAILURE + fi + + local hostname="${url#*://}" port=21 dir=/ + case "$hostname" in + "["*"]") + hostname="${hostname#\[}" + hostname="${hostname%%\]*}" + ;; + "["*"]/"*) + hostname="${hostname#\[}" + dir="/${hostname#*/}" + hostname="${hostname%%\]*}" + ;; + *"/"*) + dir="/${hostname#*/}" + hostname="${hostname%%/*}" + ;; + "["*"]:"*) + hostname="${hostname#\[}" + port="${hostname#*\]:}" + port="${port%%[!0-9]*}" + hostname="${hostname%%\]:*}" + ;; + *) + hostname="${hostname%%/*}" + 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 ! "$FTP_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_ftp" "$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_FTP_PATH + return $FAILURE + fi + f_dprintf "Found DNS entry for %s successfully." "$hostname" + fi + + setvar $VAR_FTP_HOST "$hostname" + setvar $VAR_FTP_PORT "$port" + setvar $VAR_FTP_DIR "$dir" + + device_ftp set type $DEVICE_TYPE_FTP + device_ftp set init f_media_init_ftp + device_ftp set get f_media_get_ftp + device_ftp set shutdown f_media_shutdown_ftp + device_ftp set private network + f_struct_copy device_ftp device_media + f_struct_free device_ftp + + return $SUCCESS +} + +# f_media_set_ftp_active +# +# Wrapper to f_media_set_ftp to access FTP servers actively. +# +f_media_set_ftp_active() +{ + setvar $VAR_FTP_STATE "active" + f_media_set_ftp +} + +# f_media_set_ftp_passive +# +# Wrapper to f_media_set_ftp to access FTP servers passively. +# +f_media_set_ftp_passive() +{ + setvar $VAR_FTP_STATE "passive" + f_media_set_ftp +} + +# f_media_set_ftp_userpass +# +# Prompt the user to enter/confirm the username/password variables that will +# be used to communicate with the FTP servers. Returns success if the user does +# not cancel or press Esc to either username or password. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_FTP_USER +# The username to send via ftp(1) when connecting to an FTP +# server. +# VAR_FTP_PASS +# The password to send with the above username. +# +# Does not prompt for confirmation of values if VAR_NONINTERACTIVE is set (see +# variable.subr for more information). +# +f_media_set_ftp_userpass() +{ + local user pass + f_variable_get_value $VAR_FTP_USER \ + "$msg_please_enter_the_username_you_wish_to_login_as" + f_getvar $VAR_FTP_USER user + if [ "$user" ]; then + f_variable_get_value $VAR_FTP_PASS \ + "$msg_please_enter_the_password_for_this_user" + f_getvar $VAR_FTP_PASS pass + else + pass= + fi + [ "$pass" ] # Return status +} + +# f_device_network_up $device +# +# Brings up attached network device, if any - takes FTP device as arg. +# +f_device_network_up() +{ + local dev="$1" netDev + device_$dev get private netDev || return $SUCCESS # No net == happy net + f_device_init $netDev +} + +# f_device_network_down $device +# +# Brings down attached network device, if any - takes FTP device as arg. +# +f_device_network_down() +{ + local dev="$1" netDev + device_$dev get private netDev || return $SUCCESS + f_device_shutdown $netDev +} + +# f_media_init_ftp $device +# +# Initializes the FTP media device. Returns success if both able to log into +# the FTP server and confirm the existence of at least one known release path +# using ftp(1). +# +# Variables from variable.subr used to initialize the connection are as follows +# (all of which are configured by f_media_set_ftp above): +# +# VAR_FTP_PATH +# The unparsed FTP URL representing the server to contact. +# Usually "ftp://server" for example. Can contain TCP port number +# and/or directory path (but should not contain username/password +# info). +# VAR_FTP_HOST +# The FTP host to connect to. Can be an IPv4 address (e.g., +# 127.0.0.1), IPv6 address (e.g., ::1), or DNS hostname. Usually +# set automatically in f_media_set_ftp() by parsing VAR_FTP_PATH. +# VAR_FTP_PORT +# The TCP port to connect to. Usually set automatically in +# f_media_set_ftp() by parsing VAR_FTP_PATH. +# VAR_FTP_DIR +# The base FTP directory to use when downloading files from the +# FTP server. Usually set automatically in f_media_set_ftp() by +# parsing VAR_FTP_PATH. +# VAR_FTP_USER [Optional] +# If unset, defaults to using anonymous access. +# VAR_FTP_PASS [Optional] +# If unset, defaults to a sensible value. +# +# In addition, the following (managed either manually or by f_media_set_ftp_*): +# +# VAR_FTP_STATE +# Sets FTPMODE for ftp(1) and can be one of: +# active active mode FTP only +# auto automatic determination of passive or active +# (this is the default) +# gate gate-ftp mode +# passive passive mode FTP only +# See ftp(1) for additional information. +# +# And last, but not least (managed automatically or manually): +# +# VAR_RELNAME +# Defaults to being set to $(uname -r) but can be overridden. +# This sets the name of a release to look for as part of a well +# known set of paths to search for release data once connected +# via FTP. If set to "__RELEASE" or "any" then the VAR_FTP_DIR is +# taken as the absolute path to the release and no further +# searching is done (see FTP_DIRS above in the GLOBALS section +# for a list of well known paths that are used when searching for +# a VAR_RELNAME sub-directory). +# +f_media_init_ftp() +{ + local dev="$1" + + local url + device_$dev get name url + f_dprintf "Init routine called for FTP device. url=[%s]" "$url" + + if [ "$FTP_INITIALIZED" ]; then + f_dprintf "FTP device already initialized." + return $SUCCESS + fi + + # If we can't initialize the network, bag it! + f_device_network_up $dev || return $FAILURE + + local cp + while :; do + f_getvar $VAR_FTP_PATH cp + if [ ! "$cp" ]; then + if ! f_media_set_ftp || + ! f_getvar $VAR_FTP_PATH cp || + [ ! "$cp" ] + then + f_dialog_msgbox \ + "$msg_unable_to_get_proper_ftp_path" + f_device_network_down $dev + return $FAILURE + fi + fi + + local ftp_host ftp_dir + if ! { + f_getvar $VAR_FTP_HOST ftp_host && + f_getvar $VAR_FTP_DIR ftp_dir + }; then + f_dialog_msgbox "$msg_missing_ftp_host_or_directory" + f_device_network_down $dev + return $FAILURE + fi + + local ftp_port + f_getvar $VAR_FTP_PORT ftp_port + local host="$ftp_host" port="${ftp_port:+:$ftp_port}" + case "$host" in *:*) host="[$host]"; esac + + local user pass use_anon="" + f_getvar $VAR_FTP_USER user + if [ ! "$user" ]; then + user="anonymous" + use_anon=1 + fi + if ! f_getvar $VAR_FTP_PASS pass; then + f_getvar $VAR_HOSTNAME cp + if f_running_as_init; then + pass="installer@$cp" + else + local name="$( id -un 2> /dev/null )" + pass="${name:-ftp}@$cp" + fi + fi + + f_show_info "$msg_logging_in_to_user_at_host" \ + "$user" "$ftp_host" + + local userpass="" + if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then + userpass="$user${pass:+:$( f_uriencode "$pass" )}" + userpass="$userpass${userpass:+@}" + fi + + local mode rx + f_getvar $VAR_FTP_STATE mode + + if [ "$ftp_dir" ]; then + if ! rx=$( + printf 'cd "%s"\npwd\n' "$ftp_dir" | eval \ + FTPMODE=\"\$mode\" \ + ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} \ + \"ftp://\$userpass\$host\$port\" \ + 2>&1 + ); then + f_show_msg "$msg_couldnt_open_ftp_connection" \ + "$ftp_host" "$rx" + break # to failure + fi + if echo "$rx" | awk -v dir="/${ftp_dir#/}" ' + BEGIN { found = 0 } + /^Remote directory: / { + sub(/^[^:]*:[[:space:]]*/, "") + if ($0 != dir) next + found = 1; exit + } + END { exit ! found } + '; then + setvar $VAR_FTP_DIR "$ftp_dir" + setvar $VAR_FTP_PATH \ + "ftp://$ftp_host/${ftp_dir#/}" + else + f_show_msg \ + "$msg_please_check_the_url_and_try_again" \ + "ftp://$ftp_host/${ftp_dir#/}" + break # to failure + fi + fi + + # + # 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_ftp: rel=[%s]" "$rel" + + case "$rel" in + __RELEASE|any) + FTP_INITIALIZED=YES + return $SUCCESS + ;; + *) + # + # Ok, since we have a release variable, let's walk + # through the list of directories looking for a release + # directory. First successful CWD wins. + # + if ! rx=$( + for dir in $FTP_DIRS; do + # Avoid confusing some servers + [ "$dir" = "." ] && continue + printf 'cd "/%s/%s"\npwd\n' \ + "$dir" "$rel" + done | eval \ + FTPMODE=\"\$mode\" \ + ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} \ + \"ftp://\$userpass\$host\$port\" \ + 2>&1 + ); then + f_show_msg "$msg_couldnt_open_ftp_connection" \ + "$ftp_host" "$rx" + break # to failure + fi + + local fdir + if fdir=$( echo "$rx" | awk ' + BEGIN { found = 0 } + /^Remote directory: / { + sub(/^[^:]*:[[:space:]]*/, "") + if ($0 == "/") next + # Exit after the first dir + found++; print; exit + } + END { exit ! found } + ' ); then + setvar $VAR_FTP_DIR "$fdir" + setvar $VAR_FTP_PATH "ftp://$ftp_host$fdir" + FTP_INITIALIZED=YES + return $SUCCESS + else + f_yesno "$msg_cant_find_distribution" \ + "$rel" "$ftp_host" + if [ $? -eq $SUCCESS ]; then + unset $VAR_FTP_PATH + f_media_set_ftp && continue + fi + fi + esac + break # to failure + done + + unset FTP_INITIALIZED $VAR_FTP_PATH + f_device_network_down $dev + return $FAILURE +} + +# f_media_get_ftp $device $file [$probe_only] +# +# Returns data from $file on an FTP server using ftp(1). Please note that +# $device is unused but must be present (even if null). Information is instead +# gathered from the environment. $probe_only is currently unused by this media +# type. +# +# Variables from variable.subr used to configure the connection are as follows +# (all of which are configured by f_media_set_ftp above): +# +# VAR_FTP_HOST +# FTP host to connect to. Can be an IPv4 address, IPv6 address, +# or DNS hostname of your choice. +# VAR_FTP_PORT +# TCP port to connect on; see f_media_set_ftp() above. +# VAR_FTP_USER [Optional] +# If unset, defaults to using anonymous access. +# VAR_FTP_PASS [Optional] +# If unset, defaults to a sensible value. +# +# In addition, the following (managed either manually or by f_media_set_ftp_*): +# +# VAR_FTP_STATE +# Sets FTPMODE for ftp(1) and can be one of: +# active active mode FTP only +# auto automatic determination of passive or active +# (this is the default) +# gate gate-ftp mode +# passive passive mode FTP only +# See ftp(1) for additional information. +# +# See variable.subr for additional information. +# +# Example usage: +# f_media_set_ftp +# f_media_get_ftp media $file +# +f_media_get_ftp() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + local ftp_host ftp_port + f_getvar $VAR_FTP_HOST ftp_host + f_getvar $VAR_FTP_PORT ftp_port + + if [ ! "$FTP_INITIALIZED" ]; then + f_dprintf "No FTP connection open, can't get file %s" "$file" + return $FAILURE + fi + + if ! { + f_validate_ipaddr "$ftp_host" || + f_validate_ipaddr6 "$ftp_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_media_get_ftp" "$ftp_host" + f_host_lookup "$ftp_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="$ftp_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$ftp_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_ftp_server %s:%s" \ + "$ftp_host" "$ftp_port" + return $FAILURE + fi + + local user pass use_anon="" + f_getvar $VAR_FTP_USER user + if [ ! "$user" ]; then + user="anonymous" + use_anon=1 + fi + if ! f_getvar $VAR_FTP_PASS pass; then + f_getvar $VAR_HOSTNAME cp + if f_running_as_init; then + pass="installer@$cp" + else + local name="$( id -un 2> /dev/null )" + pass="${name:-ftp}@$cp" + fi + fi + + local userpass="" + if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then + userpass="$user${pass:+:$( f_uriencode "$pass" )}" + userpass="$userpass${userpass:+@}" + fi + + local ftp_dir mode rx + f_getvar $VAR_FTP_DIR ftp_dir + f_getvar $VAR_FTP_STATE mode + + local dir="${ftp_dir#/}" + local port="${ftp_port:+:$ftp_port}" + case "$host" in *:*) host="[$host]"; esac + + f_dprintf "sending ftp request for: %s" "ftp://$host$port/$dir/$file" + + eval FTPMODE=\"\$mode\" ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} -o - \ + \"ftp://\$userpass\$host\$port/\$dir/\$file\" 2> /dev/null + local retval=$? + + [ $retval -eq $SUCCESS ] || f_dprintf "request failed!" + return $retval +} + +# f_media_shutdown_ftp $device +# +# Shuts down the FTP device. Return status should be ignored. Note that since +# we don't maintain an open connection to the FTP server there's nothing to do. +# +f_media_shutdown_ftp() +{ + [ "$FTP_INITIALIZED" ] || return $SUCCESS + + unset FTP_INITIALIZED +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/ftp.subr + +fi # ! $_MEDIA_FTP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/httpproxy.subr b/usr.sbin/bsdconfig/share/media/httpproxy.subr new file mode 100644 index 0000000..fad1007 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/httpproxy.subr @@ -0,0 +1,433 @@ +if [ ! "$_MEDIA_HTTPPROXY_SUBR" ]; then _MEDIA_HTTPPROXY_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/httpproxy.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/ftp.subr +f_include $BSDCFG_SHARE/media/tcpip.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ FUNCTIONS + +# f_media_set_http_proxy +# +# Return success if we both found and set the media type to be an ftp server, +# accessed via http proxy. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_HTTP_PROXY +# HTTP Proxy server to use. Valid examples include: +# myhost +# somename:3128 +# 192.168.2.3 +# [::1]:8080 +# The default port if not specified is 3128. +# +# Variables from variable.subr that are set after successful execution include +# the following: +# +# VAR_HTTP_PROXY_HOST The host portion of VAR_HTTP_PROXY. +# VAR_HTTP_PROXY_PORT The TCP port parsed from VAR_HTTP_PROXY. +# +# See also f_media_set_ftp() for additional variables. +# +f_media_set_http_proxy() +{ + FTP_SKIP_RESOLV=1 f_media_set_ftp || return $FAILURE + + f_variable_get_value $VAR_HTTP_PROXY \ + "$msg_please_enter_the_address_of_the_http_proxy" + + local proxy + f_getvar $VAR_HTTP_PROXY proxy + [ "$proxy" ] || return $FAILURE + + local hostname="$proxy" port=3128 + case "$hostname" in + "["*"]") + hostname="${hostname#\[}" + hostname="${hostname%\]}" + ;; + "["*"]:") + hostname="${hostname#\[}" + port="${hostname#*\]:}" + port="${port%%[!0-9]*}" + hostname="${hostname%%\]:*}" + ;; + *":"*) + port="${hostname#*:}" + hostname="${hostname%%:*}" + esac + + setvar $VAR_HTTP_PROXY_HOST "$hostname" + setvar $VAR_HTTP_PROXY_PORT "$port" + + if f_debugging; then + f_dprintf "VAR_FTP_PATH : %s" "$( f_getvar $VAR_FTP_PATH )" + f_dprintf "VAR_HTTP_PROXY_HOST, _PORT: %s:%s" \ + "$( f_getvar $VAR_HTTP_PROXY_HOST )" \ + "$( f_getvar $VAR_HTTP_PROXY_PORT )" + fi + + # media device has been set by f_media_set_ftp(), overwrite partly: + device_media set type $DEVICE_TYPE_HTTP_PROXY + device_media set init f_media_init_http_proxy + device_media set get f_media_get_http_proxy + device_media unset shutdown + + return $SUCCESS +} + +# f_http_proxy_check_access [$connect_only] +# +# Return success if able list a remote FTP directory via HTTP proxy. 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_PROXY_HOST +# The HTTP proxy server host name, IPv4 address or IPv6 address. +# Valid examples include: +# myhost +# 192.168.2.3 +# ::1 +# VAR_HTTP_PROXY_PORT +# The TCP port to connect to when communicating with the HTTP +# proxy server. +# VAR_HTTP_PROXY_PATH +# The FTP URL sent to the HTTP proxy server. Unused if +# $connect_only is present and non-NULL. +# +f_http_proxy_check_access() +{ + local connect_only="$1" hosts="" + + local proxy_host proxy_port + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + f_getvar $VAR_HTTP_PROXY_PORT proxy_port + + if ! { + f_validate_ipaddr "$proxy_host" || + f_validate_ipaddr6 "$proxy_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_http_proxy_check_access" "$proxy_host" + f_host_lookup "$proxy_host" hosts + } + }; then + # All the above validations failed + [ "$hosts" ] && f_dialog_msgbox "$hosts" + unset $VAR_HTTP_PROXY_HOST + return $FAILURE + elif [ ! "$hosts" ]; then + # One of the first two validations passed + hosts="$proxy_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$proxy_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + unset $VAR_HTTP_PROXY_HOST + return $FAILURE + fi + [ "$connect_only" ] && return $SUCCESS + + # + # Some proxies fetch files with certain extensions in "ascii mode" + # instead of "binary mode" for FTP. The FTP server then translates all + # LF to CRLF. + # + # You can force Squid to use binary mode by appending ";type=i" to the + # URL, which is what sysinstall(8) has traditionally done. + # + + local proxy_path + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_show_info "$msg_checking_access_to" "$proxy_path" + + local rx + if ! rx=$( + printf "GET %s/ HTTP/1.0\r\n\r\n" "${proxy_path%/}" | + nc -n "$host" "$proxy_port" + ); then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + unset $VAR_HTTP_PROXY_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 + + # + # Scan the headers of the response + # this is extremely quick'n dity + # + + unset $VAR_HTTP_FTP_MODE + if echo "$hdr" | awk ' + BEGIN { found = 0 } + { + if (!match($0, /^Server: /)) next + found = ( substr($0, 9, 5) ~ /[Ss]quid/ ) + } + END { exit ! found } + '; then + setvar $VAR_HTTP_FTP_MODE ";type=i" + else + setvar $VAR_HTTP_FTP_MODE "" + fi + + return $http_found +} + +# f_media_init_http_proxy $device +# +# Initializes the HTTP Proxy media device. Returns success if able to confirm +# the existence of at least one known FTP server release path via HTTP proxy +# using f_http_proxy_check_access(), above. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_HTTP_PROXY_HOST +# The HTTP proxy server to connect to. Usually set by having +# f_media_set_http_proxy() parse VAR_HTTP_PROXY. Must be set. +# Also see f_http_proxy_check_access() for additional variables. +# VAR_RELNAME +# Usually set to `uname -r' but can be overridden. +# VAR_FTP_PATH +# The FTP URL to send to the HTTP proxy server. Usually set by +# calling f_media_set_ftp(). +# +# Meanwhile, after successful execution, the following variables (also from +# variable.subr) are set: +# +# VAR_HTTP_PROXY_PATH +# The [possibly] adjusted VAR_FTP_PATH that was found to contain +# a valid FreeBSD repository. +# +f_media_init_http_proxy() +{ + local dev="$1" + f_dprintf "Init routine called for HTTP Proxy device. dev=[%s]" "$dev" + + # + # First verify access + # + local connect_only=1 + f_http_proxy_check_access $connect_only + + local proxy_host + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + while [ ! "$proxy_host" ]; do + f_media_set_http_proxy || return $FAILURE + f_http_proxy_check_access $connect_only + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + done + + local rel proxy_path http_found=$FAILURE + while :; do + # + # If the release is specified as "__RELEASE" or "any", then + # just assume that the path the user gave is ok. + # + f_getvar $VAR_RELNAME rel + f_dprintf "f_media_init_http_proxy: rel=[%s]" "$rel" + + case "$rel" in + __RELEASE|any) + f_getvar $VAR_FTP_PATH $VAR_HTTP_PROXY_PATH + f_http_proxy_check_access + http_found=$? + ;; + *) + local fdir fp + f_getvar $VAR_FTP_PATH fp + for fdir in $FTP_DIRS; do + setvar $VAR_HTTP_PROXY_PATH "$fp/$fdir/$rel" + if f_http_proxy_check_access; then + http_found=$SUCCESS + break + fi + done + esac + + [ $http_found -eq $SUCCESS ] && break + + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_show_msg "$msg_please_check_the_url_and_try_again" \ + "$proxy_path" + + unset $VAR_HTTP_PROXY_PATH + f_media_set_http_proxy || break + done + + return $http_found +} + +# f_media_get_http_proxy $device $file [$probe_only] +# +# Returns data from $file on an FTP server via HTTP proxy using nc(1). Please +# note that $device is unused but must be present (even if null). Information +# is instead gathered from the environment. $probe_only is currently unused by +# this media type. +# +# The variables used to configure the connection are as follows (all of which +# are configured by f_media_set_http_proxy above): +# +# VAR_HTTP_PROXY_HOST +# HTTP proxy host to connect. Can be an IPv4 address, IPv6 +# address, or DNS hostname of your choice. +# VAR_HTTP_PROXY_PORT +# TCP port to connect on; see f_media_set_http_proxy above. +# VAR_HTTP_PROXY_PATH +# URL (including "ftp://" protocol-prefix) of FTP directory to +# use as a prefix when requesting $file via HTTP proxy. +# +# See variable.subr for additional information. +# +# Example usage: +# f_media_set_http_proxy +# f_media_get_http_proxy media $file +# +f_media_get_http_proxy() +{ + local dev="$1" file="$2" probe_only="$3" hosts= + + f_dprintf "f_media_get_http_proxy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + local proxy_host proxy_port + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + f_getvar $VAR_HTTP_PROXY_PORT proxy_port + + if ! { + f_validate_ipaddr "$proxy_host" || + f_validate_ipaddr6 "$proxy_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_media_get_http_proxy" "$proxy_host" + f_host_lookup "$proxy_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="$proxy_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$proxy_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + return $FAILURE + fi + + local proxy_path mode + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_getvar $VAR_HTTP_FTP_MODE mode + local url="${proxy_path%/}/$file$mode" rx + + f_dprintf "sending http request for: %s" "$url" + printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$proxy_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 + + cat # output the rest ``as-is'' + exit 200 + ) + local retval=$? + [ $retval -eq 200 ] && return $SUCCESS + + 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/httpproxy.subr + +fi # ! $_MEDIA_HTTPPROXY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/network.subr b/usr.sbin/bsdconfig/share/media/network.subr new file mode 100644 index 0000000..d9fe8e6 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/network.subr @@ -0,0 +1,182 @@ +if [ ! "$_MEDIA_NETWORK_SUBR" ]; then _MEDIA_NETWORK_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/network.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/media/tcpip.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +NETWORK_INITIALIZED= + +############################################################ FUNCTIONS + +# f_media_init_network $device +# +# Initialize a network device (such as `fxp0', `em0', etc.). Returns success if +# able to successfully initialize the device. If not running as init (basically +# from the FreeBSD install media) then assume that the network has already been +# initialized and returns success. +# +# The variables (from variable.subr) used to initialize the network are as +# follows (all of which are configured either automatically or manaully): +# +# VAR_IFCONFIG + device_name (e.g., `ifconfig_em0') +# Automatically populated but can be overridden in a script. This +# defines the ifconfig(8) properties specific to a chosen network +# interface device. Optional if VAR_IPV6ADDR is set. +# VAR_IPV6ADDR [Optional] +# If not running as init (and setting up RTSOL connections for +# the interface), then must be set manually. If set, used as the +# IPv6 configuration for the given network interface device. +# VAR_GATEWAY [Optional] +# If not running as init (and setting up a static connection for +# the interface) then must be set (usually via rc.conf(5), but +# can be set manually to override). If unset, the user is warned +# but not prevented from proceeding (as most connections need a +# default route but not everyone). +# +f_media_init_network() +{ + local dev="$1" + + f_dprintf "Init routine called for network device \`%s'." "$dev" + if [ "$NETWORK_INITIALIZED" ]; then + f_dprintf "Network already initialized." + return $SUCCESS + elif ! f_running_as_init; then + f_dprintf "Not running as init -- calling the deed done." + NETWORK_INITIALIZED=1 + return $SUCCESS + fi + + if [ ! -e "$RESOLV_CONF" ]; then + if ! f_config_resolv; then + f_show_msg "$msg_cant_seem_to_write_out_resolv_conf" \ + "$RESOLV_CONF" + return $FAILURE + fi + fi + + local cp + if f_getvar $VAR_IFCONFIG$dev cp; then + # + # If this interface isn't a DHCP one, bring it up. + # If it is, then it's already up. + # + case "$cp" in + *DHCP*) + f_dprintf "A DHCP interface. Should already be up." + ;; + *) + f_dprintf "Not a DHCP interface." + if ! f_quietly ifconfig "$dev" $cp; then + f_show_msg "$msg_unable_to_configure_device" \ + "$dev" + return $FAILURE + fi + local rp + f_getvar $VAR_GATEWAY rp + if [ ! "$rp" ]; then + f_dialog_msgbox "$msg_no_gateway_has_been_set" + else + # + # Explicitly flush all routes to get back to a + # known sane state. We don't need to check this + # exit code because if anything fails it will + # show up in the route add below. + # + f_quietly route -n flush + f_dprintf "Adding default route to %s." "$rp" + if ! f_quietly route -n add default "$rp"; then + f_dialog_msgbox \ + "$msg_failed_to_add_default_route" + return $FAILURE + fi + fi + esac + elif ! { f_getvar $VAR_IPV6ADDR cp && [ "$cp" ]; }; then + f_show_msg "$msg_device_is_not_configured" "$dev" + return $FAILURE + fi + + f_dprintf "Network initialized successfully." + NETWORK_INITIALIZED=1 + return $SUCCESS +} + +# f_media_shutdown_network $device +# +# Shuts down the configured network device (e.g., `fxp0', `em0', etc.) and +# deletes the default route (if configured). Returns failure if the device +# passed has not been configured. If not running as init (basically from the +# FreeBSD install media) then does nothing and returns success. +# +f_media_shutdown_network() +{ + local dev="$1" cp + + f_dprintf "Shutdown called for network device %s" "$dev" + if [ ! "$NETWORK_INITIALIZED" ]; then + f_dprintf "Network not initialized -- nothing to do." + return $SUCCESS + fi + + unset NETWORK_INITIALIZED + unset $VAR_NETWORK_DEVICE + + if ! f_running_as_init; then + f_dprintf "Not running as init -- calling the deed done." + return $SUCCESS + fi + + f_getvar $VAR_IFCONFIG$dev cp || return $FAILURE + f_dprintf "ifconfig %s down" "$dev" + f_quietly ifconfig $dev down || + f_show_msg "$msg_unable_to_down_the_interface_properly" "$dev" + + if f_getvar $VAR_GATEWAY cp; then + f_dprintf "Deleting default route." + f_quietly route -n delete default + fi + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/network.subr + +fi # ! $_MEDIA_NETWORK_SUBR diff --git a/usr.sbin/bsdconfig/share/media/nfs.subr b/usr.sbin/bsdconfig/share/media/nfs.subr new file mode 100644 index 0000000..461db1c --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/nfs.subr @@ -0,0 +1,251 @@ +if [ ! "$_MEDIA_NFS_SUBR" ]; then _MEDIA_NFS_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/nfs.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr +f_include $BSDCFG_SHARE/media/tcpip.subr +f_include $BSDCFG_SHARE/media/network.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +NFS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_nfs +# +# Return success if we both found and set the media type to be an NFS server. +# Variables from variable.subr that can be used to script user input: +# +# VAR_NFS_PATH +# The NFS path specification (host:path) to use when mounting the +# remote repository. +# VAR_NAMESERVER [Optional] +# Automatically populated from resolv.conf(5) but can be +# overridden. If set, the host portion of VAR_NFS_PATH is +# looked up using f_host_lookup() from `tcpip.subr'. +# +# Meanwhile, the following variables from variable.subr are set after +# successful execution: +# +# VAR_NFS_HOST +# The host portion of the NFS path specification, parsed from +# VAR_NFS_PATH. +# +f_media_set_nfs() +{ + local nfs + + f_media_close + + f_variable_get_value $VAR_NFS_PATH \ + "$msg_please_enter_the_full_nfs_file_specification" + f_getvar $VAR_NFS_PATH nfs + [ "$nfs" ] || return $FAILURE + + case "$nfs" in + *:*) : valid NFS path ;; + *) + f_dialog_msgbox "$msg_invalid_nfs_path_specification" + return $FAILURE + esac + + f_struct_new DEVICE device_nfs + device_nfs set name "$nfs" + + if ! f_struct device_network || + ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration" + then + f_struct device_network && + f_device_shutdown network + f_device_select_tcp || return $FAILURE + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + f_device_init network || + f_dprintf "%s: $msg_net_device_init_failed\n" f_media_set_nfs + + local hostname="${nfs%%:*}" + if f_quietly f_getvar $VAR_NAMESERVER && ! { + 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_nfs" "$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_NFS_PATH + return $FAILURE + fi + f_dprintf "Found DNS entry for %s successfully." "$hostname" + fi + + setvar $VAR_NFS_HOST "$hostname" + + device_nfs set type $DEVICE_TYPE_NFS + device_nfs set init f_media_init_nfs + device_nfs set get f_media_get_nfs + device_nfs set shutdown f_media_shutdown_nfs + device_nfs set private device_network # in name only (deref'd later) + + f_struct_copy device_nfs device_media + f_struct_free device_nfs + + return $SUCCESS +} + +# f_media_init_nfs $device +# +# Initializes the NFS media device. Returns success if able to mount the NFS +# device using mount_nfs(1). +# +# The variables (from variable.subr) used to initialize the NFS mount are as +# follows (all of which are configured manually/optionally from the options +# menu): +# +# VAR_NFS_TCP [Optional] +# If non-NULL, adds the "tcp" option via `-o' to mount_nfs(8). +# VAR_NFS_V3 [Optional] +# If non-NULL, adds the "nfsv3" option via `-o' to mount_nfs(8). +# VAR_NFS_SECURE [Optional] +# If non-NULL, adds the "-P" flag to mount_nfs(8). +# VAR_SLOW_ETHER [Optional] +# If non-NULL, adjusts the read/write size to avoid timeouts. +# +f_media_init_nfs() +{ + local dev="$1" name err + + device_$dev get name name || return $FAILURE + f_dprintf "Init routine called for NFS device. name=[%s]" \ + "$name" + + if [ "$NFS_MOUNTED" ]; then + f_dprintf "NFS device already mounted." + return $SUCCESS + fi + + if ! f_device_init network; then + f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed" + return $FAILURE + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + local cp tcp="" use3="" secure="" readsize=4096 writesize=4096 + f_getvar $VAR_NFS_TCP cp + [ "$cp" = "YES" ] && tcp=1 + f_getvar $VAR_NFS_V3 cp + [ "$cp" = "YES" ] && use3=1 + f_getvar $VAR_NFS_SECURE cp + [ "$cp" = "YES" ] && secure=1 + f_getvar $VAR_SLOW_ETHER cp + [ "$cp" = "YES" ] && readsize=1024 writesize=1024 + + local options="rsize=$readsize,wsize=$writesize" + [ "$use3" ] && options="$options,nfsv3" + [ "$tcp" ] && options="$options,tcp" + + if ! err=$( mount_nfs \ + ${secure:+-P} -o "$options" "$name" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_nfs: }" + f_show_msg "$msg_error_mounting_device" \ + "$name" "$MOUNTPOINT" "$err" + f_struct device_network && + f_device_shutdown network + return $FAILURE + fi + NFS_MOUNTED=1 + + f_dprintf "Mounted NFS device %s onto %s" "$name" "$MOUNTPOINT" + + return $SUCCESS +} + +# f_media_get_nfs $device $file [$probe_only] +# +# Returns data from $file on a mounted NFS device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_nfs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_nfs $device +# +# Shuts down the NFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_nfs() +{ + local dev="$1" err + + [ "$NFS_MOUNTED" ] || return + + f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT" + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_nfs_partition" \ + "$MOUNTPOINT" "$err" + else + NFS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/nfs.subr + +fi # ! $_MEDIA_NFS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/options.subr b/usr.sbin/bsdconfig/share/media/options.subr new file mode 100644 index 0000000..c32bec5 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/options.subr @@ -0,0 +1,308 @@ +if [ ! "$_MEDIA_OPTIONS_SUBR" ]; then _MEDIA_OPTIONS_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/options.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/any.subr +f_include $BSDCFG_SHARE/media/ftp.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +OPTIONS_HELPFILE=$BSDCFG_LIBE/include/options.hlp + +############################################################ FUNCTIONS + +# f_media_options_menu +# +# Prompt the user to confirm/edit various media settings. Returns success. +# +f_media_options_menu() +{ + f_dialog_title "$msg_options_editor" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + local prompt="" + local hline="$hline_arrows_tab_enter" + local menu_list size cp + + # + # A hack so that the dialogs below are always interactive in a script + # + local old_interactive= + if ! f_interactive; then + f_getvar $VAR_NONINTERACTIVE old_interactive + unset $VAR_NONINTERACTIVE + fi + + while :; do + menu_list="" + + f_getvar $VAR_NFS_SECURE cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_secure' 'YES' + '$msg_nfs_server_talks_only_on_a_secure_port'" + else menu_list="$menu_list + ' $msg_nfs_secure' 'NO' + '$msg_nfs_server_talks_only_on_a_secure_port'" + fi + + f_getvar $VAR_SLOW_ETHER cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_slow' 'YES' + '$msg_user_is_using_a_slow_pc_or_ethernet_card'" + else menu_list="$menu_list + ' $msg_nfs_slow' 'NO' + '$msg_user_is_using_a_slow_pc_or_ethernet_card'" + fi + + f_getvar $VAR_NFS_TCP cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_tcp' 'YES' '$msg_use_tcp_protocol_for_nfs'" + else menu_list="$menu_list + ' $msg_nfs_tcp' 'NO' '$msg_use_tcp_protocol_for_nfs'" + fi + + f_getvar $VAR_NFS_V3 cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_version_3' 'YES' '$msg_use_nfs_version_3'" + else menu_list="$menu_list + ' $msg_nfs_version_3' 'NO' '$msg_use_nfs_version_3'" + fi + + f_getvar $VAR_DEBUG cp + if [ "$cp" ]; then menu_list="$menu_list + ' $msg_debugging' 'YES' + '$msg_emit_extra_debugging_output'" + else menu_list="$menu_list + ' $msg_debugging' 'NO' + '$msg_emit_extra_debugging_output'" + fi + + f_getvar $VAR_TRY_DHCP cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_dhcp' 'YES' + '$msg_attempt_automatic_dhcp_configuration'" + else menu_list="$menu_list + ' $msg_dhcp' 'NO' + '$msg_attempt_automatic_dhcp_configuration'" + fi + + f_getvar $VAR_TRY_RTSOL cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_ipv6' 'YES' + '$msg_attempt_ipv6_configuration_of_interfaces'" + else menu_list="$menu_list + ' $msg_ipv6' 'NO' + '$msg_attempt_ipv6_configuration_of_interfaces'" + fi + + f_getvar $VAR_FTP_USER cp + menu_list="$menu_list + ' $msg_ftp_username' '$cp' + '$msg_username_and_password_to_use'" + + f_getvar $VAR_EDITOR cp + menu_list="$menu_list + ' $msg_editor' '$cp' '$msg_which_text_editor_to_use'" + + f_getvar $VAR_RELNAME cp + menu_list="$menu_list + ' $msg_release_name' '$cp' + '$msg_which_release_to_attempt_to_load'" + + if f_struct device_media; then + device_media get type cp + 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";; + *) + cp="<$msg_unknown>" + esac + else + cp="<$msg_not_yet_set>" + fi + menu_list="$menu_list + ' $msg_media_type' '$cp' + '$msg_the_current_installation_media_type'" + + f_getvar $VAR_MEDIA_TIMEOUT cp + menu_list="$menu_list + ' $msg_media_timeout' '$cp' + '$msg_timeout_value_in_seconds_for_slow_media'" + + menu_list="$menu_list + ' $msg_rescan_devices' '<*>' + '$msg_rerun_bsdconfig_initial_device_probe' + ' $msg_use_defaults' '[${msg_reset}]' + '$msg_reset_all_values_to_startup_defaults' + " # END-QUOTE + + size=$( eval f_dialog_menu_with_help_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu + + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --item-help \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_done\" \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + --menu \"\$prompt\" $size $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + + local mtag + mtag=$( f_dialog_menutag ) + f_dprintf "retval=%s mtag=[%s]" $retval "$mtag" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$OPTIONS_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + break # to success + fi + + case "$mtag" in + " $msg_nfs_secure") + f_getvar $VAR_NFS_SECURE cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_SECURE="NO" + else + export $VAR_NFS_SECURE="YES" + fi ;; + " $msg_nfs_slow") + f_getvar $VAR_SLOW_ETHER cp + if [ "$cp" = "YES" ]; then + export $VAR_SLOW_ETHER="NO" + else + export $VAR_SLOW_ETHER="YES" + fi ;; + " $msg_nfs_tcp") + f_getvar $VAR_NFS_TCP cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_TCP="NO" + else + export $VAR_NFS_TCP="YES" + fi ;; + " $msg_nfs_version_3") + f_getvar $VAR_NFS_V3 cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_V3="NO" + else + export $VAR_NFS_V3="YES" + fi ;; + " $msg_debugging") + if f_getvar $VAR_DEBUG cp && [ "$cp" ]; then + unset $VAR_DEBUG + else + export $VAR_DEBUG=1 + fi ;; + " $msg_dhcp") + f_getvar $VAR_TRY_DHCP cp + if [ "$cp" = "YES" ]; then + export $VAR_TRY_DHCP="NO" + else + export $VAR_TRY_DHCP="YES" + fi ;; + " $msg_ipv6") + f_getvar $VAR_TRY_RTSOL cp + if [ "$cp" = "YES" ]; then + export $VAR_TRY_RTSOL="NO" + else + export $VAR_TRY_RTSOL="YES" + fi ;; + " $msg_ftp_username") + f_media_set_ftp_userpass ;; + " $msg_editor") + f_variable_get_value $VAR_EDITOR \ + "$msg_please_specify_the_name_of_the_text_editor" + ;; + " $msg_release_name") + f_variable_get_value $VAR_RELNAME \ + "$msg_please_specify_the_release_you_wish_to_load" + ;; + " $msg_media_type") + f_media_get_type ;; + " $msg_media_timeout") + f_variable_get_value $VAR_MEDIA_TIMEOUT \ + "$msg_please_specify_the_number_of_seconds_to_wait" + ;; + " $msg_rescan_devices") + f_device_rescan ;; + " $msg_use_defaults") + f_variable_set_defaults ;; + esac + done + + # Restore old VAR_NONINTERACTIVE if needed. + [ "$old_interactive" ] && + setvar $VAR_NONINTERACTIVE "$old_interactive" + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/options.subr + +fi # ! $_MEDIA_OPTIONS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/tcpip.subr b/usr.sbin/bsdconfig/share/media/tcpip.subr new file mode 100644 index 0000000..0bf0487 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/tcpip.subr @@ -0,0 +1,1688 @@ +if [ ! "$_MEDIA_TCPIP_SUBR" ]; then _MEDIA_TCPIP_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/tcpip.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +TCP_HELPFILE=$BSDCFG_LIBE/include/tcp.hlp +NETWORK_DEVICE_HELPFILE=$BSDCFG_LIBE/include/network_device.hlp + +############################################################ GLOBALS + +# +# Path to resolv.conf(5). +# +: ${RESOLV_CONF:="/etc/resolv.conf"} + +# +# Path to nsswitch.conf(5). +# +: ${NSSWITCH_CONF:="/etc/nsswitch.conf"} + +# +# Path to hosts(5) +# +: ${ETC_HOSTS:="/etc/hosts"} + +# +# Structure of dhclient.leases(5) lease { ... } entry +# +f_struct_define DHCP_LEASE \ + interface \ + fixed_address \ + filename \ + server_name \ + script \ + medium \ + host_name \ + subnet_mask \ + routers \ + domain_name_servers \ + domain_name \ + broadcast_address \ + dhcp_lease_time \ + dhcp_message_type \ + dhcp_server_identifier \ + dhcp_renewal_time \ + dhcp_rebinding_time \ + renew \ + rebind \ + expire + +############################################################ FUNCTIONS + +# f_validate_hostname $hostname +# +# Returns zero if the given argument (a fully-qualified hostname) is compliant +# with standards set-forth in RFC's 952 and 1123 of the Network Working Group: +# +# RFC 952 - DoD Internet host table specification +# http://tools.ietf.org/html/rfc952 +# +# RFC 1123 - Requirements for Internet Hosts - Application and Support +# http://tools.ietf.org/html/rfc1123 +# +# See http://en.wikipedia.org/wiki/Hostname for a brief overview. +# +# The return status for invalid hostnames is one of: +# 255 Entire hostname exceeds the maximum length of 255 characters. +# 63 One or more individual labels within the hostname (separated by +# dots) exceeds the maximum of 63 characters. +# 1 One or more individual labels within the hostname contains one +# or more invalid characters. +# 2 One or more individual labels within the hostname starts or +# ends with a hyphen (hyphens are allowed, but a label cannot +# begin or end with a hyphen). +# 3 One or more individual labels within the hostname are null. +# +# f_dialog_validate_hostname $hostname +# +# If the hostname is determined to be invalid, the appropriate error will be +# displayed using the f_show_msg function. +# +f_validate_hostname() +{ + local fqhn="$1" + + # Return error if the hostname exceeds 255 characters + [ ${#fqhn} -gt 255 ] && return 255 + + local IFS="." # Split on `dot' + for label in $fqhn; do + # Return error if the label exceeds 63 characters + [ ${#label} -gt 63 ] && return 63 + + # Return error if the label is null + [ "$label" ] || return 3 + + # Return error if label begins/ends with dash + case "$label" in -*|*-) return 2; esac + + # Return error if the label contains any invalid chars + case "$label" in *[!0-9a-zA-Z-]*) return 1; esac + done + + return $SUCCESS +} + +# f_inet_atoi $ipv4_address [$var_to_set] +# +# Convert an IPv4 address or mask from dotted-quad notation (e.g., `127.0.0.1' +# or `255.255.255.0') to a 32-bit unsigned integer for the purpose of network +# and broadcast calculations. For example, one can validate that two addresses +# are on the same network: +# +# f_inet_atoi 1.2.3.4 ip1num +# f_inet_atoi 1.2.4.5 ip2num +# f_inet_atoi 255.255.0.0 masknum +# if [ $(( $ip1num & $masknum )) -eq \ +# $(( $ip2num & $masknum )) ] +# then +# : IP addresses are on same network +# fi +# +# See f_validate_ipaddr() below for an additional example usage, on calculating +# network and broadcast addresses. +# +# If $var_to_set is missing or NULL, the converted IP address 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_inet_atoi() +{ + local __addr="$1" __var_to_set="$2" __num=0 + if f_validate_ipaddr "$__addr"; then + __num=$( IFS=.; set -- $__addr; \ + echo $(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 )) ) + fi + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" $__num + else + echo $__num + fi +} + +# f_validate_ipaddr $ipaddr [$netmask] +# +# Returns zero if the given argument (an IP address) is of the proper format. +# +# The return status for invalid IP address is one of: +# 1 One or more individual octets within the IP address (separated +# by dots) contains one or more invalid characters. +# 2 One or more individual octets within the IP address are null +# and/or missing. +# 3 One or more individual octets within the IP address exceeds the +# maximum of 255 (or 2^8, being an octet comprised of 8 bits). +# 4 The IP address has either too few or too many octets. +# +# If a netmask is provided, the IP address is checked further: +# +# 5 The IP address must not be the network or broadcast address. +# +f_validate_ipaddr() +{ + local ip="$1" mask="$2" + + # Track number of octets for error checking + local noctets=0 + + local oldIFS="$IFS" + local IFS="." # Split on `dot' + for octet in $ip; do + # Return error if the octet is null + [ "$octet" ] || return 2 + + # Return error if not a whole integer + f_isinteger "$octet" || return 1 + + # Return error if not a positive integer + [ $octet -ge 0 ] || return 1 + + # Return error if the octet exceeds 255 + [ $octet -gt 255 ] && return 3 + + noctets=$(( $noctets + 1 )) + done + IFS="$oldIFS" + + [ $noctets -eq 4 ] || return 4 + + # + # The IP address must not be network or broadcast address. + # + if [ "$mask" ]; then + local ipnum masknum netnum bcastnum + local max_addr=4294967295 # 255.255.255.255 + + f_inet_atoi $ip ipnum + f_inet_atoi $mask masknum + + netnum=$(( $ipnum & $masknum )) + bcastnum=$(( ($ipnum & $masknum)+$max_addr-$masknum )) + + if [ "$masknum" ] && + [ $ipnum -eq $netnum -o $ipnum -eq $bcastnum ] + then + return 5 + fi + fi + + return $SUCCESS +} + +# f_validate_ipaddr6 $ipv6_addr +# +# Returns zero if the given argument (an IPv6 address) is of the proper format. +# +# The return status for invalid IP address is one of: +# 1 One or more individual segments within the IP address +# (separated by colons) contains one or more invalid characters. +# Segments must contain only combinations of the characters 0-9, +# A-F, or a-f. +# 2 Too many/incorrect null segments. A single null segment is +# allowed within the IP address (separated by colons) but not +# allowed at the beginning or end (unless a double-null segment; +# i.e., "::*" or "*::"). +# 3 One or more individual segments within the IP address +# (separated by colons) exceeds the length of 4 hex-digits. +# 4 The IP address entered has either too few (less than 3), too +# many (more than 8), or not enough segments, separated by +# colons. +# 5* The IPv4 address at the end of the IPv6 address is invalid. +# * When there is an error with the dotted-quad IPv4 address at the +# end of the IPv6 address, the return value of 5 is OR'd with a +# bit-shifted (<< 4) return of f_validate_ipaddr. +# +f_validate_ipaddr6() +{ + local ip="${1%\%*}" # removing the interface specification if-present + + local IFS=":" # Split on `colon' + set -- $ip: + + # Return error if too many or too few segments + # Using 9 as max in case of leading or trailing null spanner + [ $# -gt 9 -o $# -lt 3 ] && return 4 + + local h="[0-9A-Fa-f]" + local nulls=0 nsegments=$# contains_ipv4_segment= + + while [ $# -gt 0 ]; do + + segment="${1%:}" + shift + + # + # Return error if this segment makes one null too-many. A + # single null segment is allowed anywhere in the middle as well + # as double null segments are allowed at the beginning or end + # (but not both). + # + if [ ! "$segment" ]; then + nulls=$(( $nulls + 1 )) + if [ $nulls -eq 3 ]; then + # Only valid syntax for 3 nulls is `::' + [ "$ip" = "::" ] || return 2 + elif [ $nulls -eq 2 ]; then + # Only valid if begins/ends with `::' + case "$ip" in + ::*|*::) : fall thru ;; + *) return 2 + esac + fi + continue + fi + + # + # Return error if not a valid hexadecimal short + # + case "$segment" in + $h|$h$h|$h$h$h|$h$h$h$h) + : valid segment of 1-4 hexadecimal digits + ;; + *[!0-9A-Fa-f]*) + # Segment contains at least one invalid char + + # Return error immediately if not last segment + [ $# -eq 0 ] || return 1 + + # Otherwise, check for legacy IPv4 notation + case "$segment" in + *[!0-9.]*) + # Segment contains at least one invalid + # character even for an IPv4 address + return 1 + esac + + # Return error if not enough segments + if [ $nulls -eq 0 ]; then + [ $nsegments -eq 7 ] || return 4 + fi + + contains_ipv4_segment=1 + + # Validate the IPv4 address + f_validate_ipaddr "$segment" || + return $(( 5 | $? << 4 )) + ;; + *) + # Segment characters are all valid but too many + return 3 + esac + + done + + if [ $nulls -eq 1 ]; then + # Single null segment cannot be at beginning/end + case "$ip" in + :*|*:) return 2 + esac + fi + + # + # A legacy IPv4 address can span the last two 16-bit segments, + # reducing the amount of maximum allowable segments by-one. + # + maxsegments=8 + if [ "$contains_ipv4_segment" ]; then + maxsegments=7 + fi + + case $nulls in + # Return error if missing segments with no null spanner + 0) [ $nsegments -eq $maxsegments ] || return 4 ;; + # Return error if null spanner with too many segments + 1) [ $nsegments -le $maxsegments ] || return 4 ;; + # Return error if leading/trailing `::' with too many segments + 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || return 4 ;; + esac + + return $SUCCESS +} + +# f_validate_netmask $netmask +# +# Returns zero if the given argument (a subnet mask) is of the proper format. +# +# The return status for invalid netmask is one of: +# 1 One or more individual fields within the subnet mask (separated +# by dots) contains one or more invalid characters. +# 2 One or more individual fields within the subnet mask are null +# and/or missing. +# 3 One or more individual fields within the subnet mask exceeds +# the maximum of 255 (a full 8-bit register). +# 4 The subnet mask has either too few or too many fields. +# 5 One or more individual fields within the subnet mask is an +# invalid integer (only 0,128,192,224,240,248,252,254,255 are +# valid integers). +# +f_validate_netmask() +{ + local mask="$1" + + # Track number of fields for error checking + local nfields=0 + + local IFS="." # Split on `dot' + for field in $mask; do + # Return error if the field is null + [ "$field" ] || return 2 + + # Return error if not a whole positive integer + f_isinteger "$field" || return 1 + + # Return error if the field exceeds 255 + [ $field -gt 255 ] && return 3 + + # Return error if the field is an invalid integer + case "$field" in + 0|128|192|224|240|248|252|254|255) :;; + *) return 5;; + esac + + nfields=$(( $nfields + 1 )) + done + + [ $nfields -eq 4 ] || return 4 +} + +# f_validate_gateway $gateway $ipaddr $netmask +# +# Validate an IPv4 default gateway (aka router) address for a given IP address +# making sure the two are in the same network (able to ``talk'' to each other). +# Returns success if $ipaddr and $gateway are in the same network given subnet +# mask $netmask. +# +f_validate_gateway() +{ + local gateway="$1" ipaddr="$2" netmask="$3" + local gwnum ipnum masknum + + f_validate_ipaddr "$gateway" "$netmask" || return $FAILURE + + f_inet_atoi "$netmask" masknum + f_inet_atoi "$ipaddr" ipnum + f_inet_atoi "$gateway" gwnum + + # Gateway must be within set of IPs reachable through interface + [ $(( $ipnum & $masknum )) -eq \ + $(( $gwnum & $masknum )) ] # Return status +} + +# f_dialog_validate_tcpip $hostname $gateway $nameserver $ipaddr $netmask +# +# Returns success if the arguments provided are valid for accessing a TCP/IP +# network, otherwise returns failure. +# +f_dialog_validate_tcpip() +{ + local hostname="$1" gateway="$2" nameserver="$3" + local ipaddr="$4" netmask="$5" + local ipnum masknum + + if [ ! "$hostname" ]; then + f_dialog_msgbox "$msg_must_specify_a_host_name_of_some_sort" + elif ! f_validate_hostname "$hostname"; then + f_dialog_msgbox "$msg_invalid_hostname_value" + elif [ "$netmask" ] && ! f_validate_netmask "$netmask"; then + f_dialog_msgbox "$msg_invalid_netmask_value" + elif [ "$nameserver" ] && + ! f_validate_ipaddr "$nameserver" && + ! f_validate_ipaddr6 "$nameserver"; then + f_dialog_msgbox "$msg_invalid_name_server_ip_address_specified" + elif [ "$ipaddr" ] && ! f_validate_ipaddr "$ipaddr" "$netmask"; then + f_dialog_msgbox "$msg_invalid_ipv4_address" + elif [ "$gateway" -a "$gateway" != "NO" ] && + ! f_validate_gateway "$gateway" "$ipaddr" "$netmask"; then + f_dialog_msgbox "$msg_invalid_gateway_ipv4_address_specified" + else + return $SUCCESS + fi + + return $FAILURE +} + +# f_ifconfig_inet $interface [$var_to_set] +# +# Returns the IPv4 address associated with $interface. If $var_to_set is +# missing or NULL, the IP address 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). +# +# 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_ifconfig_inet_awk=' +BEGIN { found = 0 } +( $1 == "inet" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_ifconfig_inet() +{ + local __interface="$1" __var_to_set="$2" + if [ "$__var_to_set" ]; then + local __ip + __ip=$( ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet_awk" ) + setvar "$__var_to_set" "$__ip" + else + ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet_awk" + fi +} + +# f_ifconfig_inet6 $interface [$var_to_set] +# +# Returns the IPv6 address associated with $interface. If $var_to_set is +# missing or NULL, the IP address 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). +# +# 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_ifconfig_inet6_awk=' +BEGIN { found = 0 } +( $1 == "inet6" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_ifconfig_inet6() +{ + local __interface="$1" __var_to_set="$2" + if [ "$__var_to_set" ]; then + local __ip6 + __ip6=$( ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet6_awk" ) + setvar "$__var_to_set" "$__ip6" + else + ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet6_awk" + fi +} + +# f_ifconfig_netmask $interface [$var_to_set] +# +# Returns the IPv4 subnet mask associated with $interface. If $var_to_set is +# missing or NULL, the netmask 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_ifconfig_netmask() +{ + local __interface="$1" __var_to_set="$2" __octets + __octets=$( ifconfig "$__interface" 2> /dev/null | awk \ + ' + BEGIN { found = 0 } + ( $1 == "inet" ) \ + { + printf "%s %s %s %s\n", + substr($4,3,2), + substr($4,5,2), + substr($4,7,2), + substr($4,9,2) + found = 1 + exit + } + END { exit ! found } + ' ) || return $FAILURE + + local __octet __netmask= + for __octet in $__octets; do + __netmask="$__netmask.$( printf "%u" "0x$__octet" )" + done + __netmask="${__netmask#.}" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__netmask" + else + echo $__netmask + fi +} + +# f_route_get_default [$var_to_set] +# +# Returns the IP address of the currently active default router. If $var_to_set +# is missing or NULL, the IP address 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). +# +# 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_route_get_default=' +BEGIN { found = 0 } +( $1 == "gateway:" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_route_get_default() +{ + local __var_to_set="$1" + if [ "$__var_to_set" ]; then + local __ip + __ip=$( route -n get default 2> /dev/null | + awk "$f_route_get_default_awk" ) + setvar "$__var_to_set" "$__ip" + else + route -n get default 2> /dev/null | + awk "$f_route_get_default_awk" + fi +} + +# f_resolv_conf_nameservers [$var_to_set] +# +# Returns nameserver(s) configured in resolv.conf(5). If $var_to_set is missing +# or NULL, the list of nameservers 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). +# +# 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_resolv_conf_nameservers_awk=' +BEGIN { found = 0 } +( $1 == "nameserver" ) \ +{ + print $2 + found = 1 +} +END { exit ! found } +' +f_resolv_conf_nameservers() +{ + local __var_to_set="$1" + if [ "$__var_to_set" ]; then + local __ns + __ns=$( awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \ + 2> /dev/null ) + setvar "$__var_to_set" "$__ns" + else + awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \ + 2> /dev/null + fi +} + +# f_config_resolv +# +# Attempts to configure resolv.conf(5) and ilk. Returns success if able to +# write the file(s), otherwise returns error status. +# +# Variables from variable.subr that are used in configuring resolv.conf(5) are +# as follows (all of which can be configured automatically through functions +# like f_dhcp_get_info() or manually): +# +# VAR_NAMESERVER +# The nameserver to add in resolv.conf(5). +# VAR_DOMAINNAME +# The domain to configure in resolv.conf(5). Also used in the +# configuration of hosts(5). +# VAR_IPADDR +# The IPv4 address to configure in hosts(5). +# VAR_IPV6ADDR +# The IPv6 address to configure in hosts(5). +# VAR_HOSTNAME +# The hostname to associate with the IPv4 and/or IPv6 address in +# hosts(5). +# +f_config_resolv() +{ + local cp c6p dp hp + + f_getvar $VAR_NAMESERVER cp + if [ "$cp" ]; then + case "$RESOLV_CONF" in + */*) f_quietly mkdir -p "${RESOLV_CONF%/*}" ;; + esac + + # Attempt to create/truncate the file + ( :> "$RESOLV_CONF" ) 2> /dev/null || return $FAILURE + + f_getvar $VAR_DOMAINNAME dp && + printf "domain\t%s\n" "$dp" >> "$RESOLV_CONF" + printf "nameserver\t%s\n" "$cp" >> "$RESOLV_CONF" + + f_dprintf "Wrote out %s" "$RESOLV_CONF" + fi + + f_getvar $VAR_DOMAINNAME dp + f_getvar $VAR_IPADDR cp + f_getvar $VAR_IPV6ADDR c6p + f_getvar $VAR_HOSTNAME hp + + # Attempt to create the file if it doesn't already exist + if [ ! -e "$ETC_HOSTS" ]; then + case "$ETC_HOSTS" in + */*) f_quietly mkdir -p "${ETC_HOSTS%/*}" ;; + esac + + ( :> "$ETC_HOSTS" ) 2> /dev/null || return $FAILURE + fi + + # Scan the file and add ourselves if not already configured + awk -v dn="$dp" -v ip4="$cp" -v ip6="$c6p" -v hn="$hp" ' + BEGIN { + local4found = local6found = 0 + hn4found = hn6found = h4found = h6found = 0 + h = ( match(hn, /\./) ? substr(hn, 0, RSTART-1) : "" ) + } + ($1 == "127.0.0.1") { local4found = 1 } + ($1 == "::1") { local6found = 1 } + { + for (n = 2; n <= NF; n++) + { + if ( $1 == ip4 ) { + if ( $n == h ) h4found = 1 + if ( $n == hn ) hn4found = 1 + if ( $n == hn "." ) hn4found = 1 + } + if ( $1 == ip6 ) { + if ( $n == h ) h6found = 1 + if ( $n == hn ) hn6found = 1 + if ( $n == hn "." ) hn6found = 1 + } + } + } + END { + hosts = FILENAME + + if ( ! local6found ) + printf "::1\t\t\tlocalhost%s\n", + ( dn ? " localhost." dn : "" ) >> hosts + if ( ! local4found ) + printf "127.0.0.1\t\tlocalhost%s\n", + ( dn ? " localhost." dn : "" ) >> hosts + + if ( ip6 && ! (h6found && hn6found)) + { + printf "%s\t%s %s\n", ip6, hn, h >> hosts + printf "%s\t%s.\n", ip6, hn >> hosts + } + else if ( ip6 ) + { + if ( ! h6found ) + printf "%s\t%s.\n", ip6, h >> hosts + if ( ! hn6found ) + printf "%s\t%s\n", ip6, hn >> hosts + } + + if ( ip4 && ! (h4found && hn4found)) + { + printf "%s\t\t%s %s\n", ip4, hn, h >> hosts + printf "%s\t\t%s.\n", ip4, hn >> hosts + } + else if ( ip4 ) + { + if ( ! h4found ) + printf "%s\t\t%s.\n", ip4, h >> hosts + if ( ! hn4found ) + printf "%s\t\t%s\n", ip4, hn >> hosts + } + } + ' "$ETC_HOSTS" 2> /dev/null || return $FAILURE + + f_dprintf "Wrote out %s" "$ETC_HOSTS" + return $SUCCESS +} + +# f_dhcp_parse_leases $leasefile struct_name +# +# Parse $leasefile and store the information for the most recent lease in a +# struct (see struct.subr for additional details) named `struct_name'. See +# DHCP_LEASE struct definition in the GLOBALS section above. +# +f_dhcp_parse_leases() +{ + local leasefile="$1" struct_name="$2" + + [ "$struct_name" ] || return $FAILURE + + if [ ! -e "$leasefile" ]; then + f_dprintf "%s: No such file or directory" "$leasefile" + return $FAILURE + fi + + f_struct "$struct_name" && f_struct_free "$struct_name" + f_struct_new DHCP_LEASE "$struct_name" + + eval "$( awk -v struct="$struct_name" ' + BEGIN { + lease_found = 0 + keyword_list = " \ + interface \ + fixed-address \ + filename \ + server-name \ + script \ + medium \ + " + split(keyword_list, keywords, FS) + + time_list = "renew rebind expire" + split(time_list, times, FS) + + option_list = " \ + host-name \ + subnet-mask \ + routers \ + domain-name-servers \ + domain-name \ + broadcast-address \ + dhcp-lease-time \ + dhcp-message-type \ + dhcp-server-identifier \ + dhcp-renewal-time \ + dhcp-rebinding-time \ + " + split(option_list, options, FS) + } + function set_value(prop,value) + { + lease_found = 1 + gsub(/[^[:alnum:]_]/, "_", prop) + sub(/;$/, "", value) + sub(/^"/, "", value) + sub(/"$/, "", value) + sub(/,.*/, "", value) + printf "%s set %s \"%s\"\n", struct, prop, value + } + /^lease {$/, /^}$/ \ + { + if ( $0 ~ /^lease {$/ ) next + if ( $0 ~ /^}$/ ) exit + + for (k in keywords) + { + keyword = keywords[k] + if ( $1 == keyword ) + { + set_value(keyword, $2) + next + } + } + + for (t in times) + { + time = times[t] + if ( $1 == time ) + { + set_value(time, $2 " " $3 " " $4) + next + } + } + + if ( $1 != "option" ) next + for (o in options) + { + option = options[o] + if ( $2 == option ) + { + set_value(option, $3) + next + } + } + } + EXIT { + if ( ! lease_found ) + { + printf "f_struct_free \"%s\"\n", struct + print "return $FAILURE" + } + } + ' "$leasefile" )" +} + +# f_dhcp_get_info $interface +# +# Parse the dhclient(8) lease database for $interface to obtain all the +# necessary IPv4 details necessary to communicate on the network. The retrieved +# information is stored in VAR_IPADDR, VAR_NETMASK, VAR_GATEWAY, and +# VAR_NAMESERVER. +# +# If reading the lease database fails, values are obtained from ifconfig(8) and +# route(8). If the DHCP lease did not provide a nameserver (or likewise, we +# were unable to parse the lease database), fall-back to resolv.conf(5) for +# obtaining the nameserver. Always returns success. +# +f_dhcp_get_info() +{ + local interface="$1" cp + local leasefile="/var/db/dhclient.leases.$interface" + + # If it fails, do it the old-fashioned way + if f_dhcp_parse_leases "$leasefile" lease; then + lease get fixed_address $VAR_IPADDR + lease get subnet_mask $VAR_NETMASK + lease get routers cp + setvar $VAR_GATEWAY "${cp%%,*}" + lease get domain_name_servers cp + setvar $VAR_NAMESERVER "${cp%%,*}" + lease get host_name cp && + setvar $VAR_HOSTNAME "$cp" + f_struct_free lease + else + # Bah, now we have to get the information from ifconfig + if f_debugging; then + f_dprintf "DHCP configured interface returns %s" \ + "$( ifconfig "$interface" )" + fi + f_ifconfig_inet "$interface" $VAR_IPADDR + f_ifconfig_netmask "$interface" $VAR_NETMASK + f_route_get_default $VAR_GATEWAY + fi + + # If we didn't get a name server value, hunt for it in resolv.conf + local ns + if [ -r "$RESOLV_CONF" ] && ! { + f_getvar $VAR_NAMESERVER ns || [ "$ns" ] + }; then + f_resolv_conf_nameservers cp && + setvar $VAR_NAMESERVER ${cp%%[$IFS]*} + fi + + return $SUCCESS +} + +# f_rtsol_get_info $interface +# +# Returns the rtsol-provided IPv6 address associated with $interface. The +# retrieved IP address is stored in VAR_IPV6ADDR. Always returns success. +# +f_rtsol_get_info() +{ + local interface="$1" cp + cp=$( ifconfig "$interface" 2> /dev/null | awk \ + ' + BEGIN { found = 0 } + ( $1 == "inet6" ) && ( $2 ~ /^fe80:/ ) \ + { + print $2 + found = 1 + exit + } + END { exit ! found } + ' ) && setvar $VAR_IPV6ADDR "$cp" +} + +# f_host_lookup $host [$var_to_set] +# +# Use host(1) to lookup (or reverse) an Internet number from (or to) a name. +# Multiple answers are returned separated by a single space. If host(1) does +# not exit cleanly, its full output is provided and the return status is 1. +# +# If nsswitch.conf(5) has been configured to query local access first for the +# `hosts' database, we'll manually check hosts(5) first (preventing host(1) +# from hanging in the event that DNS goes awry). +# +# If $var_to_set is missing or NULL, the list of IP addresses 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). +# +# The variables from variable.subr used in looking up the host are as follows +# (which are set manually): +# +# VAR_IPV6_ENABLE [Optional] +# If set to "YES", enables the lookup of IPv6 addresses and IPv4 +# address. IPv6 addresses, if any, will come before IPv4. Note +# that if nsswitch.conf(5) shows an affinity for "files" for the +# "host" database and there is a valid entry in hosts(5) for +# $host, this setting currently has no effect (an IPv4 address +# can supersede an IPv6 address). By design, hosts(5) overrides +# any preferential treatment. Otherwise, if this variable is not +# set, IPv6 addresses will not be used (IPv4 addresses will +# specifically be requested from DNS). +# +# 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_host_lookup_awk=' +BEGIN{ addrs = "" } +!/^[[:space:]]*(#|$)/ \ +{ + for (n=1; n++ < NF;) if ($n == name) + addrs = addrs (addrs ? " " : "") $1 +} +END { + if (addrs) print addrs + exit !addrs +} +' +f_host_lookup() +{ + local __host="$1" __var_to_set="$2" + f_dprintf "f_host_lookup: host=[%s]" "$__host" + + # If we're configured to look at local files first, do that + if awk '/^hosts:/{exit !($2=="files")}' "$NSSWITCH_CONF"; then + if [ "$__var_to_set" ]; then + local __cp + if __cp=$( awk -v name="$__host" \ + "$f_host_lookup_awk" "$ETC_HOSTS" ) + then + setvar "$__var_to_set" "$__cp" + return $SUCCESS + fi + else + awk -v name="$__host" \ + "$f_host_lookup_awk" "$ETC_HOSTS" && + return $SUCCESS + fi + fi + + # + # Fall back to host(1) -- which is further governed by nsswitch.conf(5) + # + + local __output __ip6 __addrs="" __wait="" + f_getvar $VAR_MEDIA_TIMEOUT __wait + [ "$__wait" ] && __wait="-W $(( $__wait / 2 ))" + f_getvar $VAR_IPV6_ENABLE __ip6 + if [ "$__ip6" = "YES" ]; then + if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then + # An error occurred, display in-full and return error + [ "$__var_to_set" ] && + setvar "$__var_to_set" "$__output" + return $FAILURE + fi + __addrs=$( echo "$__output" | awk '/ address /{print $NF}' ) + fi + if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then + # An error occurred, display it in-full and return error + [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output" + return $FAILURE + fi + __addrs="$__addrs${__addrs:+ }$( + echo "$__output" | awk '/ address /{print $NF}' )" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__addrs" + else + echo $__addrs + fi +} + +# f_device_dialog_tcp $device +# +# This is it - how to get TCP setup values. Prompt the user to edit/confirm the +# interface, gateway, nameserver, and hostname settings -- all required for +# general TCP/IP access. +# +# Variables from variable.subr that can be used to sript user input: +# +# VAR_NO_INET6 +# If set, prevents asking the user if they would like to use +# rtsol(8) to check for an IPv6 router. +# VAR_TRY_RTSOL +# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the +# user if they would like to try the IPv6 RouTer SOLicitation +# utility (rtsol(8)) to get IPv6 information. Ignored if +# VAR_NO_INET6 is set. +# VAR_TRY_DHCP +# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the +# user if they would like to try to acquire IPv4 connection +# settings from a DHCP server using dhclient(8). +# +# VAR_GATEWAY Default gateway to use. +# VAR_IPADDR Interface address to assign. +# VAR_NETMASK Interface subnet mask. +# VAR_EXTRAS Extra interface options to ifconfig(8). +# VAR_HOSTNAME Hostname to set. +# VAR_DOMAINNAME Domain name to use. +# VAR_NAMESERVER DNS nameserver to use when making lookups. +# VAR_IPV6ADDR IPv6 interface address. +# +# In addition, the following variables are used in acquiring network settings +# from the user: +# +# VAR_NONINTERACTIVE +# If set (such as when running in a script), prevents asking the +# user questions or displaying the usual prompts, etc. +# VAR_NETINTERACTIVE +# The one exception to VAR_NONINTERACTIVE is VAR_NETINTERACTIVE, +# which if set will prompt the user to try RTSOL (unless +# VAR_TRY_RTSOL has been set), try DHCP (unless VAR_TRY_DHCP has +# been set), and display the network verification dialog. This +# allows you to have a mostly non-interactive script that still +# prompts for network setup/confirmation. +# +# After successfull execution, the following variables are set: +# +# VAR_IFCONFIG + $device (e.g., `ifconfig_em0') +# Defines the ifconfig(8) properties specific to $device. +# +f_device_dialog_tcp() +{ + local dev="$1" cp n + local use_dhcp="" use_rtsol="" + local _ipaddr _netmask _extras + + [ "$dev" ] || return $FAILURE + + # Initialize vars from previous device values + local private + device_$dev get private private + if [ "$private" ] && f_struct "$private"; then + $private get ipaddr _ipaddr + $private get netmask _netmask + $private get extras _extras + $private get use_dhcp use_dhcp + $private get use_rtsol use_rtsol + else # See if there are any defaults + + # + # This is a hack so that the dialogs below are interactive in a + # script if we have requested interactive behavior. + # + local old_interactive= + if ! f_interactive && f_netinteractive; then + f_getvar $VAR_NONINTERACTIVE old_interactive + unset $VAR_NONINTERACTIVE + fi + + + # + # Try a RTSOL scan if such behavior is desired. + # If the variable was configured and is YES, do it. + # If it was configured to anything else, treat it as NO. + # Otherwise, ask the question interactively. + # + local try6 + if ! f_quietly f_getvar $VAR_NO_INET6 && { + { f_getvar $VAR_TRY_RTSOL try6 && [ "$try6" = "YES" ]; } || + { + ! f_quietly f_getvar $VAR_TRY_RTSOL && + f_dialog_noyes "$msg_try_ipv6_configuration" + } + }; then + local i + + f_quietly sysctl net.inet6.ip6.forwarding=0 + f_quietly sysctl net.inet6.ip6.accept_rtadv=1 + f_quietly ifconfig $dev up + + i=$( sysctl -n net.inet6.ip6.dad_count ) + sleep $(( $i + 1 )) + + f_quietly mkdir -p /var/run + f_dialog_info "$msg_scanning_for_ra_servers" + if f_quietly rtsol $dev; then + i=$( sysctl -n net.inet6.ip6.dad_count ) + sleep $(( $i + 1 )) + f_rtsol_get_info $dev + use_rtsol=1 + else + use_rtsol= + fi + fi + + # + # Try a DHCP scan if such behavior is desired. + # If the variable was configured and is YES, do it. + # If it was configured to anything else, treat it as NO. + # Otherwise, ask the question interactively. + # + local try4 + if { f_getvar $VAR_TRY_DHCP try4 && [ "$try4" = "YES" ]; } || { + ! f_quietly f_getvar $VAR_TRY_DHCP && + f_dialog_noyes "$msg_try_dhcp_configuration" + }; then + f_quietly ifconfig $dev delete + f_quietly mkdir -p /var/db + f_quietly mkdir -p /var/run + f_quietly mkdir -p /tmp + + local msg="$msg_scanning_for_dhcp_servers" + trap - SIGINT + ( # Execute in sub-shell to allow/catch Ctrl-C + trap 'exit $FAILURE' SIGINT + if [ "$USE_XDIALOG" ]; then + f_quietly dhclient $dev | + f_xdialog_info "$msg" + else + f_dialog_info "$msg" + f_quietly dhclient $dev + fi + ) + local retval=$? + trap 'f_interrupt' SIGINT + if [ $retval -eq $SUCCESS ]; then + f_dhcp_get_info $dev + use_dhcp=1 + else + use_dhcp= + fi + fi + + # Restore old VAR_NONINTERACTIVE if needed. + [ "$old_interactive" ] && + setvar $VAR_NONINTERACTIVE "$old_interactive" + + # Special hack so it doesn't show up oddly in the menu + local gw + if f_getvar $VAR_GATEWAY gw && [ "$gw" = "NO" ]; then + setvar $VAR_GATEWAY "" + fi + + # Get old IP address from variable space, if available + if [ ! "$_ipaddr" ]; then + if f_getvar $VAR_IPADDR cp; then + _ipaddr="$cp" + elif f_getvar ${dev}_$VAR_IPADDR cp; then + _ipaddr="$cp" + fi + fi + + # Get old netmask from variable space, if available + if [ ! "$_netmask" ]; then + if f_getvar $VAR_NETMASK cp; then + _netmask="$cp" + elif f_getvar ${dev}_$VAR_NETMASK cp; then + _netmask="$cp" + fi + fi + + # Get old extras string from variable space, if available + if [ ! "$_extras" ]; then + if f_getvar $VAR_EXTRAS cp; then + _extras="$cp" + elif f_getvar ${dev}_$VAR_EXTRAS cp; then + _extras="$cp" + fi + fi + fi + + # Look up values already recorded with the system, or blank the string + # variables ready to accept some new data + local _hostname _gateway _nameserver + f_getvar $VAR_HOSTNAME _hostname + case "$_hostname" in + *.*) : do nothing ;; # Already fully-qualified + *) + f_getvar $VAR_DOMAINNAME cp + [ "$cp" ] && _hostname="$_hostname.$cp" + esac + f_getvar $VAR_GATEWAY _gateway + f_getvar $VAR_NAMESERVER _nameserver + + # Re-check variables for initial inheritance before heading into dialog + [ "$_hostname" ] || _hostname="${HOSTNAME:-$( hostname )}" + [ "$_gateway" ] || f_route_get_default _gateway + [ ! "$_nameserver" ] && + f_resolv_conf_nameservers cp && _nameserver=${cp%%[$IFS]*} + [ "$_ipaddr" ] || f_ifconfig_inet $dev _ipaddr + [ "$_netmask" ] || f_ifconfig_netmask $dev _netmask + + # If non-interactive, jump over dialog section and into config section + if f_netinteractive || f_interactive || [ ! "$_hostname" ] + then + [ ! "$_hostname" ] && f_interactive && + f_dialog_msgbox "$msg_hostname_variable_not_set" + + local title=" $msg_network_configuration " + local hline="$hline_alnum_arrows_punc_tab_enter" + local extras_help="$tcplayout_extras_help" + + # Modify the help line for PLIP config + [ "${dev#plip}" != "$dev" ] && + extras_help="$tcplayout_extras_help_for_plip" + + f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] && + title="$title($msg_ipv6_ready) " + + if [ ! "$USE_XDIALOG" ]; then + local prompt="$msg_dialog_mixedform_navigation_help" + # Calculate center position for displaying device label + local devlabel="$msg_configuration_for_interface $dev" + local width=54 + local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 )) + + while :; do + cp=$( $DIALOG \ + --title "$title" \ + --backtitle "$DIALOG_BACKTITLE" \ + --hline "$hline" \ + --item-help \ + --ok-label "$msg_ok" \ + --cancel-label "$msg_cancel" \ + --help-button \ + --help-label "$msg_help" \ + --mixedform "$prompt" 16 $width 9 \ + "$msg_host_name_including_domain:" 1 2 \ + "$_hostname" 2 3 45 255 0 \ + "$tcplayout_hostname_help" \ + "$msg_ipv4_gateway:" 3 2 \ + "$_gateway" 4 3 16 15 0 \ + "$tcplayout_gateway_help" \ + "$msg_name_server:" 3 31 \ + "$_nameserver" 4 32 16 15 0 \ + "$tcplayout_nameserver_help" \ + "- $devlabel -" 5 $n "" 0 0 0 0 3 "" \ + "$msg_ipv4_address:" 6 6 \ + "$_ipaddr" 7 7 16 15 0 \ + "$tcplayout_ipaddr_help" \ + "$msg_netmask:" 6 31 \ + "$_netmask" 7 32 16 15 0 \ + "$tcplayout_netmask_help" \ + "$msg_extra_options_to_ifconfig" 8 6 \ + "$_extras" 9 7 41 2048 0 \ + "$extras_help" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + + # --mixed-form always returns 0, we have to + # use the returned data to determine button + if [ ! "$cp" ]; then + # User either chose "Cancel", pressed + # ESC, or blanked every form field + return $FAILURE + else + n=$( echo "$cp" | f_number_of_lines ) + [ $n -eq 1 ] && case "$cp" in HELP*) + # User chose "Help" + f_show_help "$TCP_HELPFILE" + continue + esac + fi + + # Turn mixed-form results into env variables + eval "$( echo "$cp" | awk ' + BEGIN { + n = 0 + field[++n] = "_hostname" + field[++n] = "_gateway" + field[++n] = "_nameserver" + field[++n] = "_ipaddr" + field[++n] = "_netmask" + field[++n] = "_extras" + nfields = n + n = 0 + } + { + gsub(/'\''/, "'\'\\\\\'\''") + sub(/[[:space:]]*$/, "") + value[field[++n]] = $0 + } + END { + for ( n = 1; n <= nfields; n++ ) + { + printf "%s='\''%s'\'';\n", + field[n], + value[field[n]] + } + }' )" + + f_dialog_validate_tcpip \ + "$_hostname" \ + "$_gateway" \ + "$_nameserver" \ + "$_ipaddr" \ + "$_netmask" \ + && break + done + else + # Xdialog(1) does not support --mixed-form + # Create a persistent menu instead + + f_dialog_title "$msg_network_configuration" + local prompt="" + + while :; do + cp=$( $DIALOG \ + --title "$DIALOG_TITLE" \ + --backtitle "$DIALOG_BACKTITLE" \ + --hline "$hline" \ + --item-help \ + --ok-label "$msg_ok" \ + --cancel-label "$msg_cancel" \ + --help "" \ + --menu "$prompt" 21 60 8 \ + "$msg_accept_continue" "" \ + "$tcplayout_accept_cont_help" \ + "$msg_host_name_including_domain:" \ + "$_hostname" \ + "$tcplayout_hostname_help" \ + "$msg_ipv4_gateway:" "$_gateway" \ + "$tcplayout_gateway_help" \ + "$msg_name_server:" "$_nameserver" \ + "$tcplayout_nameserver_help" \ + "$msg_ipv4_address:" "$_ipaddr" \ + "$tcplayout_ipaddr_help" \ + "$msg_netmask:" "$_netmask" \ + "$tcplayout_netmask_help" \ + "$msg_extra_options_to_ifconfig" \ + "$_extras" "$extras_help" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + f_dprintf "retval=%u mtag=[%s]" $retval "$cp" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$TCP_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + # User chose "Cancel" or pressed ESC + f_dialog_title_restore + return $FAILURE + fi + + case "$cp" in + "$msg_accept_continue") + f_dialog_validate_tcpip \ + "$_hostname" \ + "$_gateway" \ + "$_nameserver" \ + "$_ipaddr" \ + "$_netmask" \ + && break ;; + "$msg_host_name_including_domain:") + cp=$( f_dialog_input "$cp" \ + "$_hostname" + ) && _hostname="$cp" ;; + "$msg_ipv4_gateway:") + cp=$( f_dialog_input "$cp" \ + "$_gateway" + ) && _gateway="$cp" ;; + "$msg_name_server:") + cp=$( f_dialog_input "$cp" \ + "$_nameserver" + ) && _nameserver="$cp" ;; + "$msg_ipv4_address:") + cp=$( f_dialog_input "$cp" \ + "$_ipaddr" + ) && _ipaddr="$cp" ;; + "$msg_netmask:") + cp=$( f_dialog_input "$cp" \ + "$_netmask" + ) && _netmask="$cp" ;; + "$msg_extra_options_to_ifconfig") + cp=$( f_dialog_input "$cp" \ + "$_extras" + ) && _extras="$cp" ;; + esac + done + + f_dialog_title_restore + + fi # XDIALOG + + fi # interactive + + # We actually need to inform the rest of bsdconfig about this + # data now if the user hasn't selected cancel. + + if [ "$_hostname" ]; then + setvar $VAR_HOSTNAME "$_hostname" + f_quietly hostname "$_hostname" + case "$_hostname" in + *.*) setvar $VAR_DOMAINNAME "${_hostname#*.}" ;; + esac + fi + [ "$_gateway" ] && setvar $VAR_GATEWAY "$_gateway" + [ "$_nameserver" ] && setvar $VAR_NAMESERVER "$_nameserver" + [ "$_ipaddr" ] && setvar $VAR_IPADDR "$_ipaddr" + [ "$_netmask" ] && setvar $VAR_NETMASK "$_netmask" + [ "$_extras" ] && setvar $VAR_EXTRAS "$_extras" + + f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev" + f_struct_new DEVICE_INFO devinfo_$dev + device_$dev set private devinfo_$dev + + devinfo_$dev set ipaddr $_ipaddr + devinfo_$dev set netmask $_netmask + devinfo_$dev set extras $_extras + devinfo_$dev set use_rtsol $use_rtsol + devinfo_$dev set use_dhcp $use_dhcp + + if [ "$use_dhcp" -o "$_ipaddr" ]; then + if [ "$use_dhcp" ]; then + cp="DHCP${extras:+ $extras}" + else + cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}" + fi + setvar $VAR_IFCONFIG$dev "$cp" + fi + [ "$use_rtsol" ] && + setvar $VAR_IPV6_ENABLE "YES" + + [ "$use_dhcp" ] || + f_config_resolv # XXX this will do it on the MFS copy + + return $SUCCESS +} + +# f_device_scan_tcp [$var_to_set] +# +# Scan for the first active/configured TCP/IP device. The name of the interface +# is printed to stderr like other dialog(1)-based functions (stdout is reserved +# for dialog(1) interaction) if $var_to_set is missing or NULL. Returns failure +# if no active/configured interface +# +f_device_scan_tcp() +{ + local __var_to_set="$1" __iface + for __iface in $( ifconfig -l ); do + if ifconfig $__iface | awk ' + BEGIN { + has_inet = has_inet6 = is_ethernet = 0 + is_usable = 1 + } + ( $1 == "status:" && $2 != "active" ) { is_usable = 0; exit } + ( $1 == "inet" ) { + if ($2 == "0.0.0.0") { is_usable = 0; exit } + has_inet++ + } + ( $1 == "inet6") { has_inet6++ } + ( $1 == "media:" ) { + if ($2 != "Ethernet") { is_usable = 0; exit } + is_ethernet = 1 + } + END { + if (!(is_ethernet && (has_inet || has_inet6))) + is_usable = 0 + exit ! is_usable + }'; then + f_interactive && + f_show_msg "$msg_using_interface" "$__iface" + f_dprintf "f_device_scan_tcp found %s" "$__iface" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__iface" + else + echo "$__iface" >&2 + fi + return $SUCCESS + fi + done + + return $FAILURE +} + +# f_device_select_tcp +# +# Prompt the user to select network interface to use for TCP/IP access. +# Variables from variable.subr that can be used to script user input: +# +# VAR_NETWORK_DEVICE [Optional] +# Either a comma-separated list of network interfaces to try when +# setting up network access (e.g., "fxp0,em0") or "ANY" (case- +# sensitive) to indicate that the first active and configured +# interface is acceptable. If unset, the user is presented with a +# menu of all available network interfaces. +# +# Returns success if a valid network interface has been selected. +# +f_device_select_tcp() +{ + local devs dev cnt network_dev + f_getvar $VAR_NETWORK_DEVICE network_dev + + f_dprintf "f_device_select_tcp: %s=[%s]" \ + VAR_NETWORK_DEVICE "$network_dev" + + if [ "$network_dev" ]; then + # + # This can be set to several types of values. If set to ANY, + # scan all network devices looking for a valid link, and go + # with the first device found. Can also be specified as a + # comma delimited list, with each network device tried in + # order. Can also be set to a single network device. + # + [ "$network_dev" = "ANY" ] && f_device_scan_tcp network_dev + + while [ "$network_dev" ]; do + case "$network_dev" in + *,*) dev="${network_dev%%,*}" + network_dev="${network_dev#*,}" + ;; + *) dev="$network_dev" + network_dev= + esac + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + + if [ ${cnt:=0} -gt 0 ]; then + dev="${devs%%[$IFS]*}" + f_device_dialog_tcp $dev + if [ $? -eq $SUCCESS ]; then + setvar $VAR_NETWORK_DEVICE $dev + return $SUCCESS + fi + fi + done + + f_interactive && f_dialog_msgbox "$msg_no_network_devices" + return $FAILURE + + fi # $network_dev + + f_device_find "" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + dev="${devs%%[$IFS]*}" + + f_quietly f_getvar NETWORK_CONFIGURED # for debugging info + if ! f_running_as_init && + ! [ "${NETWORK_CONFIGURED+set}" -a "$NETWORK_CONFIGURED" = "NO" ] + then + trap 'f_interrupt' SIGINT + if f_dialog_yesno "$msg_assume_network_is_already_configured" + then + setvar $VAR_NETWORK_DEVICE $dev + return $SUCCESS + fi + fi + + local retval=$SUCCESS + if [ ${cnt:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_network_devices" + retval=$FAILURE + elif [ $cnt -eq 1 ]; then + f_device_dialog_tcp $dev + retval=$? + [ $retval -eq $SUCCESS ] && setvar $VAR_NETWORK_DEVICE $dev + else + local title="$msg_network_interface_information_required" + local prompt="$msg_please_select_ethernet_device_to_configure" + local hline="$hline_arrows_tab_enter" + + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \ + "$NETWORK_DEVICE_HELPFILE" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_device_dialog_tcp $dev + retval=$? + if [ $retval -eq $SUCCESS ]; then + f_struct_copy device_$dev device_network + setvar $VAR_NETWORK_DEVICE network + else + f_struct_free device_network + fi + fi + + return $retval +} + +# f_dialog_menu_select_tcp +# +# Like f_dialog_select_tcp() above, but do it from a menu that doesn't care +# about status. In other words, where f_dialog_select_tcp() will not display a +# menu if scripted, this function will always display the menu of available +# network interfaces. +# +f_dialog_menu_select_tcp() +{ + local private use_dhcp name + NETWORK_CONFIGURED=NO f_device_select_tcp + if f_struct device_network && + device_network get private private && + f_struct_copy "$private" di && + di get use_dhcp use_dhcp && + [ ! "$use_dhcp" ] && + device_network get name name && + f_yesno "$msg_would_you_like_to_bring_interface_up" "$name" + then + if ! f_device_init network; then + f_show_msg "$msg_initialization_of_device_failed" \ + "$name" + fi + fi + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/tcpip.subr + +fi # ! $_MEDIA_TCPIP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/ufs.subr b/usr.sbin/bsdconfig/share/media/ufs.subr new file mode 100644 index 0000000..0b70f09 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ufs.subr @@ -0,0 +1,193 @@ +if [ ! "$_MEDIA_UFS_SUBR" ]; then _MEDIA_UFS_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/ufs.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +UFS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_ufs +# +# Return success if we both found and set the media type to be a UFS partition. +# Variables from variable.subr that can be used to script user input: +# +# VAR_UFS_PATH +# Path to a UFS character device node to be used with mount(8) in +# mounting a UFS formatted partition. Valid examples include: +# /dev/da0s1a +# /dev/ad4s1e +# However, other forms may be valid (see mount(8) for additional +# information). +# +f_media_set_ufs() +{ + local ufs + + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_UFS devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_variable_get_value $VAR_UFS_PATH \ + "$msg_enter_the_device_name_of_a_ufs_formatted_partition" + f_getvar $VAR_UFS_PATH ufs + [ "$ufs" ] || return $FAILURE + + local fstype + fstype=$( df -nT $ufs 2> /dev/null | + awk '!/Type/{print $2;exit}' ) + + f_struct_new DEVICE device_ufs + device_ufs set name ${fstype:-ufs} + device_ufs set devname "$ufs" + device_ufs set get f_media_get_ufs + device_ufs set init f_media_init_ufs + device_ufs set shutdown f_media_shutdown_ufs + device_ufs unset private + + f_struct_copy device_ufs device_media + f_struct_free device_ufs + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_ufs_partition" + local prompt="$msg_please_select_ufs_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_ufs $device +# +# Initializes the UFS media device. Returns success if able to mount the UFS +# partition device using mount(1). +# +f_media_init_ufs() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for UFS device. devname=[%s]" \ + "$devname" + + if [ "$UFS_MOUNTED" ]; then + f_dprintf "UFS device already mounted." + return $SUCCESS + fi + + if [ ! -e "$devname" ]; then + f_show_msg "$msg_no_such_file_or_directory" \ + "f_media_init_ufs" "$devname" + return $FAILURE + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount: }"; err="${err#$devname : }" + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + fi + UFS_MOUNTED=1 + return $SUCCESS +} + +# f_media_get_ufs $device $file [$probe_only] +# +# Returns data from $file on a mounted UFS partition device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_ufs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_ufs $device +# +# Shuts down the UFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_ufs() +{ + local dev="$1" err + + [ "$UFS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_ufs_partition" \ + "$MOUNTPOINT" "$err" + else + UFS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/ufs.subr + +fi # ! $_MEDIA_UFS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/usb.subr b/usr.sbin/bsdconfig/share/media/usb.subr new file mode 100644 index 0000000..c7fc973 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/usb.subr @@ -0,0 +1,174 @@ +if [ ! "$_MEDIA_USB_SUBR" ]; then _MEDIA_USB_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/usb.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +USB_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_usb +# +# Attempt to use USB as the media type. Return success if we both found and set +# the media type to be a USB drive. +# +f_media_set_usb() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_USB devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_usb_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_usb_drive" + local prompt="$msg_please_select_a_usb_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_USB \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_USB devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media && + device_media unset private + + if f_interactive; then + local name + f_struct device_media get name name + f_show_msg "$msg_using_usb_device" "$name" + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_usb $device +# +# Initializes the USB media device. Returns success if able to mount the USB +# disk device using mount(8). +# +f_media_init_usb() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for USB device. devname=[%s]" \ + "$devname" + + if [ "$USB_MOUNTED" ]; then + f_dprintf "USB device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ); then + USB_MOUNTED=1 + return $SUCCESS + fi + + err="${err#mount: }"; err="${err#$devname: }" + f_show_msg "$msg_error_mounting_usb_drive" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE +} + +# f_media_get_usb $device $file [$probe_only] +# +# Returns data from $file on a mounted USB disk device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_usb() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_usb $device +# +# Shuts down the USB disk device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_usb() +{ + local dev="$1" err + + [ "$USB_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_ufs_partition" \ + "$MOUNTPOINT" "$err" + else + USB_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/usb.subr + +fi # ! $_MEDIA_USB_SUBR diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr index 84d1cab..3ea5dd5 100644 --- a/usr.sbin/bsdconfig/share/script.subr +++ b/usr.sbin/bsdconfig/share/script.subr @@ -1,6 +1,6 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1 # -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,7 +31,10 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1 BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." script.subr +f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/any.subr +f_include $BSDCFG_SHARE/media/tcpip.subr ############################################################ GLOBALS @@ -75,11 +78,13 @@ f_dispatch() local func="$1" resword="${2:-$1}" f_dprintf "f_dispatch: calling resword \`%s'" "$resword" eval $func - local retval=$? _ignore_this_error - f_getvar $VAR_NO_ERROR _ignore_this_error - [ $retval -eq $SUCCESS ] || + local retval=$? + if [ $retval -ne $SUCCESS ]; then + local _ignore_this_error + f_getvar $VAR_NO_ERROR _ignore_this_error [ "$_ignore_this_error" ] || f_die $retval \ - "$msg_command_failed_rest_of_script_aborted" "$resword" + "$msg_command_failed_rest_of_script_aborted" "$resword" + fi unset $VAR_NO_ERROR } @@ -146,8 +151,26 @@ f_script_load() # # Reserved words meant for scripting # +f_resword_new deviceRescan f_device_rescan f_resword_new dumpVariables f_dump_variables f_resword_new loadConfig f_script_load +f_resword_new mediaClose f_media_close +f_resword_new mediaGetType f_media_get_type +f_resword_new mediaOpen f_media_open +f_resword_new mediaSetCDROM f_media_set_cdrom +f_resword_new mediaSetDOS f_media_set_dos +f_resword_new mediaSetFTP f_media_set_ftp +f_resword_new mediaSetFTPActive f_media_set_ftp_active +f_resword_new mediaSetFTPPassive f_media_set_ftp_passive +f_resword_new mediaSetFTPUserPass f_media_set_ftp_userpass +f_resword_new mediaSetFloppy f_media_set_floppy +f_resword_new mediaSetHTTP f_media_set_http_proxy +f_resword_new mediaSetHTTPProxy f_media_set_http_proxy +f_resword_new mediaSetNFS f_media_set_nfs +f_resword_new mediaSetUFS f_media_set_ufs +f_resword_new mediaSetUSB f_media_set_usb +f_resword_new optionsEditor f_media_options_menu +f_resword_new tcpMenuSelect f_dialog_menu_select_tcp f_dprintf "%s: Successfully loaded." script.subr diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 6fe0f32..5b9f51e 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -1,6 +1,6 @@ if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -101,6 +101,72 @@ f_isinteger() ( : $((0/$arg)) ) > /dev/null 2>&1 } +# f_uriencode [$text] +# +# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric +# characters are converted to `%XX' sequence where XX represents the hexa- +# decimal ordinal of the non-alphanumeric character. If $text is missing, data +# is instead read from standard input. +# +f_uriencode_awk=' +BEGIN { + output = "" + for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n) +} +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) { + char = substr($0, n, 1) + if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char] + sline = sline char + } + output = output ( output ? "%0a" : "" ) sline +} +END { print output } +' +f_uriencode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uriencode_awk" + else + awk "$f_uriencode_awk" + fi +} + +# f_uridecode [$text] +# +# Decode $text from a URI. Encoded characters are converted from their `%XX' +# sequence into original unencoded ASCII sequences. If $text is missing, data +# is instead read from standard input. +# +f_uridecode_awk=' +BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) } +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) + { + seq = substr($0, n, 3) + if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) { + hex = substr(seq, 2, 2) + sline = sline chr[sprintf("%u", "0x"hex)] + n += 2 + } else + sline = sline substr(seq, 1, 1) + } + print sline +} +' +f_uridecode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uridecode_awk" + else + awk "$f_uridecode_awk" + fi +} + f_dprintf "%s: Successfully loaded." strings.subr fi # ! $_STRINGS_SUBR diff --git a/usr.sbin/bsdconfig/share/struct.subr b/usr.sbin/bsdconfig/share/struct.subr new file mode 100644 index 0000000..3c6f90f --- /dev/null +++ b/usr.sbin/bsdconfig/share/struct.subr @@ -0,0 +1,206 @@ +if [ ! "$_STRUCT_SUBR" ]; then _STRUCT_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 + +############################################################ FUNCTIONS + +# f_struct_define $type $member_name1 ... +# +# Define a new `structure' type $type made up of the properties $member_name1 +# $member_name2 and so-on. Properties are not typed and can hold any type of +# data (including names of other structs). +# +# Before creating instances of a struct (using f_struct_new $type $name) you +# should use this function to define $type. +# +# Both $type and member names should consist only of alpha-numeric letters or +# the underscore. +# +f_struct_define() +{ + local type="$1" + [ "$type" ] || return $FAILURE + shift + setvar "_struct_typedef_$type" "$*" +} + +# f_struct_new $type $name +# +# Create a new `structure' named $name of type $type. There are two ways to +# access properties of a struct, but they are not equal (each method has its +# own unique benefits, discussed below). +# +# The primary method of accessing (both setting and getting) properties of any +# struct is through the f_struct() function below. +# +# The secondary method of accessing data is by using $name as a function. +# +# Both access methods are cross-platform compatible with any version of sh(1). +# Below is an example of the primary access method: +# +# f_struct_new MY_STRUCT_TYPE my_struct +# f_struct my_struct set abc 123 +# f_struct my_struct get abc # prints 123 to stdout +# f_struct my_struct get abc abc # sets local variable $abc to 123 +# +# Alternatively, the secondary access method (details below): +# +# f_struct_new MY_STRUCT_TYPE my_struct +# my_struct set abc 123 +# my_struct get abc # prints 123 to stdout +# my_struct get abc abc # sets local variable $abc to 123 +# +# The secondary form should only be used if/when: +# + You are certain that the structure already exists +# + You want a syntax error if/when the struct does not exist +# +# The primary benefit to the secondary form is syntax cleanliness and read- +# ability. If you are unsure if a given struct exists (which would cause a +# syntax error when using this form), you can use the primary access method to +# first test for the existence of the struct. For example: +# +# if f_struct my_struct; then +# my_struct get abc # only executed if my_struct exists +# fi +# +# For more information, see the f_struct() function. +# +f_struct_new() +{ + local type="$1" name="$2" + f_dprintf "f_struct_new: type=[%s] name=[%s]" "$type" "$name" + [ "$name" ] || return $FAILURE + setvar "_struct_type_$name" "$type" || return $FAILURE + # OK to use bare $name at this point + eval $name\(\){ f_struct $name \"\$@\"\; } +} + +# f_struct $name +# f_struct $name get $property [$var_to_set] +# f_struct $name set $property $new_value +# f_struct $name unset $property +# +# Access routine for getting, setting, unsetting, and testing properties of +# `structures'. +# +# If only given $name, returns success if struct $name has been created (using +# the f_struct_new() function above). +# +# For getting properties of a struct (versus setting) there are two methods of +# access. If $var_to_set is missing or NULL, the value of the property 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). Returns success unless the property is unset. +# +# For setting properties of a struct, sets the value of $property to $new_value +# and returns success. +# +# For unsetting, the underlying environment variable associated with the given +# $property is unset. +# +f_struct() +{ + local __name="$1" __action="$2" __property="$3" + case $# in + 0) return $FAILURE ;; + 1) f_have $__name ;; + *) case "$__action" in + get) local __var_to_set="$4" + f_getvar "_struct_value_${__name}_$__property" "$__var_to_set" + ;; + set) local new_value="$4" + setvar "_struct_value_${__name}_$__property" "$new_value" ;; + unset) unset "_struct_value_${__name}_$__property" ;; + esac + esac + # Return the status of the last command above +} + +# f_struct_free $name +# +# Unset the collection of environment variables and accessor-function +# associated with struct $name. +# +f_struct_free() +{ + local name="$1" type member members + f_getvar "_struct_type_$name" type + f_dprintf "f_struct_free: name=[%s] type=[%s]" "$name" "$type" + [ "$name" ] || return $FAILURE + f_getvar "_struct_typedef_$type" members + for member in $members; do + f_struct "$name" unset $member + done + unset -f "$name" + unset "_struct_type_$name" +} + +# f_struct_copy $from_name $to_name +# +# Copy the properties of one struct to another. If struct $to_name does not +# exist, it is created. If struct $from_name does not exist, nothing is done +# and struct $to_name remains unmodified. +# +# Returns success unless struct $to_name did not exist and f_struct_new() was +# unable to create it. +# +f_struct_copy() +{ + local from_name="$1" to_name="$2" type + f_dprintf "f_struct_copy: from_name=[%s] to_name=[%s]" \ + "$from_name" "$to_name" + f_getvar "_struct_type_$from_name" type + f_struct "$to_name" || + f_struct_new "$type" "$to_name" || return $FAILURE + f_struct "$from_name" || return $SUCCESS + f_dprintf "f_struct_copy: copying properties from %s to %s" \ + "$from_name" "$to_name" + local property properties from_value n=0 k=0 + f_getvar "_struct_typedef_$type" properties + for property in $properties; do + k=$(( $k + 1 )) + if f_struct "$from_name" get $property from_value; then + f_struct "$to_name" set $property "$from_value" + n=$(( $n + 1 )) + else + f_struct "$to_name" unset $property + fi + done + f_dprintf "f_struct_copy: copied %u of %u properties from %s to %s" \ + "$n" "$k" "$from_name" "$to_name" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." struct.subr + +fi # ! $_STRUCT_SUBR diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr index 235f6dc..7a066421 100644 --- a/usr.sbin/bsdconfig/share/variable.subr +++ b/usr.sbin/bsdconfig/share/variable.subr @@ -1,6 +1,6 @@ if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1 # -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -109,7 +109,15 @@ f_variable_set_defaults() # # Initialize various user-edittable values to their defaults # - setvar $VAR_RELNAME "$UNAME_R" + setvar $VAR_EDITOR "${EDITOR:-/usr/bin/ee}" + setvar $VAR_FTP_STATE "passive" + 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_RELNAME "$UNAME_R" f_dprintf "f_variable_set_defaults: Defaults initialized." } @@ -158,17 +166,71 @@ f_interactive() ! 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" ] +} + ############################################################ 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_NO_ERROR noError +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_HOSTNAME hostname +f_variable_new VAR_HTTP_FTP_MODE httpFtpMode +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_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_ERROR noError +f_variable_new VAR_NO_INET6 noInet6 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 # # Self-initialize unless requested otherwise |