Index: head/usr.sbin/bsdconfig/bsdconfig =================================================================== --- head/usr.sbin/bsdconfig/bsdconfig (revision 262894) +++ head/usr.sbin/bsdconfig/bsdconfig (revision 262895) @@ -1,428 +1,428 @@ #!/bin/sh #- # Copyright (c) 2012 Ron McDowell # Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES # When common.subr is included, it automatically scans "$@" for `-d' and/or # `-D file' arguments to conditionally enable debugging. Similarly, when # dialog.subr is included, it automatically scans "$@" for `-X' and/or `-S'. # To prevent this scanning from becoming confused by extra options, define # any/all extra arguments to use in the optstring to getopts when scanning # for dedicated options such as those described. # # NOTE: This needs to be declared before including `common.subr'. # NOTE: You really only need to list flags that require an argument as unknown # flags are silently accepted unless they take an argument (in which case # the following argument will terminate option processing unless it looks # like a flag). # GETOPTS_EXTRA="f:" BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." "$0" f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/mustberoot.subr f_include $BSDCFG_SHARE/strings.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" f_include_lang $BSDCFG_LIBE/include/messages.subr BSDCONFIG_HELPFILE=$BSDCFG_LIBE/include/bsdconfig.hlp USAGE_HELPFILE=$BSDCFG_LIBE/include/usage.hlp ############################################################ CONFIGURATION # # Alternate `local' libexec directory for add-on modules (e.g., from ports) # BSDCFG_LOCAL_LIBE="/usr/local/libexec/bsdconfig" ############################################################ FUNCTIONS # usage # # display usage and exit # usage() { local index="INDEX" local cmd_list # Calculated below cd $BSDCFG_LIBE # No need to preserve CWD (headed toward exit) # Test for language-specific indices f_quietly ls */"$index.${LANG:-$LC_ALL}" && index="$index.${LANG:-$LC_ALL}" cmd_list=$( awk '/^menu_selection="/ { sub(/\|.*/, "") sub(/^menu_selection="/, "") print }' */$index | sort ) local alt_cmd_list # Calculated below (if $BSDCFG_LOCAL_LIBE exists) if f_quietly cd $BSDCFG_LOCAL_LIBE; then # No need to preserve CWD (headed toward exit) # Test for language-specific indices f_quietly ls */"$index.${LANG:-$LC_ALL}" && index="$index.${LANG:-$LC_ALL}" alt_cmd_list=$( awk '/^menu_selection="/ { sub(/\|.*/, "") sub(/^menu_selection="/, "") print }' */$index 2> /dev/null | sort ) # Conflate lists, removing duplicates cmd_list=$( printf "%s\n%s\n" \ "$cmd_list" "$alt_cmd_list" | sort -u ) fi # # Determine the longest command-length (in characters) # local longest_cmd longest_cmd=$( echo "$cmd_list" | f_longest_line_length ) f_dprintf "longest_cmd=[%s]" "$longest_cmd" # # Determine the maximum width of terminal/console # local max_size="$( stty size 2> /dev/null )" : ${max_size:="24 80"} local max_width="${max_size#*[$IFS]}" f_dprintf "max_width=[%s]" "$max_width" # # Using the longest command-length as the width of a single column, # determine if we can use more than one column to display commands. # local x=$longest_cmd ncols=1 x=$(( $x + 8 )) # Accomodate leading tab character x=$(( $x + 3 + $longest_cmd )) # Preload end of next column while [ $x -lt $max_width ]; do ncols=$(( $ncols + 1 )) x=$(( $x + 3 + $longest_cmd )) done f_dprintf "ncols=[%u] x=[%u]" $ncols $x # # Re-format the command-list into multiple columns # cmd_list=$( eval "$( echo "$cmd_list" | awk -v ncols=$ncols -v size=$longest_cmd ' BEGIN { n = 0 row_item[1] = "" } function print_row() { fmt = "printf \"\\t%-" size "s" for (i = 1; i < cur_col; i++) fmt = fmt " %-" size "s" fmt = fmt "\\n\"" printf "%s", fmt for (i = 1; i <= cur_col; i++) printf " \"%s\"", row_item[i] print "" } { n++ cur_col = (( n - 1 ) % ncols ) + 1 printf "f_dprintf \"row_item[%u]=[%%s]\" \"%s\"\n", cur_col, $0 row_item[cur_col] = $0 if ( cur_col == ncols ) print_row() } END { if ( cur_col < ncols ) print_row() }' )" ) f_usage $BSDCFG_LIBE/USAGE \ "PROGRAM_NAME" "$pgm" \ "COMMAND_LIST" "$cmd_list" # Never reached } # dialog_menu_main # # Display the dialog(1)-based application main menu. # dialog_menu_main() { local title="$DIALOG_TITLE" local btitle="$DIALOG_BACKTITLE" local prompt="$msg_menu_text" local menu_list=" 'X' '$msg_exit' '$msg_exit_bsdconfig' '1' '$msg_usage' '$msg_quick_start_how_to_use_this_menu_system' " # END-QUOTE local defaultitem= # Calculated below local hline= # # Pick up the base modules (directories named `[0-9][0-9][0-9].*') # local menuitem menu_title menu_help menu_selection index=2 for menuitem in $( cd $BSDCFG_LIBE && ls -d [0-9][0-9][0-9].* ); do [ -f "$BSDCFG_LIBE/$menuitem/INDEX" ] || continue [ $index -lt ${#DIALOG_MENU_TAGS} ] || break menu_program= menu_title= menu_help= f_include_lang $BSDCFG_LIBE/$menuitem/INDEX [ "$menu_program" ] || continue case "$menu_program" in /*) : already fully qualified ;; *) menu_program="$menuitem/$menu_program" esac tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) setvar "menu_program$tag" "$menu_program" f_shell_escape "$menu_title" menu_title f_shell_escape "$menu_help" menu_help menu_list="$menu_list '$tag' '$menu_title' '$menu_help'" index=$(( $index + 1 )) done # # Process the `local' libexec sources. # # Whereas modules in $BSDCFG_LIBE must be named [0-9][0-9][0-9].* # modules in $BSDCFG_LOCAL_LIBE should NOT be named this way (making it # more practical for port-maintainers). # # This also has the fortunate side-effect of making the de-duplication # effort rather simple (because so-called `base' modules must be named # differently than add-on modules). # local separator_added= for menuitem in $( cd "$BSDCFG_LOCAL_LIBE" 2> /dev/null && ls -d * ) do # Skip the module if it looks like a `base' module case "$menuitem" in [0-9][0-9][0-9].*) continue;; esac [ -f "$BSDCFG_LOCAL_LIBE/$menuitem/INDEX" ] || continue [ $index -lt ${#DIALOG_MENU_TAGS} ] || break menu_program= menu_title= menu_help= f_include_lang $BSDCFG_LOCAL_LIBE/$menuitem/INDEX || continue [ "$menu_program" ] || continue if [ ! "$separator_added" ]; then menu_list="$menu_list '-' '-' ''" separator_added=1 fi case "$menu_program" in /*) : already fully qualified ;; *) menu_program="$BSDCFG_LOCAL_LIBE/$menuitem/$menu_program" esac tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) setvar "menu_program$tag" "$menu_program" f_shell_escape "$menu_title" menu_title f_shell_escape "$menu_help" menu_help menu_list="$menu_list '$tag' '$menu_title' '$menu_help'" index=$(( $index + 1 )) done local height width rows eval f_dialog_menu_with_help_size height width rows \ \"\$title\" \ \"\$btitle\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list # Obtain default-item from previously stored selection f_dialog_default_fetch defaultitem local menu_choice menu_choice=$( eval $DIALOG \ --clear \ --title \"\$title\" \ --backtitle \"\$btitle\" \ --hline \"\$hline\" \ --item-help \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_exit_bsdconfig\" \ --help-button \ --help-label \"\$msg_help\" \ ${USE_XDIALOG:+--help \"\"} \ --default-item \"\$defaultitem\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_data_sanitize menu_choice f_dialog_menutag_store "$menu_choice" # Only update default-item on success [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice" return $retval } ############################################################ MAIN # # If $0 is not "bsdconfig", interpret it either as a keyword to a menuitem or # as a valid resword (see script.subr for additional details about reswords). # if [ "$pgm" != "bsdconfig" ]; then if indexfile=$( f_index_file "$pgm" ) && cmd=$( f_index_menusel_command "$indexfile" "$pgm" ) then f_dprintf "pgm=[%s] indexfile=[%s] cmd=[%s]" \ "$pgm" "$indexfile" "$cmd" exec "$cmd" "$@" || exit 1 else f_include $BSDCFG_SHARE/script.subr for resword in $RESWORDS; do [ "$pgm" = "$resword" ] || continue # Found a match f_dprintf "pgm=[%s] A valid resWord!" "$pgm" - f_dispatch $resword + f_dispatch $resword $resword "$@" exit $? done fi fi # # Process command-line arguments # scripts_loaded=0 while getopts f:h$GETOPTS_STDARGS flag; do case "$flag" in f) [ $scripts_loaded -eq 0 ] && f_include $BSDCFG_SHARE/script.subr f_script_load "$OPTARG" scripts_loaded=$(( $scripts_loaded + 1 )) ;; h|\?) usage ;; esac done shift $(( $OPTIND - 1 )) # If we've loaded any scripts, do not continue any further [ $scripts_loaded -gt 0 ] && exit # # Initialize # f_dialog_title "$msg_main_menu" [ "$SECURE" ] && f_mustberoot_init # Incorporate rc-file if it exists [ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" # # If a non-option argument was passed, process it as a menuitem selection... # if [ "$1" ]; then # # ...unless it's a long-option for usage. # case "$1" in -help|--help|-\?) usage # Not reached esac # # Find the INDEX (possibly i18n) claiming this keyword and get the # command to execute from the menu_selection line. # if ! { indexfile=$( f_index_file "$1" ) && cmd=$( f_index_menusel_command "$indexfile" "$1" ) }; then # no matches, display usage (which shows valid keywords) f_err "%s: %s: $msg_not_found\n" "$pgm" "$1" usage # Not reached fi shift exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1 # Not reached fi # # Launch application main menu # while :; do dialog_menu_main retval=$? f_dialog_menutag_fetch mtag f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" if [ $retval -eq $DIALOG_HELP ]; then f_show_help "$BSDCONFIG_HELPFILE" continue elif [ $retval -ne $DIALOG_OK ]; then f_die fi case "$mtag" in X) break ;; 1) # Usage f_show_help "$USAGE_HELPFILE" continue esac # Anything else is a dynamically loaded menuitem f_getvar menu_program$mtag menu_program case "$menu_program" in /*) cmd="$menu_program" ;; *) cmd="$BSDCFG_LIBE/$menu_program" esac f_dprintf "cmd=[%s]" "$cmd" $cmd ${USE_XDIALOG:+-X} done exit $SUCCESS ################################################################################ # END ################################################################################ Index: head/usr.sbin/bsdconfig/share/script.subr =================================================================== --- head/usr.sbin/bsdconfig/share/script.subr (revision 262894) +++ head/usr.sbin/bsdconfig/share/script.subr (revision 262895) @@ -1,207 +1,206 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1 # -# Copyright (c) 2012-2013 Devin Teske +# Copyright (c) 2012-2014 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." script.subr f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/media/any.subr f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/mustberoot.subr f_include $BSDCFG_SHARE/networking/services.subr f_include $BSDCFG_SHARE/packages/packages.subr f_include $BSDCFG_SHARE/variable.subr ############################################################ GLOBALS RESWORDS= ############################################################ FUNCTIONS # f_resword_new $resword $function # # Create a new `reserved' word for scripting purposes. Reswords call pre- # defined functions but differ from those functions in the following ways: # -# + Reswords do not take arguments but instead get all their data from -# the environment variable namespace. # + Unless noError is set (must be non-NULL), if calling the resword # results in failure, the application will terminate prematurely. # + noError is unset after each/every resword is called. # # Reswords should not be used in bsdconfig itself (hence the name `reserved -# word') but instead only in scripts loaded through f_script_load()). +# word') but instead only in scripts loaded through f_script_load(). # f_resword_new() { local resword="$1" func="$2" [ "$resword" ] || return $FAILURE f_dprintf "script.subr: New resWord %s -> %s" "$resword" "$func" - eval $resword\(\){ f_dispatch $func $resword\; } + eval $resword\(\){ f_dispatch $func $resword \"\$@\"\; } RESWORDS="$RESWORDS${RESWORDS:+ }$resword" } -# f_dispatch $func [$resword] +# f_dispatch $func $resword # # Wrapper function used by `reserved words' (reswords) to call other functions. # If $noError is set and non-NULL, a failure result from $func is ignored, # otherwise the application is prematurely terminated using f_die(). # # NOTE: $noError is unset after every call. # f_dispatch() { - local func="$1" resword="${2:-$1}" + local func="$1" resword="$2" + shift 2 # func resword f_dprintf "f_dispatch: calling resword \`%s'" "$resword" - eval $func + eval $func "$@" 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" fi unset $VAR_NO_ERROR } # f_script_load [$file] # # Load a script (usually filled with reswords). If $file is missing or NULL, # use one of the following instead (in order): # # $configFile # install.cfg # /stand/install.fg # /tmp/install.cfg # # Unknown/unregistered reswords will generate sh(1) syntax errors but not cause # premature termination. # # Returns success if a script was loaded and itself returned success. # f_script_load() { local script="$1" config_file retval=$SUCCESS f_dprintf "f_script_load: script=[%s]" "$script" if [ ! "$script" ]; then f_getvar $VAR_CONFIG_FILE config_file for script in \ $config_file \ install.cfg \ /stand/install.cfg \ /tmp/install.cfg \ ; do [ -e "$script" ] && break done fi local old_interactive= f_getvar $VAR_NONINTERACTIVE old_interactive # save a copy # Hint to others that we're running from a script, should they care setvar $VAR_NONINTERACTIVE yes if [ "$script" = "-" ]; then f_dprintf "f_script_load: Loading script from stdin" eval "$( cat )" retval=$? else f_dprintf "f_script_load: Loading script \`%s'" "$script" if [ ! -e "$script" ]; then f_show_msg "$msg_unable_to_open" "$script" return $FAILURE fi . "$script" retval=$? fi [ "$old_interactive" ] && setvar $VAR_NONINTERACTIVE "$old_interactive" return $retval } ############################################################ MAIN # # Reserved words meant for scripting # # this file f_resword_new loadConfig f_script_load # device.subr f_resword_new deviceRescan f_device_rescan # media/common.subr f_resword_new mediaOpen f_media_open f_resword_new mediaClose f_media_close # media includes f_resword_new mediaGetType f_media_get_type # media/any.subr f_resword_new mediaSetCDROM f_media_set_cdrom # media/cdrom.subr f_resword_new mediaSetDOS f_media_set_dos # media/dos.subr f_resword_new mediaSetDirectory f_media_set_directory # media/directory.subr f_resword_new mediaSetFloppy f_media_set_floppy # media/floppy.subr f_resword_new mediaSetNFS f_media_set_nfs # media/nfs.subr f_resword_new mediaSetUFS f_media_set_ufs # media/ufs.subr f_resword_new mediaSetUSB f_media_set_usb # media/usb.subr f_resword_new optionsEditor f_media_options_menu # media/options.subr f_resword_new tcpMenuSelect f_dialog_menu_select_tcp # media/tcp.subr # media/ftp.subr 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 # media/http.subr f_resword_new mediaSetHTTP f_media_set_http # media/httpproxy.subr f_resword_new mediaSetHTTPProxy f_media_set_http_proxy # networking/services.subr f_resword_new configPCNFSD f_config_pcnfsd # packages/packages.subr f_resword_new configPackages f_package_config f_resword_new packageAdd f_package_add f_resword_new packageDelete f_package_delete f_resword_new packageReinstall f_package_reinstall # variable.subr f_resword_new installVarDefaults f_variable_set_defaults f_resword_new dumpVariables f_dump_variables f_dprintf "%s: Successfully loaded." script.subr fi # ! $_SCRIPT_SUBR