diff --git a/usr.sbin/bsdconfig/console/INDEX b/usr.sbin/bsdconfig/console/INDEX index b3bf975a518d..e298f340e63c 100644 --- a/usr.sbin/bsdconfig/console/INDEX +++ b/usr.sbin/bsdconfig/console/INDEX @@ -1,70 +1,70 @@ # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2015 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$ # # Title that will be shown in the bsdconfig menu. # menu_title="Console" # # A short descriptive line shown at the bottom of the bsdconfig menu. keep it # short because any line longer than the terminal width will be truncated. # menu_help="Customize system console behavior" # # Two-part variable that defines an action to take when `keyword' is passed on # a bsdconfig command line. Variable takes the form "keyword|command" and # multiple occurrences of the variable (with different `keyword's, or different # `keyword's AND `command's) are allowed. If `command' begins with a '/' then # the full path to the program is needed. If `command' begins with anything # else it is a path relative to the directory this INDEX file is in. `keyword' # can be i18n'ed but `command' is the name of a script. # menu_selection="console|console" menu_selection="vt_font|font" menu_selection="vt_keymap|keymap" menu_selection="vt_repeat|repeat" menu_selection="vt_saver|saver" menu_selection="vt_screenmap|screenmap" menu_selection="vt_ttys|ttys" # For backward compatibility menu_selection="syscons_font|font" menu_selection="syscons_keymap|keymap" menu_selection="syscons_repeat|repeat" menu_selection="syscons_saver|saver" menu_selection="syscons_screenmap|screenmap" menu_selection="syscons_ttys|ttys" # # ------------ Items below this line do NOT need i18n translation ------------ # # Name of the program to be run when this menu choice is selected. If it begins # with a '/' then the full path to the program is needed. If it begins with # anything else it is a path relative to the directory this INDEX file is in. # menu_program="console" diff --git a/usr.sbin/bsdconfig/includes/INDEX b/usr.sbin/bsdconfig/includes/INDEX index c32542de279e..a6a6c49212a4 100644 --- a/usr.sbin/bsdconfig/includes/INDEX +++ b/usr.sbin/bsdconfig/includes/INDEX @@ -1,57 +1,57 @@ -# Copyright (c) 2013 Devin Teske +# Copyright (c) 2013-2015 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$ # # Title that will be shown in the bsdconfig menu. # menu_title="" # # A short descriptive line shown at the bottom of the bsdconfig menu. keep it # short because any line longer than the terminal width will be truncated. # menu_help="" # # Two-part variable that defines an action to take when `keyword' is passed on # a bsdconfig command line. Variable takes the form "keyword|command" and # multiple occurrences of the variable (with different `keyword's, or different # `keyword's AND `command's) are allowed. If `command' begins with a '/' then # the full path to the program is needed. If `command' begins with anything # else it is a path relative to the directory this INDEX file is in. `keyword' # can be i18n'ed but `command' is the name of a script. # menu_selection="includes|includes" menu_selection="api|includes" # # ------------ Items below this line do NOT need i18n translation ------------ # # Name of the program to be run when this menu choice is selected. If it begins # with a '/' then the full path to the program is needed. If it begins with # anything else it is a path relative to the directory this INDEX file is in. # menu_program="" diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr index 6ee08ce8f5ac..14758e678ae9 100644 --- a/usr.sbin/bsdconfig/networking/share/device.subr +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -1,385 +1,385 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1 # -# Copyright (c) 2006-2013 Devin Teske +# Copyright (c) 2006-2015 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..." networking/device.subr f_include $BSDCFG_SHARE/device.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 f_include $BSDCFG_SHARE/networking/media.subr f_include $BSDCFG_SHARE/networking/netmask.subr f_include $BSDCFG_SHARE/networking/resolv.subr f_include $BSDCFG_SHARE/networking/routing.subr f_include $BSDCFG_SHARE/strings.subr f_include $BSDCFG_SHARE/sysrc.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking" f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ GLOBALS # # Settings used while interacting with various dialog(1) menus # : ${DIALOG_MENU_NETDEV_KICK_INTERFACES=1} : ${DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK=3} ############################################################ FUNCTIONS # f_dialog_menu_netdev [$default] # # Display a list of network devices with descriptions. Optionally, if present # and non-NULL, initially highlight $default interface. # f_dialog_menu_netdev() { local menu_list # Calculated below local defaultitem="${1%\*}" # Trim trailing asterisk if present # # Display a message to let the user know we're working... # (message will remain until we throw up the next dialog) # f_dialog_info "$msg_probing_network_interfaces" # # Get list of usable network interfaces # local dev devs if iflist= # Calculated below f_device_rescan_network f_device_find "" $DEVICE_TYPE_NETWORK devs for dev in $devs; do f_struct "$dev" get name if || continue # Skip unsavory interfaces case "$if" in lo[0-9]*|ppp[0-9]*|sl[0-9]*) continue ;; esac iflist="$iflist $if" done iflist="${iflist# }" # # Optionally kick interfaces in the head to get them to accurately # track the carrier status in realtime (required on FreeBSD). # if [ "$DIALOG_MENU_NETDEV_KICK_INTERFACES" ]; then DIALOG_MENU_NETDEV_KICK_INTERFACES= for if in $iflist; do f_quietly ifconfig $if up done if [ "$DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK" ]; then # interfaces need time to update carrier status sleep $DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK fi fi # # Mark any "active" interfaces with an asterisk (*) # to the right of the device name. # menu_list=$( for if in $iflist; do f_device_desc $if $DEVICE_TYPE_NETWORK desc f_shell_escape "$desc" desc if f_device_is_active $if; then printf "'%s\*' '%s'\n" $if "$desc" else printf "'%s' '%s'\n" $if "$desc" fi done ) if [ ! "$menu_list" ]; then f_show_msg "$msg_no_network_interfaces" return $DIALOG_CANCEL fi # Maybe the default item was marked as active f_device_is_active "$defaultitem" && defaultitem="$defaultitem*" # # Ask user to select an interface # local prompt="$msg_select_network_interface" local hline="$hline_arrows_tab_enter" local height width rows eval f_dialog_menu_size height width rows \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list local menu_choice menu_choice=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --default-item \"\$defaultitem\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_menutag_store -s "$menu_choice" return $retval } # f_dialog_menu_netdev_edit $interface $ipaddr $netmask $options $dhcp # # Allow a user to edit network interface settings. Current values are not # probed but rather taken from the positional arguments. # f_dialog_menu_netdev_edit() { local funcname=f_dialog_menu_netdev_edit local interface="$1" ipaddr="$2" netmask="$3" options="$4" dhcp="$5" local prompt menu_list height width rows # # Create a duplicate set of variables for change-tracking... # local ipaddr_orig="$2" \ netmask_orig="$3" \ options_orig="$4" \ dhcp_orig="$5" local hline="$hline_arrows_tab_enter" f_sprintf prompt "$msg_network_configuration" "$interface" # # Loop forever until the user has finished configuring the different # components of the network interface. # # To apply the settings, we need to know each of the following: # - IP Address # - Network subnet mask # - Additional ifconfig(8) options # # It is only when we have all of the above values that we can make the # changes effective because all three options must be specified at-once # to ifconfig(8). # local defaultitem= while :; do local dhcp_status="$msg_disabled" [ "$dhcp" ] && dhcp_status="$msg_enabled" # # Display configuration-edit menu # menu_list=" 'X $msg_save_exit' '$msg_return_to_previous_menu' '2 $msg_dhcp' '$dhcp_status' '3 $msg_ipaddr4' '$ipaddr' '4 $msg_netmask' '$netmask' '5 $msg_options' '$options' " # END-QUOTE eval f_dialog_menu_size height width rows \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $menu_list local tag tag=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --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 tag if [ $retval -eq $DIALOG_HELP ]; then f_show_help "$TCP_HELPFILE" continue elif [ $retval -ne $DIALOG_OK ]; then return $retval else # Only update default-item on success defaultitem="$tag" fi # # Call the below ``modifier functions'' whose job it is to take # input from the user and assign the newly-acquired values back # to the ipaddr, netmask, and options variables for us to re- # read and display in the summary dialog. # case "$tag" in X\ *) break ;; 2\ *) # # Proceed cautiously (confirm with the user) if/when NFS- # mounts are active. If the network on which these mounts # are made is changed parts of the system may hang. # if f_nfs_mounted && ! f_jailed; then local setting f_sprintf setting "$msg_current_dhcp_status" \ "$interface" "$dhcp_status" f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || continue fi # # Toggle DHCP status # if [ "$dhcp_status" = "$msg_enabled" ]; then dhcp= else trap - SIGINT ( # Execute within sub-shell to allow/catch Ctrl-C trap 'exit $FAILURE' SIGINT f_sprintf msg "$msg_scanning_for_dhcp" "$interface" if [ "$USE_XDIALOG" ]; then ( f_quietly ifconfig "$interface" delete f_quietly dhclient "$interface" ) | f_xdialog_info "$msg" else f_dialog_info "$msg" f_quietly ifconfig "$interface" delete f_quietly dhclient "$interface" fi ) retval=$? trap 'interrupt' SIGINT if [ $retval -eq $DIALOG_OK ]; then dhcp=1 f_ifconfig_inet "$interface" ipaddr f_ifconfig_inet6 "$interface" ipaddr6 f_ifconfig_netmask "$interface" netmask options= # Fixup search/domain in resolv.conf(5) hostname=$( f_sysrc_get \ 'hostname:-$(hostname)' ) f_dialog_resolv_conf_update "$hostname" fi fi ;; 3\ *) f_dialog_input_ipaddr "$interface" "$ipaddr" [ $? -eq $DIALOG_OK ] && dhcp= ;; 4\ *) f_dialog_input_netmask "$interface" "$netmask" [ $? -eq $DIALOG_OK -a "$_netmask" ] && dhcp= ;; 5\ *) f_dialog_menu_media_options "$interface" "$options" [ $? -eq $DIALOG_OK ] && dhcp= ;; esac done # # Save only if the user changed at least one feature of the interface # if [ "$ipaddr" != "$ipaddr_orig" -o \ "$netmask" != "$netmask_orig" -o \ "$options" != "$options_orig" -o \ "$dhcp" != "$dhcp_orig" ] then f_show_info "$msg_saving_network_interface" "$interface" local value= if [ "$dhcp" ]; then f_eval_catch $funcname f_sysrc_delete \ 'f_sysrc_delete defaultrouter' value=DHCP else value="inet $ipaddr netmask $netmask" value="$value${options:+ }$options" fi f_eval_catch $funcname f_sysrc_set \ 'f_sysrc_set "ifconfig_%s" "%s"' "$interface" "$value" fi # # Re/Apply the settings if desired # if [ ! "$dhcp" ]; then if f_yesno "$msg_bring_interface_up" "$interface" then f_show_info "$msg_bring_interface_up" "$interface" local dr="$( f_sysrc_get defaultrouter )" if [ "$dr" = "NO" -o ! "$dr" ]; then f_route_get_default dr [ "$dr" ] && f_eval_catch \ $funcname f_sysrc_set \ 'f_sysrc_set defaultrouter "%s"' "$dr" fi # # Make a backup of resolv.conf(5) before using # ifconfig(8) and then restore it afterward. This # allows preservation of nameservers acquired via # DHCP on FreeBSD-8.x (normally lost as ifconfig(8) # usage causes dhclient(8) to exit which scrubs # resolv.conf(5) by-default upon termination). # f_quietly cp -fp "$RESOLV_CONF" "$RESOLV_CONF.$$" if f_eval_catch $funcname ifconfig \ 'ifconfig "%s" inet "%s" netmask "%s" %s' \ "$interface" "$ipaddr" "$netmask" "$options" then [ "$dr" -a "$dr" != "NO" ] && f_eval_catch $funcname route \ 'route add default "%s"' "$dr" fi if cmp -s "$RESOLV_CONF" "$RESOLV_CONF.$$"; then f_quietly rm -f "$RESOLV_CONF.$$" else f_quietly mv -f "$RESOLV_CONF.$$" "$RESOLV_CONF" fi fi fi return $DIALOG_OK } ############################################################ MAIN f_dprintf "%s: Successfully loaded." networking/device.subr fi # ! $_NETWORKING_DEVICE_SUBR diff --git a/usr.sbin/bsdconfig/share/dialog.subr b/usr.sbin/bsdconfig/share/dialog.subr index c83c0c6ad487..d7c2d2c3dfba 100644 --- a/usr.sbin/bsdconfig/share/dialog.subr +++ b/usr.sbin/bsdconfig/share/dialog.subr @@ -1,2341 +1,2341 @@ if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1 # -# Copyright (c) 2006-2014 Devin Teske +# Copyright (c) 2006-2015 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..." dialog.subr f_include $BSDCFG_SHARE/strings.subr f_include $BSDCFG_SHARE/variable.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" f_include_lang $BSDCFG_LIBE/include/messages.subr ############################################################ CONFIGURATION # # Default file descriptor to link to stdout for dialog(1) passthru allowing # execution of dialog from within a sub-shell (so-long as its standard output # is explicitly redirected to this file descriptor). # : ${DIALOG_TERMINAL_PASSTHRU_FD:=${TERMINAL_STDOUT_PASSTHRU:-3}} ############################################################ GLOBALS # # Default name of dialog(1) utility # NOTE: This is changed to "Xdialog" by the optional `-X' argument # DIALOG="dialog" # # Default dialog(1) title and backtitle text # DIALOG_TITLE="$pgm" DIALOG_BACKTITLE="bsdconfig" # # Settings used while interacting with dialog(1) # DIALOG_MENU_TAGS="123456789ABCDEFGHIJKLMNOPQRSTUVWYZabcdefghijklmnopqrstuvwxyz" # # Declare that we are fully-compliant with Xdialog(1) by unset'ing all # compatibility settings. # unset XDIALOG_HIGH_DIALOG_COMPAT unset XDIALOG_FORCE_AUTOSIZE unset XDIALOG_INFOBOX_TIMEOUT # # Exit codes for [X]dialog(1) # DIALOG_OK=${SUCCESS:-0} DIALOG_CANCEL=${FAILURE:-1} DIALOG_HELP=2 DIALOG_ITEM_HELP=2 DIALOG_EXTRA=3 DIALOG_ITEM_HELP=4 export DIALOG_ERROR=254 # sh(1) can't handle the default of `-1' DIALOG_ESC=255 # # Default behavior is to call f_dialog_init() automatically when loaded. # : ${DIALOG_SELF_INITIALIZE=1} # # Default terminal size (used if/when running without a controlling terminal) # : ${DEFAULT_TERMINAL_SIZE:=24 80} # # Minimum width(s) for various dialog(1) implementations (sensible global # default(s) for all widgets of a given variant) # : ${DIALOG_MIN_WIDTH:=24} : ${XDIALOG_MIN_WIDTH:=35} # # When manually sizing Xdialog(1) widgets such as calendar and timebox, you'll # need to know the size of the embedded GUI objects because the height passed # to Xdialog(1) for these widgets has to be tall enough to accomodate them. # # These values are helpful when manually sizing with dialog(1) too, but in a # different way. dialog(1) does not make you accomodate the custom items in the # height (but does for width) -- a height of 3 will display three lines and a # full calendar, for example (whereas Xdialog will truncate the calendar if # given a height of 3). For dialog(1), use these values for making sure that # the height does not exceed max_height (obtained by f_dialog_max_size()). # DIALOG_CALENDAR_HEIGHT=15 DIALOG_TIMEBOX_HEIGHT=6 ############################################################ GENERIC FUNCTIONS # f_dialog_data_sanitize $var_to_edit ... # # When using dialog(1) or Xdialog(1) sometimes unintended warnings or errors # are generated from underlying libraries. For example, if $LANG is set to an # invalid or unknown locale, the warnings from the Xdialog(1) libraries will # clutter the output. This function helps by providing a centralied function # that removes spurious warnings from the dialog(1) (or Xdialog(1)) response. # # Simply pass the name of one or more variables that need to be sanitized. # After execution, the variables will hold their newly-sanitized data. # f_dialog_data_sanitize() { if [ "$#" -eq 0 ]; then f_dprintf "%s: called with zero arguments" \ f_dialog_response_sanitize return $FAILURE fi local __var_to_edit for __var_to_edit in $*; do # Skip warnings and trim leading/trailing whitespace setvar $__var_to_edit "$( f_getvar $__var_to_edit | awk ' BEGIN { data = 0 } { if ( ! data ) { if ( $0 ~ /^$/ ) next if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next data = 1 } print } ' )" done } # f_dialog_line_sanitize $var_to_edit ... # # When using dialog(1) or Xdialog(1) sometimes unintended warnings or errors # are generated from underlying libraries. For example, if $LANG is set to an # invalid or unknown locale, the warnings from the Xdialog(1) libraries will # clutter the output. This function helps by providing a centralied function # that removes spurious warnings from the dialog(1) (or Xdialog(1)) response. # # Simply pass the name of one or more variables that need to be sanitized. # After execution, the variables will hold their newly-sanitized data. # # This function, unlike f_dialog_data_sanitize(), also removes leading/trailing # whitespace from each line. # f_dialog_line_sanitize() { if [ "$#" -eq 0 ]; then f_dprintf "%s: called with zero arguments" \ f_dialog_response_sanitize return $FAILURE fi local __var_to_edit for __var_to_edit in $*; do # Skip warnings and trim leading/trailing whitespace setvar $__var_to_edit "$( f_getvar $__var_to_edit | awk ' BEGIN { data = 0 } { if ( ! data ) { if ( $0 ~ /^$/ ) next if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next data = 1 } sub(/^[[:space:]]*/, "") sub(/[[:space:]]*$/, "") print } ' )" done } ############################################################ TITLE FUNCTIONS # f_dialog_title [$new_title] # # Set the title of future dialog(1) ($DIALOG_TITLE) or backtitle of Xdialog(1) # ($DIALOG_BACKTITLE) invocations. If no arguments are given or the first # argument is NULL, the current title is returned. # # Each time this function is called, a backup of the current values is made # allowing a one-time (single-level) restoration of the previous title using # the f_dialog_title_restore() function (below). # f_dialog_title() { local new_title="$1" if [ "${1+set}" ]; then if [ "$USE_XDIALOG" ]; then _DIALOG_BACKTITLE="$DIALOG_BACKTITLE" DIALOG_BACKTITLE="$new_title" else _DIALOG_TITLE="$DIALOG_TITLE" DIALOG_TITLE="$new_title" fi else if [ "$USE_XDIALOG" ]; then echo "$DIALOG_BACKTITLE" else echo "$DIALOG_TITLE" fi fi } # f_dialog_title_restore # # Restore the previous title set by the last call to f_dialog_title(). # Restoration is non-recursive and only works to restore the most-recent title. # f_dialog_title_restore() { if [ "$USE_XDIALOG" ]; then DIALOG_BACKTITLE="$_DIALOG_BACKTITLE" else DIALOG_TITLE="$_DIALOG_TITLE" fi } # f_dialog_backtitle [$new_backtitle] # # Set the backtitle of future dialog(1) ($DIALOG_BACKTITLE) or title of # Xdialog(1) ($DIALOG_TITLE) invocations. If no arguments are given or the # first argument is NULL, the current backtitle is returned. # f_dialog_backtitle() { local new_backtitle="$1" if [ "${1+set}" ]; then if [ "$USE_XDIALOG" ]; then _DIALOG_TITLE="$DIALOG_TITLE" DIALOG_TITLE="$new_backtitle" else _DIALOG_BACKTITLE="$DIALOG_BACKTITLE" DIALOG_BACKTITLE="$new_backtitle" fi else if [ "$USE_XDIALOG" ]; then echo "$DIALOG_TITLE" else echo "$DIALOG_BACKTITLE" fi fi } # f_dialog_backtitle_restore # # Restore the previous backtitle set by the last call to f_dialog_backtitle(). # Restoration is non-recursive and only works to restore the most-recent # backtitle. # f_dialog_backtitle_restore() { if [ "$USE_XDIALOG" ]; then DIALOG_TITLE="$_DIALOG_TITLE" else DIALOG_BACKTITLE="$_DIALOG_BACKTITLE" fi } ############################################################ SIZE FUNCTIONS # f_dialog_max_size $var_height $var_width # # Get the maximum height and width for a dialog widget and store the values in # $var_height and $var_width (respectively). # f_dialog_max_size() { local funcname=f_dialog_max_size local __var_height="$1" __var_width="$2" __max_size [ "$__var_height" -o "$__var_width" ] || return $FAILURE if [ "$USE_XDIALOG" ]; then __max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION else if __max_size=$( $DIALOG --print-maxsize \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) then f_dprintf "$funcname: %s --print-maxsize = [%s]" \ "$DIALOG" "$__max_size" # usually "MaxSize: 24, 80" __max_size="${__max_size#*: }" f_replaceall "$__max_size" "," "" __max_size else f_eval_catch -dk __max_size $funcname stty \ 'stty size' || __max_size= # usually "24 80" fi : ${__max_size:=$DEFAULT_TERMINAL_SIZE} fi if [ "$__var_height" ]; then local __height="${__max_size%%[$IFS]*}" # # If we're not using Xdialog(1), we should assume that $DIALOG # will render --backtitle behind the widget. In such a case, we # should prevent a widget from obscuring the backtitle (unless # $NO_BACKTITLE is set and non-NULL, allowing a trap-door). # if [ ! "$USE_XDIALOG" ] && [ ! "$NO_BACKTITLE" ]; then # # If use_shadow (in ~/.dialogrc) is OFF, we need to # subtract 4, otherwise 5. However, don't check this # every time, rely on an initialization variable set # by f_dialog_init(). # local __adjust=5 [ "$NO_SHADOW" ] && __adjust=4 # Don't adjust height if already too small (allowing # obscured backtitle for small values of __height). [ ${__height:-0} -gt 11 ] && __height=$(( $__height - $__adjust )) fi setvar "$__var_height" "$__height" fi [ "$__var_width" ] && setvar "$__var_width" "${__max_size##*[$IFS]}" } # f_dialog_size_constrain $var_height $var_width [$min_height [$min_width]] # # Modify $var_height to be no-less-than $min_height (if given; zero otherwise) # and no-greater-than terminal height (or screen height if $USE_XDIALOG is # set). # # Also modify $var_width to be no-less-than $XDIALOG_MIN_WIDTH (or # $XDIALOG_MIN_WIDTH if $_USE_XDIALOG is set) and no-greater-than terminal # or screen width. The use of $[X]DIALOG_MIN_WIDTH can be overridden by # passing $min_width. # # Return status is success unless one of the passed arguments is invalid # or all of the $var_* arguments are either NULL or missing. # f_dialog_size_constrain() { local __var_height="$1" __var_width="$2" local __min_height="$3" __min_width="$4" local __retval=$SUCCESS # Return failure unless at least one var_* argument is passed [ "$__var_height" -o "$__var_width" ] || return $FAILURE # # Print debug warnings if any given (non-NULL) argument are invalid # NOTE: Don't change the name of $__{var,min,}{height,width} # local __height __width local __arg __cp __fname=f_dialog_size_constrain for __arg in height width; do debug= f_getvar __var_$__arg __cp [ "$__cp" ] || continue if ! debug= f_getvar "$__cp" __$__arg; then f_dprintf "%s: var_%s variable \`%s' not set" \ $__fname $__arg "$__cp" __retval=$FAILURE elif ! eval f_isinteger \$__$__arg; then f_dprintf "%s: var_%s variable value not a number" \ $__fname $__arg __retval=$FAILURE fi done for __arg in height width; do debug= f_getvar __min_$__arg __cp [ "$__cp" ] || continue f_isinteger "$__cp" && continue f_dprintf "%s: min_%s value not a number" $__fname $__arg __retval=$FAILURE setvar __min_$__arg "" done # Obtain maximum height and width values # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __max_height_size_constain __max_width_size_constrain f_dialog_max_size \ __max_height_size_constrain __max_width_size_constrain # Adjust height if desired if [ "$__var_height" ]; then if [ $__height -lt ${__min_height:-0} ]; then setvar "$__var_height" $__min_height elif [ $__height -gt $__max_height_size_constrain ]; then setvar "$__var_height" $__max_height_size_constrain fi fi # Adjust width if desired if [ "$__var_width" ]; then if [ "$USE_XDIALOG" ]; then : ${__min_width:=${XDIALOG_MIN_WIDTH:-35}} else : ${__min_width:=${DIALOG_MIN_WIDTH:-24}} fi if [ $__width -lt $__min_width ]; then setvar "$__var_width" $__min_width elif [ $__width -gt $__max_width_size_constrain ]; then setvar "$__var_width" $__max_width_size_constrain fi fi if [ "$debug" ]; then # Print final constrained values to debugging [ "$__var_height" ] && f_quietly f_getvar "$__var_height" [ "$__var_width" ] && f_quietly f_getvar "$__var_width" fi return $__retval # success if no debug warnings were printed } # f_dialog_menu_constrain $var_height $var_width $var_rows "$prompt" \ # [$min_height [$min_width [$min_rows]]] # # Modify $var_height to be no-less-than $min_height (if given; zero otherwise) # and no-greater-than terminal height (or screen height if $USE_XDIALOG is # set). # # Also modify $var_width to be no-less-than $XDIALOG_MIN_WIDTH (or # $XDIALOG_MIN_WIDTH if $_USE_XDIALOG is set) and no-greater-than terminal # or screen width. The use of $[X]DIALOG_MIN_WIDTH can be overridden by # passing $min_width. # # Last, modify $var_rows to be no-less-than $min_rows (if specified; zero # otherwise) and no-greater-than (max_height - 8) where max_height is the # terminal height (or screen height if $USE_XDIALOG is set). If $prompt is NULL # or missing, dialog(1) allows $var_rows to be (max_height - 7), maximizing the # number of visible rows. # # Return status is success unless one of the passed arguments is invalid # or all of the $var_* arguments are either NULL or missing. # f_dialog_menu_constrain() { local __var_height="$1" __var_width="$2" __var_rows="$3" __prompt="$4" local __min_height="$5" __min_width="$6" __min_rows="$7" # Return failure unless at least one var_* argument is passed [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] || return $FAILURE # # Print debug warnings if any given (non-NULL) argument are invalid # NOTE: Don't change the name of $__{var,min,}{height,width,rows} # local __height_menu_constrain __width_menu_constrain local __rows_menu_constrain local __arg __cp __fname=f_dialog_menu_constrain for __arg in height width rows; do debug= f_getvar __var_$__arg __cp [ "$__cp" ] || continue if ! debug= f_getvar "$__cp" __${__arg}_menu_constrain; then f_dprintf "%s: var_%s variable \`%s' not set" \ $__fname $__arg "$__cp" __retval=$FAILURE elif ! eval f_isinteger \$__${__arg}_menu_constrain; then f_dprintf "%s: var_%s variable value not a number" \ $__fname $__arg __retval=$FAILURE fi done for __arg in height width rows; do debug= f_getvar __min_$__arg __cp [ "$__cp" ] || continue f_isinteger "$__cp" && continue f_dprintf "%s: min_%s value not a number" $__fname $__arg __retval=$FAILURE setvar __min_$__arg "" done # Obtain maximum height and width values # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __max_height_menu_constrain __max_width_menu_constrain f_dialog_max_size \ __max_height_menu_constrain __max_width_menu_constrain # Adjust height if desired if [ "$__var_height" ]; then if [ $__height_menu_constrain -lt ${__min_height:-0} ]; then setvar "$__var_height" $__min_height elif [ $__height_menu_constrain -gt \ $__max_height_menu_constrain ] then setvar "$__var_height" $__max_height_menu_constrain fi fi # Adjust width if desired if [ "$__var_width" ]; then if [ "$USE_XDIALOG" ]; then : ${__min_width:=${XDIALOG_MIN_WIDTH:-35}} else : ${__min_width:=${DIALOG_MIN_WIDTH:-24}} fi if [ $__width_menu_constrain -lt $__min_width ]; then setvar "$__var_width" $__min_width elif [ $__width_menu_constrain -gt \ $__max_width_menu_constrain ] then setvar "$__var_width" $__max_width_menu_constrain fi fi # Adjust rows if desired if [ "$__var_rows" ]; then if [ "$USE_XDIALOG" ]; then : ${__min_rows:=1} else : ${__min_rows:=0} fi local __max_rows_menu_constrain=$(( $__max_height_menu_constrain - 7 )) # If prompt_len is zero (no prompt), bump the max-rows by 1 # Default assumption is (if no argument) that there's no prompt [ ${__prompt_len:-0} -gt 0 ] || __max_rows_menu_constrain=$(( $__max_rows_menu_constrain + 1 )) if [ $__rows_menu_constrain -lt $__min_rows ]; then setvar "$__var_rows" $__min_rows elif [ $__rows_menu_constrain -gt $__max_rows_menu_constrain ] then setvar "$__var_rows" $__max_rows_menu_constrain fi fi if [ "$debug" ]; then # Print final constrained values to debugging [ "$__var_height" ] && f_quietly f_getvar "$__var_height" [ "$__var_width" ] && f_quietly f_getvar "$__var_width" [ "$__var_rows" ] && f_quietly f_getvar "$__var_rows" fi return $__retval # success if no debug warnings were printed } # f_dialog_infobox_size [-n] $var_height $var_width \ # $title $backtitle $prompt [$hline] # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--infobox' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, and [optionally] hline. The optimal height and # width for the described widget (not exceeding the actual terminal height or # width) is stored in $var_height and $var_width (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # dialog(1). # f_dialog_infobox_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" __hline="$6" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # Default height/width of zero for auto-sizing local __height=0 __width=0 __n # Adjust height if desired if [ "$__var_height" ]; then # # Set height based on number of rows in prompt # __n=$( echo -n "$__prompt" | f_number_of_lines ) __n=$(( $__n + 2 )) [ $__n -gt $__height ] && __height=$__n # # For Xdialog(1) bump height if backtitle is enabled (displayed # in the X11 window with a separator line between the backtitle # and msg text). # if [ "$USE_XDIALOG" -a "$__btitle" ]; then __n=$( echo "$__btitle" | f_number_of_lines ) __height=$(( $__height + $__n + 2 )) fi setvar "$__var_height" $__height fi # Adjust width if desired if [ "$__var_width" ]; then # # Bump width for long titles # __n=$(( ${#__title} + 4 )) [ $__n -gt $__width ] && __width=$__n # # If using Xdialog(1), bump width for long backtitles (which # appear within the window). # if [ "$USE_XDIALOG" ]; then __n=$(( ${#__btitle} + 4 )) [ $__n -gt $__width ] && __width=$__n fi # # Bump width for long prompts # __n=$( echo "$__prompt" | f_longest_line_length ) __n=$(( $__n + 4 )) # add width for border [ $__n -gt $__width ] && __width=$__n # # Bump width for long hlines. Xdialog(1) supports `--hline' but # it's currently not used (so don't do anything here if using # Xdialog(1)). # if [ ! "$USE_XDIALOG" ]; then __n=$(( ${#__hline} + 10 )) [ $__n -gt $__width ] && __width=$__n fi # Bump width by 16.6% if using Xdialog(1) [ "$USE_XDIALOG" ] && __width=$(( $__width + $__width / 6 )) setvar "$__var_width" $__width fi # Constrain values to sensible minimums/maximums unless `-n' was passed # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_size_constrain "$__var_height" "$__var_width" } # f_dialog_buttonbox_size [-n] $var_height $var_width \ # $title $backtitle $prompt [$hline] # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--msgbox' and `--yesno' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, and [optionally] hline. The optimal height and # width for the described widget (not exceeding the actual terminal height or # width) is stored in $var_height and $var_width (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # dialog(1). # f_dialog_buttonbox_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" __hline="$6" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # Calculate height/width of infobox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_bbox_size __width_bbox_size f_dialog_infobox_size -n \ "${__var_height:+__height_bbox_size}" \ "${__var_width:+__width_bbox_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # Adjust height if desired if [ "$__var_height" ]; then # Add height to accomodate the buttons __height_bbox_size=$(( $__height_bbox_size + 2 )) # Adjust for clipping with Xdialog(1) on Linux/GTK2 [ "$USE_XDIALOG" ] && __height_bbox_size=$(( $__height_bbox_size + 3 )) setvar "$__var_height" $__height_bbox_size fi # No adjustemnts to width, just pass-thru the infobox width if [ "$__var_width" ]; then setvar "$__var_width" $__width_bbox_size fi # Constrain values to sensible minimums/maximums unless `-n' was passed # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_size_constrain "$__var_height" "$__var_width" } # f_dialog_inputbox_size [-n] $var_height $var_width \ # $title $backtitle $prompt $init [$hline] # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--inputbox' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, and [optionally] hline. The optimal height and # width for the described widget (not exceeding the actual terminal height or # width) is stored in $var_height and $var_width (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # dialog(1). # f_dialog_inputbox_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" __init="$6" __hline="$7" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # Calculate height/width of buttonbox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_ibox_size __width_ibox_size f_dialog_buttonbox_size -n \ "${__var_height:+__height_ibox_size}" \ "${__var_width:+__width_ibox_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # Adjust height if desired if [ "$__var_height" ]; then # Add height for input box (not needed for Xdialog(1)) [ ! "$USE_XDIALOG" ] && __height_ibox_size=$(( $__height_ibox_size + 3 )) setvar "$__var_height" $__height_ibox_size fi # Adjust width if desired if [ "$__var_width" ]; then # Bump width for initial text (something neither dialog(1) nor # Xdialog(1) do, but worth it!; add 16.6% if using Xdialog(1)) local __n=$(( ${#__init} + 7 )) [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) [ $__n -gt $__width_ibox_size ] && __width_ibox_size=$__n setvar "$__var_width" $__width_ibox_size fi # Constrain values to sensible minimums/maximums unless `-n' was passed # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_size_constrain "$__var_height" "$__var_width" } # f_xdialog_2inputsbox_size [-n] $var_height $var_width \ # $title $backtitle $prompt \ # $label1 $init1 $label2 $init2 # # Xdialog(1) does not perform auto-sizing of the width and height of # `--2inputsbox' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, label for the first field, initial text for said # field, label for the second field, and initial text for said field. The # optimal height and width for the described widget (not exceeding the actual # terminal height or width) is stored in $var_height and $var_width # (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # Xdialog(1). # f_xdialog_2inputsbox_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" local __label1="$6" __init1="$7" __label2="$8" __init2="$9" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # Calculate height/width of inputbox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_2ibox_size __width_2ibox_size f_dialog_inputbox_size -n \ "${__var_height:+__height_2ibox_size}" \ "${__var_width:+__width_2ibox_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" "$__init1" # Adjust height if desired if [ "$__var_height" ]; then # Add height for 1st label, 2nd label, and 2nd input box __height_2ibox_size=$(( $__height_2ibox_size + 2 + 2 + 2 )) setvar "$__var_height" $__height_2ibox_size fi # Adjust width if desired if [ "$__var_width" ]; then local __n # Bump width for first label text (+16.6% since Xdialog(1)) __n=$(( ${#__label1} + 7 )) __n=$(( $__n + $__n / 6 )) [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n # Bump width for second label text (+16.6% since Xdialog(1)) __n=$(( ${#__label2} + 7 )) __n=$(( $__n + $__n / 6 )) [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n # Bump width for 2nd initial text (something neither dialog(1) # nor Xdialog(1) do, but worth it!; +16.6% since Xdialog(1)) __n=$(( ${#__init2} + 7 )) __n=$(( $__n + $__n / 6 )) [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n setvar "$__var_width" $__width_2ibox_size fi # Constrain values to sensible minimums/maximums unless `-n' was passed # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_size_constrain "$__var_height" "$__var_width" } # f_dialog_menu_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $tag2 $item2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--menu' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the menu list itself (comprised of tag/item couplets). The # optimal height, width, and rows for the described widget (not exceeding the # actual terminal height or width) is stored in $var_height, $var_width, and # $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_menu_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" __var_rows="$3" local __title="$4" __btitle="$5" __prompt="$6" __hline="$7" shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] || return $FAILURE # Calculate height/width of infobox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_menu_size __width_menu_size f_dialog_infobox_size -n \ "${__var_height:+__height_menu_size}" \ "${__var_width:+__width_menu_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # # Always process the menu-item arguments to get the longest tag-length, # longest item-length (both used to bump the width), and the number of # rows (used to bump the height). # local __longest_tag=0 __longest_item=0 __rows=0 while [ $# -ge 2 ]; do local __tag="$1" __item="$2" shift 2 # tag/item [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag} [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item} __rows=$(( $__rows + 1 )) done # Adjust rows early (for up-comning height calculation) if [ "$__var_height" -o "$__var_rows" ]; then # Add a row for visual aid if using Xdialog(1) [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 )) fi # Adjust height if desired if [ "$__var_height" ]; then # Add rows to height if [ "$USE_XDIALOG" ]; then __height_menu_size=$(( $__height_menu_size + $__rows + 7 )) else __height_menu_size=$(( $__height_menu_size + $__rows + 4 )) fi setvar "$__var_height" $__height_menu_size fi # Adjust width if desired if [ "$__var_width" ]; then # The sum total between the longest tag-length and the # longest item-length should be used to bump menu width local __n=$(( $__longest_tag + $__longest_item + 10 )) [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_menu_size ] && __width_menu_size=$__n setvar "$__var_width" $__width_menu_size fi # Store adjusted rows if desired [ "$__var_rows" ] && setvar "$__var_rows" $__rows # Constrain height, width, and rows to sensible minimum/maximum values # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_menu_constrain \ "$__var_height" "$__var_width" "$__var_rows" "$__prompt" } # f_dialog_menu_with_help_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $help1 $tag2 $item2 $help2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--menu' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the menu list itself (comprised of tag/item/help triplets). The # optimal height, width, and rows for the described widget (not exceeding the # actual terminal height or width) is stored in $var_height, $var_width, and # $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_menu_with_help_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" __var_rows="$3" local __title="$4" __btitle="$5" __prompt="$6" __hline="$7" shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] || return $FAILURE # Calculate height/width of infobox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_menu_with_help_size __width_menu_with_help_size f_dialog_infobox_size -n \ "${__var_height:+__height_menu_with_help_size}" \ "${__var_width:+__width_menu_with_help_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # # Always process the menu-item arguments to get the longest tag-length, # longest item-length, longest help-length (help-length only considered # if using Xdialog(1), as it places the help string in the widget) -- # all used to bump the width -- and the number of rows (used to bump # the height). # local __longest_tag=0 __longest_item=0 __longest_help=0 __rows=0 while [ $# -ge 3 ]; do local __tag="$1" __item="$2" __help="$3" shift 3 # tag/item/help [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag} [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item} [ ${#__help} -gt $__longest_help ] && __longest_help=${#__help} __rows=$(( $__rows + 1 )) done # Adjust rows early (for up-coming height calculation) if [ "$__var_height" -o "$__var_rows" ]; then # Add a row for visual aid if using Xdialog(1) [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 )) fi # Adjust height if desired if [ "$__var_height" ]; then # Add rows to height if [ "$USE_XDIALOG" ]; then __height_menu_with_help_size=$(( $__height_menu_with_help_size + $__rows + 8 )) else __height_menu_with_help_size=$(( $__height_menu_with_help_size + $__rows + 4 )) fi setvar "$__var_height" $__height_menu_with_help_size fi # Adjust width if desired if [ "$__var_width" ]; then # The sum total between the longest tag-length and the # longest item-length should be used to bump menu width local __n=$(( $__longest_tag + $__longest_item + 10 )) [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_menu_with_help_size ] && __width_menu_with_help_size=$__n # Update width for help text if using Xdialog(1) if [ "$USE_XDIALOG" ]; then __n=$(( $__longest_help + 10 )) __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_menu_with_help_size ] && __width_menu_with_help_size=$__n fi setvar "$__var_width" $__width_menu_with_help_size fi # Store adjusted rows if desired [ "$__var_rows" ] && setvar "$__var_rows" $__rows # Constrain height, width, and rows to sensible minimum/maximum values # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_menu_constrain \ "$__var_height" "$__var_width" "$__var_rows" "$__prompt" } # f_dialog_radiolist_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $status1 $tag2 $item2 $status2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--radiolist' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the radio list itself (comprised of tag/item/status triplets). # The optimal height, width, and rows for the described widget (not exceeding # the actual terminal height or width) is stored in $var_height, $var_width, # and $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_radiolist_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" __var_rows="$3" local __title="$4" __btitle="$5" __prompt="$6" __hline="$7" shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] || return $FAILURE # Calculate height/width of infobox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_rlist_size __width_rlist_size f_dialog_infobox_size -n \ "${__var_height:+__height_rlist_size}" \ "${__var_width:+__width_rlist_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # # Always process the menu-item arguments to get the longest tag-length, # longest item-length (both used to bump the width), and the number of # rows (used to bump the height). # local __longest_tag=0 __longest_item=0 __rows_rlist_size=0 while [ $# -ge 3 ]; do local __tag="$1" __item="$2" shift 3 # tag/item/status [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag} [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item} __rows_rlist_size=$(( $__rows_rlist_size + 1 )) done # Adjust rows early (for up-coming height calculation) if [ "$__var_height" -o "$__var_rows" ]; then # Add a row for visual aid if using Xdialog(1) [ "$USE_XDIALOG" ] && __rows_rlist_size=$(( $__rows_rlist_size + 1 )) fi # Adjust height if desired if [ "$__var_height" ]; then # Add rows to height if [ "$USE_XDIALOG" ]; then __height_rlist_size=$(( $__height_rlist_size + $__rows_rlist_size + 7 )) else __height_rlist_size=$(( $__height_rlist_size + $__rows_rlist_size + 4 )) fi setvar "$__var_height" $__height_rlist_size fi # Adjust width if desired if [ "$__var_width" ]; then # Sum total between longest tag-length, longest item-length, # and radio-button width should be used to bump menu width local __n=$(( $__longest_tag + $__longest_item + 13 )) [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_rlist_size ] && __width_rlist_size=$__n setvar "$__var_width" $__width_rlist_size fi # Store adjusted rows if desired [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_size # Constrain height, width, and rows to sensible minimum/maximum values # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_menu_constrain \ "$__var_height" "$__var_width" "$__var_rows" "$__prompt" } # f_dialog_checklist_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $status1 $tag2 $item2 $status2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--checklist' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the check list itself (comprised of tag/item/status triplets). # The optimal height, width, and rows for the described widget (not exceeding # the actual terminal height or width) is stored in $var_height, $var_width, # and $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_checklist_size() { f_dialog_radiolist_size "$@" } # f_dialog_radiolist_with_help_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $status1 $help1 \ # $tag2 $item2 $status2 $help2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--radiolist' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the radio list itself (comprised of tag/item/status/help # quadruplets). The optimal height, width, and rows for the described widget # (not exceeding the actual terminal height or width) is stored in $var_height, # $var_width, and $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_radiolist_with_help_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" __var_rows="$3" local __title="$4" __btitle="$5" __prompt="$6" __hline="$7" shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] || return $FAILURE # Calculate height/width of infobox (adjusted/constrained below) # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_rlist_with_help_size __width_rlist_with_help_size f_dialog_infobox_size -n \ "${__var_height:+__height_rlist_with_help_size}" \ "${__var_width:+__width_rlist_with_help_size}" \ "$__title" "$__btitle" "$__prompt" "$__hline" # # Always process the menu-item arguments to get the longest tag-length, # longest item-length, longest help-length (help-length only considered # if using Xdialog(1), as it places the help string in the widget) -- # all used to bump the width -- and the number of rows (used to bump # the height). # local __longest_tag=0 __longest_item=0 __longest_help=0 local __rows_rlist_with_help_size=0 while [ $# -ge 4 ]; do local __tag="$1" __item="$2" __status="$3" __help="$4" shift 4 # tag/item/status/help [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag} [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item} [ ${#__help} -gt $__longest_help ] && __longest_help=${#__help} __rows_rlist_with_help_size=$(( $__rows_rlist_with_help_size + 1 )) done # Adjust rows early (for up-coming height calculation) if [ "$__var_height" -o "$__var_rows" ]; then # Add a row for visual aid if using Xdialog(1) [ "$USE_XDIALOG" ] && __rows_rlist_with_help_size=$(( $__rows_rlist_with_help_size + 1 )) fi # Adjust height if desired if [ "$__var_height" ]; then # Add rows to height if [ "$USE_XDIALOG" ]; then __height_rlist_with_help_size=$(( $__height_rlist_with_help_size + $__rows_rlist_with_help_size + 7 )) else __height_rlist_with_help_size=$(( $__height_rlist_with_help_size + $__rows_rlist_with_help_size + 4 )) fi setvar "$__var_height" $__height fi # Adjust width if desired if [ "$__var_width" ]; then # Sum total between longest tag-length, longest item-length, # and radio-button width should be used to bump menu width local __n=$(( $__longest_tag + $__longest_item + 13 )) [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_rlist_with_help_size ] && __width_rlist_with_help_size=$__n # Update width for help text if using Xdialog(1) if [ "$USE_XDIALOG" ]; then __n=$(( $__longest_help + 10 )) __n=$(( $__n + $__n / 6 )) # plus 16.6% [ $__n -gt $__width_rlist_with_help_size ] && __width_rlist_with_help_size=$__n fi setvar "$__var_width" $__width_rlist_with_help_size fi # Store adjusted rows if desired [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_with_help_size # Constrain height, width, and rows to sensible minimum/maximum values # Return success if no-constrain, else return status from constrain [ ! "$__constrain" ] || f_dialog_menu_constrain \ "$__var_height" "$__var_width" "$__var_rows" "$__prompt" } # f_dialog_checklist_with_help_size [-n] $var_height $var_width $var_rows \ # $title $backtitle $prompt $hline \ # $tag1 $item1 $status1 $help1 \ # $tag2 $item2 $status2 $help2 ... # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--checklist' boxes sensibly. # # This function helps solve this issue by taking three sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height, width, and rows. The second set of arguments # are the title, backtitle, prompt, and hline. The [optional] third set of # arguments are the check list itself (comprised of tag/item/status/help # quadruplets). The optimal height, width, and rows for the described widget # (not exceeding the actual terminal height or width) is stored in $var_height, # $var_width, and $var_rows (respectively). # # If the first argument is `-n', the calculated sizes ($var_height, $var_width, # and $var_rows) are not constrained to minimum/maximum values. # f_dialog_checklist_with_help_size() { f_dialog_radiolist_with_help_size "$@" } # f_dialog_calendar_size [-n] $var_height $var_width \ # $title $backtitle $prompt [$hline] # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--calendar' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, and [optionally] hline. The optimal height and # width for the described widget (not exceeding the actual terminal height or # width) is stored in $var_height and $var_width (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # dialog(1). # f_dialog_calendar_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" __hline="$6" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # # Obtain/Adjust minimum and maximum thresholds # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). # local __max_height_cal_size __max_width_cal_size f_dialog_max_size __max_height_cal_size __max_width_cal_size __max_width_cal_size=$(( $__max_width_cal_size - 2 )) # the calendar box will refuse to display if too wide local __min_width if [ "$USE_XDIALOG" ]; then __min_width=55 else __min_width=40 __max_height_cal_size=$(( $__max_height_cal_size - $DIALOG_CALENDAR_HEIGHT )) # When using dialog(1), we can't predict whether the user has # disabled shadow's in their `$HOME/.dialogrc' file, so we'll # subtract one for the potential shadow around the widget __max_height_cal_size=$(( $__max_height_cal_size - 1 )) fi # Calculate height if desired if [ "$__var_height" ]; then local __height __height=$( echo "$__prompt" | f_number_of_lines ) if [ "$USE_XDIALOG" ]; then # Add height to accomodate for embedded calendar widget __height=$(( $__height + $DIALOG_CALENDAR_HEIGHT - 1 )) # Also, bump height if backtitle is enabled if [ "$__btitle" ]; then local __n __n=$( echo "$__btitle" | f_number_of_lines ) __height=$(( $__height + $__n + 2 )) fi else [ "$__prompt" ] && __height=$(( $__height + 1 )) fi # Enforce maximum height, unless `-n' was passed [ "$__constrain" -a $__height -gt $__max_height_cal_size ] && __height=$__max_height_cal_size setvar "$__var_height" $__height fi # Calculate width if desired if [ "$__var_width" ]; then # NOTE: Function name appended to prevent __var_{height,width} # values from becoming local (and thus preventing setvar # from working). local __width_cal_size f_dialog_infobox_size -n "" __width_cal_size \ "$__title" "$__btitle" "$__prompt" "$__hline" # Enforce minimum/maximum width, unless `-n' was passed if [ "$__constrain" ]; then if [ $__width_cal_size -lt $__min_width ]; then __width_cal_size=$__min_width elif [ $__width_cal_size -gt $__max_width_cal_size ] then __width_cal_size=$__max_width_size fi fi setvar "$__var_width" $__width_cal_size fi return $SUCCESS } # f_dialog_timebox_size [-n] $var_height $var_width \ # $title $backtitle $prompt [$hline] # # Not all versions of dialog(1) perform auto-sizing of the width and height of # `--timebox' boxes sensibly. # # This function helps solve this issue by taking two sets of sequential # arguments. The first set of arguments are the variable names to use when # storing the calculated height and width. The second set of arguments are the # title, backtitle, prompt, and [optionally] hline. The optional height and # width for the described widget (not exceeding the actual terminal height or # width) is stored in $var_height and $var_width (respectively). # # If the first argument is `-n', the calculated sizes ($var_height and # $var_width) are not constrained to minimum/maximum values. # # Newline character sequences (``\n'') in $prompt are expanded as-is done by # dialog(1). # f_dialog_timebox_size() { local __constrain=1 [ "$1" = "-n" ] && __constrain= && shift 1 # -n local __var_height="$1" __var_width="$2" local __title="$3" __btitle="$4" __prompt="$5" __hline="$6" # Return unless at least one size aspect has been requested [ "$__var_height" -o "$__var_width" ] || return $FAILURE # # Obtain/Adjust minimum and maximum thresholds # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). # local __max_height_tbox_size __max_width_tbox_size f_dialog_max_size __max_height_tbox_size __max_width_tbox_size __max_width_tbox_size=$(( $__max_width_tbox_size - 2 )) # the timebox widget refuses to display if too wide local __min_width if [ "$USE_XDIALOG" ]; then __min_width=40 else __min_width=20 __max_height_tbox_size=$(( \ $__max_height_tbox_size - $DIALOG_TIMEBOX_HEIGHT )) # When using dialog(1), we can't predict whether the user has # disabled shadow's in their `$HOME/.dialogrc' file, so we'll # subtract one for the potential shadow around the widget __max_height_tbox_size=$(( $__max_height_tbox_size - 1 )) fi # Calculate height if desired if [ "$__var_height" -a "$USE_XDIALOG" ]; then # When using Xdialog(1), the height seems to have # no effect. All values provide the same results. setvar "$__var_height" 0 # autosize elif [ "$__var_height" ]; then local __height __height=$( echo "$__prompt" | f_number_of_lines ) __height=$(( $__height ${__prompt:++1} + 1 )) # Enforce maximum height, unless `-n' was passed [ "$__constrain" -a $__height -gt $__max_height_tbox_size ] && __height=$__max_height_tbox_size setvar "$__var_height" $__height fi # Calculate width if desired if [ "$__var_width" ]; then # NOTE: Function name appended to prevent __var_{height,width} # values from becoming local (and thus preventing setvar # from working). local __width_tbox_size f_dialog_infobox_size -n "" __width_tbox_size \ "$__title" "$__btitle" "$__prompt" "$__hline" # Enforce the minimum width for displaying the timebox if [ "$__constrain" ]; then if [ $__width_tbox_size -lt $__min_width ]; then __width_tbox_size=$__min_width elif [ $__width_tbox_size -ge $__max_width_tbox_size ] then __width_tbox_size=$__max_width_tbox_size fi fi setvar "$__var_width" $__width_tbox_size fi return $SUCCESS } ############################################################ CLEAR FUNCTIONS # f_dialog_clear # # Clears any/all previous dialog(1) displays. # f_dialog_clear() { $DIALOG --clear } ############################################################ INFO FUNCTIONS # f_dialog_info $info_text ... # # Throw up a dialog(1) infobox. The infobox remains until another dialog is # displayed or `dialog --clear' (or f_dialog_clear) is called. # f_dialog_info() { local info_text="$*" height width f_dialog_infobox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$info_text" $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ ${USE_XDIALOG:+--ignore-eof} \ ${USE_XDIALOG:+--no-buttons} \ --infobox "$info_text" $height $width } # f_xdialog_info $info_text ... # # Throw up an Xdialog(1) infobox and do not dismiss it until stdin produces # EOF. This implies that you must execute this either as an rvalue to a pipe, # lvalue to indirection or in a sub-shell that provides data on stdin. # # To open an Xdialog(1) infobox that does not disappear until expeclitly dis- # missed, use the following: # # f_xdialog_info "$info_text" < /dev/tty & # pid=$! # # Perform some lengthy actions # kill $pid # # NB: Check $USE_XDIALOG if you need to support both dialog(1) and Xdialog(1). # f_xdialog_info() { local info_text="$*" height width f_dialog_infobox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$info_text" exec $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --no-close --no-buttons \ --infobox "$info_text" $height $width \ -1 # timeout of -1 means abort when EOF on stdin } ############################################################ PAUSE FUNCTIONS # f_dialog_pause $msg_text $duration [$hline] # # Display a message in a widget with a progress bar that runs backward for # $duration seconds. # f_dialog_pause() { local pause_text="$1" duration="$2" hline="$3" height width f_isinteger "$duration" || return $FAILURE f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$pause_text" "$hline" if [ "$USE_XDIALOG" ]; then $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --ok-label "$msg_skip" \ --cancel-label "$msg_cancel" \ ${noCancel:+--no-cancel} \ --timeout "$duration" \ --yesno "$pause_text" \ $height $width else [ $duration -gt 0 ] && duration=$(( $duration - 1 )) [ $duration -gt 1 ] && duration=$(( $duration - 1 )) height=$(( $height + 3 )) # Add height for progress bar $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --ok-label "$msg_skip" \ --cancel-label "$msg_cancel" \ ${noCancel:+--no-cancel} \ --pause "$pause_text" \ $height $width "$duration" fi } # f_dialog_pause_no_cancel $msg_text $duration [$hline] # # Display a message in a widget with a progress bar that runs backward for # $duration seconds. No cancel button is provided. Always returns success. # f_dialog_pause_no_cancel() { noCancel=1 f_dialog_pause "$@" return $SUCCESS } ############################################################ MSGBOX FUNCTIONS # f_dialog_msgbox $msg_text [$hline] # # Throw up a dialog(1) msgbox. The msgbox remains until the user presses ENTER # or ESC, acknowledging the modal dialog. # # If the user presses ENTER, the exit status is zero (success), otherwise if # the user presses ESC the exit status is 255. # f_dialog_msgbox() { local msg_text="$1" hline="$2" height width f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline" $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --ok-label "$msg_ok" \ --msgbox "$msg_text" $height $width } ############################################################ TEXTBOX FUNCTIONS # f_dialog_textbox $file # # Display the contents of $file (or an error if $file does not exist, etc.) in # a dialog(1) textbox (which has a scrollable region for the text). The textbox # remains until the user presses ENTER or ESC, acknowledging the modal dialog. # # If the user presses ENTER, the exit status is zero (success), otherwise if # the user presses ESC the exit status is 255. # f_dialog_textbox() { local file="$1" local contents height width retval contents=$( cat "$file" 2>&1 ) retval=$? f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$contents" if [ $retval -eq $SUCCESS ]; then $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --exit-label "$msg_ok" \ --no-cancel \ --textbox "$file" $height $width else $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --ok-label "$msg_ok" \ --msgbox "$contents" $height $width fi } ############################################################ YESNO FUNCTIONS # f_dialog_yesno $msg_text [$hline] # # Display a dialog(1) Yes/No prompt to allow the user to make some decision. # The yesno prompt remains until the user presses ENTER or ESC, acknowledging # the modal dialog. # # If the user chooses YES the exit status is zero, or chooses NO the exit # status is one, or presses ESC the exit status is 255. # f_dialog_yesno() { local msg_text="$1" height width local hline="${2-$hline_arrows_tab_enter}" f_interactive || return 0 # If non-interactive, return YES all the time f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline" if [ "$USE_XDIALOG" ]; then $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --ok-label "$msg_yes" \ --cancel-label "$msg_no" \ --yesno "$msg_text" $height $width else $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --yes-label "$msg_yes" \ --no-label "$msg_no" \ --yesno "$msg_text" $height $width fi } # f_dialog_noyes $msg_text [$hline] # # Display a dialog(1) No/Yes prompt to allow the user to make some decision. # The noyes prompt remains until the user presses ENTER or ESC, acknowledging # the modal dialog. # # If the user chooses YES the exit status is zero, or chooses NO the exit # status is one, or presses ESC the exit status is 255. # # NOTE: This is just like the f_dialog_yesno function except "No" is default. # f_dialog_noyes() { local msg_text="$1" height width local hline="${2-$hline_arrows_tab_enter}" f_interactive || return 1 # If non-interactive, return NO all the time f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline" if [ "$USE_XDIALOG" ]; then $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --default-no \ --ok-label "$msg_yes" \ --cancel-label "$msg_no" \ --yesno "$msg_text" $height $width else $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$hline" \ --defaultno \ --yes-label "$msg_yes" \ --no-label "$msg_no" \ --yesno "$msg_text" $height $width fi } ############################################################ INPUT FUNCTIONS # f_dialog_inputstr_store [-s] $text # # Store some text from a dialog(1) inputbox to be retrieved later by # f_dialog_inputstr_fetch(). If the first argument is `-s', the text is # sanitized before being stored. # f_dialog_inputstr_store() { local sanitize= [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s local text="$1" # Sanitize the line before storing it if desired [ "$sanitize" ] && f_dialog_line_sanitize text setvar DIALOG_INPUTBOX_$$ "$text" } # f_dialog_inputstr_fetch [$var_to_set] # # Obtain the inputstr entered by the user from the most recently displayed # dialog(1) inputbox (previously stored with f_dialog_inputstr_store() above). # If $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # f_dialog_inputstr_fetch() { local __var_to_set="$1" __cp debug= f_getvar DIALOG_INPUTBOX_$$ "${__var_to_set:-__cp}" # get data setvar DIALOG_INPUTBOX_$$ "" # scrub memory in case data was sensitive # Return the line on standard-out if desired [ "$__var_to_set" ] || echo "$__cp" return $SUCCESS } # f_dialog_input $var_to_set $prompt [$init [$hline]] # # Prompt the user with a dialog(1) inputbox to enter some value. The inputbox # remains until the the user presses ENTER or ESC, or otherwise ends the # editing session (by selecting `Cancel' for example). # # If the user presses ENTER, the exit status is zero (success), otherwise if # the user presses ESC the exit status is 255, or if the user chose Cancel, the # exit status is instead 1. # # NOTE: The hline should correspond to the type of data you want from the user. # NOTE: Should not be used to edit multiline values. # f_dialog_input() { local __var_to_set="$1" __prompt="$2" __init="$3" __hline="$4" # NOTE: Function name appended to prevent __var_{height,width} values # from becoming local (and thus preventing setvar from working). local __height_input __width_input f_dialog_inputbox_size __height_input __width_input \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \ "$__prompt" "$__init" "$__hline" local __opterm="--" [ "$USE_XDIALOG" ] && __opterm= local __dialog_input __dialog_input=$( $DIALOG \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --hline "$__hline" \ --ok-label "$msg_ok" \ --cancel-label "$msg_cancel" \ --inputbox "$__prompt" \ $__height_input $__width_input \ $__opterm "$__init" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local __retval=$? # Remove warnings and leading/trailing whitespace from user input f_dialog_line_sanitize __dialog_input setvar "$__var_to_set" "$__dialog_input" return $__retval } ############################################################ MENU FUNCTIONS # f_dialog_menutag_store [-s] $text # # Store some text from a dialog(1) menu to be retrieved later by # f_dialog_menutag_fetch(). If the first argument is `-s', the text is # sanitized before being stored. # f_dialog_menutag_store() { local sanitize= [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s local text="$1" # Sanitize the menutag before storing it if desired [ "$sanitize" ] && f_dialog_data_sanitize text setvar DIALOG_MENU_$$ "$text" } # f_dialog_menutag_fetch [$var_to_set] # # Obtain the menutag chosen by the user from the most recently displayed # dialog(1) menu (previously stored with f_dialog_menutag_store() above). If # $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # f_dialog_menutag_fetch() { local __var_to_set="$1" __cp debug= f_getvar DIALOG_MENU_$$ "${__var_to_set:-__cp}" # get the data setvar DIALOG_MENU_$$ "" # scrub memory in case data was sensitive # Return the data on standard-out if desired [ "$__var_to_set" ] || echo "$__cp" return $SUCCESS } # f_dialog_menuitem_store [-s] $text # # Store the item from a dialog(1) menu (see f_dialog_menutag2item()) to be # retrieved later by f_dialog_menuitem_fetch(). If the first argument is `-s', # the text is sanitized before being stored. # f_dialog_menuitem_store() { local sanitize= [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s local text="$1" # Sanitize the menuitem before storing it if desired [ "$sanitize" ] && f_dialog_data_sanitize text setvar DIALOG_MENUITEM_$$ "$text" } # f_dialog_menuitem_fetch [$var_to_set] # # Obtain the menuitem chosen by the user from the most recently displayed # dialog(1) menu (previously stored with f_dialog_menuitem_store() above). If # $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # f_dialog_menuitem_fetch() { local __var_to_set="$1" __cp debug= f_getvar DIALOG_MENUITEM_$$ "${__var_to_set:-__cp}" # get data setvar DIALOG_MENUITEM_$$ "" # scrub memory in case data was sensitive # Return the data on standard-out if desired [ "$__var_to_set" ] || echo "$__cp" return $SUCCESS } # f_dialog_default_store [-s] $text # # Store some text to be used later as the --default-item argument to dialog(1) # (or Xdialog(1)) for --menu, --checklist, and --radiolist widgets. Retrieve # the text later with f_dialog_menutag_fetch(). If the first argument is `-s', # the text is sanitized before being stored. # f_dialog_default_store() { local sanitize= [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s local text="$1" # Sanitize the defaulitem before storing it if desired [ "$sanitize" ] && f_dialog_data_sanitize text setvar DEFAULTITEM_$$ "$text" } # f_dialog_default_fetch [$var_to_set] # # Obtain text to be used with the --default-item argument of dialog(1) (or # Xdialog(1)) (previously stored with f_dialog_default_store() above). If # $var_to_set is NULL or missing, output is printed to stdout (which is less # recommended due to performance degradation; in a loop for example). # f_dialog_default_fetch() { local __var_to_set="$1" __cp debug= f_getvar DEFAULTITEM_$$ "${__var_to_set:-__cp}" # get the data setvar DEFAULTITEM_$$ "" # scrub memory in case data was sensitive # Return the data on standard-out if desired [ "$__var_to_set" ] || echo "$__cp" return $SUCCESS } # f_dialog_menutag2item $tag_chosen $tag1 $item1 $tag2 $item2 ... # # To use the `--menu' option of dialog(1) you must pass an ordered list of # tag/item pairs on the command-line. When the user selects a menu option the # tag for that item is printed to stderr. # # This function allows you to dereference the tag chosen by the user back into # the item associated with said tag. # # Pass the tag chosen by the user as the first argument, followed by the # ordered list of tag/item pairs (HINT: use the same tag/item list as was # passed to dialog(1) for consistency). # # If the tag cannot be found, NULL is returned. # f_dialog_menutag2item() { local tag="$1" tagn item shift 1 # tag while [ $# -gt 0 ]; do tagn="$1" item="$2" shift 2 # tagn/item if [ "$tag" = "$tagn" ]; then echo "$item" return $SUCCESS fi done return $FAILURE } # f_dialog_menutag2item_with_help $tag_chosen $tag1 $item1 $help1 \ # $tag2 $item2 $help2 ... # # To use the `--menu' option of dialog(1) with the `--item-help' option, you # must pass an ordered list of tag/item/help triplets on the command-line. When # the user selects a menu option the tag for that item is printed to stderr. # # This function allows you to dereference the tag chosen by the user back into # the item associated with said tag (help is discarded/ignored). # # Pass the tag chosen by the user as the first argument, followed by the # ordered list of tag/item/help triplets (HINT: use the same tag/item/help list # as was passed to dialog(1) for consistency). # # If the tag cannot be found, NULL is returned. # f_dialog_menutag2item_with_help() { local tag="$1" tagn item shift 1 # tag while [ $# -gt 0 ]; do tagn="$1" item="$2" shift 3 # tagn/item/help if [ "$tag" = "$tagn" ]; then echo "$item" return $SUCCESS fi done return $FAILURE } # f_dialog_menutag2index $tag_chosen $tag1 $item1 $tag2 $item2 ... # # To use the `--menu' option of dialog(1) you must pass an ordered list of # tag/item pairs on the command-line. When the user selects a menu option the # tag for that item is printed to stderr. # # This function allows you to dereference the tag chosen by the user back into # the index associated with said tag. The index is the one-based tag/item pair # array position within the ordered list of tag/item pairs passed to dialog(1). # # Pass the tag chosen by the user as the first argument, followed by the # ordered list of tag/item pairs (HINT: use the same tag/item list as was # passed to dialog(1) for consistency). # # If the tag cannot be found, NULL is returned. # f_dialog_menutag2index() { local tag="$1" tagn n=1 shift 1 # tag while [ $# -gt 0 ]; do tagn="$1" shift 2 # tagn/item if [ "$tag" = "$tagn" ]; then echo $n return $SUCCESS fi n=$(( $n + 1 )) done return $FAILURE } # f_dialog_menutag2index_with_help $tag_chosen $tag1 $item1 $help1 \ # $tag2 $item2 $help2 ... # # To use the `--menu' option of dialog(1) with the `--item-help' option, you # must pass an ordered list of tag/item/help triplets on the command-line. When # the user selects a menu option the tag for that item is printed to stderr. # # This function allows you to dereference the tag chosen by the user back into # the index associated with said tag. The index is the one-based tag/item/help # triplet array position within the ordered list of tag/item/help triplets # passed to dialog(1). # # Pass the tag chosen by the user as the first argument, followed by the # ordered list of tag/item/help triplets (HINT: use the same tag/item/help list # as was passed to dialog(1) for consistency). # # If the tag cannot be found, NULL is returned. # f_dialog_menutag2index_with_help() { local tag="$1" tagn n=1 shift 1 # tag while [ $# -gt 0 ]; do tagn="$1" shift 3 # tagn/item/help if [ "$tag" = "$tagn" ]; then echo $n return $SUCCESS fi n=$(( $n + 1 )) done return $FAILURE } # f_dialog_menutag2help $tag_chosen $tag1 $item1 $help1 $tag2 $item2 $help2 ... # # To use the `--menu' option of dialog(1) with the `--item-help' option, you # must pass an ordered list of tag/item/help triplets on the command-line. When # the user selects a menu option the tag for that item is printed to stderr. # # This function allows you to dereference the tag chosen by the user back into # the help associated with said tag (item is discarded/ignored). # # Pass the tag chosen by the user as the first argument, followed by the # ordered list of tag/item/help triplets (HINT: use the same tag/item/help list # as was passed to dialog(1) for consistency). # # If the tag cannot be found, NULL is returned. # f_dialog_menutag2help() { local tag="$1" tagn help shift 1 # tag while [ $# -gt 0 ]; do tagn="$1" help="$3" shift 3 # tagn/item/help if [ "$tag" = "$tagn" ]; then echo "$help" return $SUCCESS fi done return $FAILURE } ############################################################ INIT FUNCTIONS # f_dialog_init # # Initialize (or re-initialize) the dialog module after setting/changing any # of the following environment variables: # # USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate # that Xdialog(1) should be used instead of dialog(1). # # SECURE Either NULL or Non-NULL. If given a value will indicate # that (while running as root) sudo(8) authentication is # required to proceed. # # Also reads ~/.dialogrc for the following information: # # NO_SHADOW Either NULL or Non-NULL. If use_shadow is OFF (case- # insensitive) in ~/.dialogrc this is set to "1" (otherwise # unset). # f_dialog_init() { local funcname=f_dialog_init DIALOG_SELF_INITIALIZE= USE_DIALOG=1 # # Clone terminal stdout so we can redirect to it from within sub-shells # eval exec $DIALOG_TERMINAL_PASSTHRU_FD\>\&1 # # Add `-S' and `-X' to the list of standard arguments supported by all # case "$GETOPTS_STDARGS" in *SX*) : good ;; # already present *) GETOPTS_STDARGS="${GETOPTS_STDARGS}SX" esac # # Process stored command-line arguments # # NB: Using backticks instead of $(...) for portability since Linux # bash(1) balks at the right parentheses encountered in the case- # statement (incorrectly interpreting it as the close of $(...)). # f_dprintf "f_dialog_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \ "$ARGV" "$GETOPTS_STDARGS" SECURE=`set -- $ARGV OPTIND=1 while getopts \ "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \ flag > /dev/null; do case "$flag" in S) echo 1 ;; esac done ` # END-BACKTICK USE_XDIALOG=`set -- $ARGV OPTIND=1 while getopts \ "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \ flag > /dev/null; do case "$flag" in S|X) echo 1 ;; esac done ` # END-BACKTICK f_dprintf "f_dialog_init: SECURE=[%s] USE_XDIALOG=[%s]" \ "$SECURE" "$USE_XDIALOG" # # Process `-X' command-line option # [ "$USE_XDIALOG" ] && DIALOG=Xdialog USE_DIALOG= # # Sanity check, or die gracefully # if ! f_have $DIALOG; then unset USE_XDIALOG local failed_dialog="$DIALOG" DIALOG=dialog f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$failed_dialog" fi # # Read ~/.dialogrc (unless using Xdialog(1)) for properties # if [ -f ~/.dialogrc -a ! "$USE_XDIALOG" ]; then eval "$( awk -v param=use_shadow -v expect=OFF \ -v set="NO_SHADOW=1" ' !/^[[:space:]]*(#|$)/ && \ tolower($1) ~ "^"param"(=|$)" && \ /[^#]*=/ { sub(/^[^=]*=[[:space:]]*/, "") if ( toupper($1) == expect ) print set";" }' ~/.dialogrc )" fi # # If we're already running as root but we got there by way of sudo(8) # and we have X11, we should merge the xauth(1) credentials from our # original user. # if [ "$USE_XDIALOG" ] && [ "$( id -u )" = "0" ] && [ "$SUDO_USER" -a "$DISPLAY" ] then if ! f_have xauth; then # Die gracefully, as we [likely] can't use Xdialog(1) unset USE_XDIALOG DIALOG=dialog f_die 1 "$msg_no_such_file_or_directory" "$pgm" "xauth" fi HOSTNAME=$( hostname ) local displaynum="${DISPLAY#*:}" eval xauth -if \~$SUDO_USER/.Xauthority extract - \ \"\$HOSTNAME/unix:\$displaynum\" \ \"\$HOSTNAME:\$displaynum\" | sudo sh -c 'xauth -ivf \ ~root/.Xauthority merge - > /dev/null 2>&1' fi # # Probe Xdialog(1) for maximum height/width constraints, or die # gracefully # if [ "$USE_XDIALOG" ]; then local maxsize if ! f_eval_catch -dk maxsize $funcname "$DIALOG" \ 'LANG= LC_ALL= %s --print-maxsize' "$DIALOG" then # Xdialog(1) failed, fall back to dialog(1) unset USE_XDIALOG # Display the error message produced by Xdialog(1) local height width f_dialog_buttonbox_size height width \ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$maxsize" dialog \ --title "$DIALOG_TITLE" \ --backtitle "$DIALOG_BACKTITLE" \ --ok-label "$msg_ok" \ --msgbox "$maxsize" $height $width exit $FAILURE fi XDIALOG_MAXSIZE=$( set -- ${maxsize##*:} height=${1%,} width=$2 echo $height $width ) fi # # If using Xdialog(1), swap DIALOG_TITLE with DIALOG_BACKTITLE. # The reason for this is because many dialog(1) applications use # --backtitle for the program name (which is better suited as # --title with Xdialog(1)). # if [ "$USE_XDIALOG" ]; then local _DIALOG_TITLE="$DIALOG_TITLE" DIALOG_TITLE="$DIALOG_BACKTITLE" DIALOG_BACKTITLE="$_DIALOG_TITLE" fi f_dprintf "f_dialog_init: dialog(1) API initialized." } ############################################################ MAIN # # Self-initialize unless requested otherwise # f_dprintf "%s: DIALOG_SELF_INITIALIZE=[%s]" \ dialog.subr "$DIALOG_SELF_INITIALIZE" case "$DIALOG_SELF_INITIALIZE" in ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; *) f_dialog_init esac f_dprintf "%s: Successfully loaded." dialog.subr fi # ! $_DIALOG_SUBR diff --git a/usr.sbin/bsdconfig/share/keymap.subr b/usr.sbin/bsdconfig/share/keymap.subr index 41f59cf7a3ef..7f2f87c91b38 100644 --- a/usr.sbin/bsdconfig/share/keymap.subr +++ b/usr.sbin/bsdconfig/share/keymap.subr @@ -1,263 +1,263 @@ if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1 # -# Copyright (c) 2013 Devin Teske +# Copyright (c) 2013-2015 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..." keymap.subr f_include $BSDCFG_SHARE/struct.subr ############################################################ CONFIGURATION # # Defaults taken from usr.sbin/kbdmap/kbdmap.h # : ${DEFAULT_LANG:=en} : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} ############################################################ GLOBALS KEYMAPS= NKEYMAPS=0 # A "keymap" from kbdmap's point of view f_struct_define KEYMAP \ desc \ keym \ mark # # Default behavior is to call f_keymap_get_all() automatically when loaded. # : ${KEYMAP_SELF_SCAN_ALL=1} ############################################################ FUNCTIONS # f_keymap_register $name $desc $keym $mark # # Register a keymap. A `structure' (see struct.subr) is created with the name # keymap_$name (so make sure $name contains only alpha-numeric characters or # the underscore, `_'). The remaining arguments after $name correspond to the # propertise of the `KEYMAP' structure-type (defined above). # # If not already registered, the keymap is then appended to the KEYMAPS # environment variable, a space-separated list of all registered keymaps. # f_keymap_register() { local name="$1" desc="$2" keym="$3" mark="$4" f_struct_new KEYMAP "keymap_$name" || return $FAILURE keymap_$name set desc "$desc" keymap_$name set keym "$keym" keymap_$name set mark "$mark" # Scan our global register to see if needs ammending local k found= for k in $KEYMAPS; do [ "$k" = "$name" ] || continue found=1 && break done [ "$found" ] || KEYMAPS="$KEYMAPS $name" return $SUCCESS } # f_keymap_checkfile $keymap # # Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap # is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure. # If debugging is enabled, an appropriate debug error message is printed if # $keymap is not available. # f_keymap_checkfile() { local keym="$1" # Fixup keymap if it doesn't already contain at least one `/' [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym" # Short-cuts [ -f "$keym" -a -r "$keym" ] && return $SUCCESS f_debugging || return $FAILURE # Print an appropriate debug error message if [ ! -e "$keym" ]; then f_dprintf "%s: No such file or directory" "$keym" elif [ ! -f "$keym" ]; then f_dprintf "%s: Not a file!" "$keym" elif [ ! -r "$keym" ]; then f_dprintf "%s: Permission denied" "$keym" fi return $FAILURE } # f_keymap_get_all # # Get all keymap information for kbdmap(5) entries both in the database and # loosely existing in $DEFAULT_KEYMAP_DIR. # f_keymap_get_all() { local fname=f_keymap_get_all local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}" [ "$lang" = "C" ] && lang="$DEFAULT_LANG" f_dprintf "%s: Looking for keymap files..." $fname f_dialog_info "$msg_looking_for_keymap_files" f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG" eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" ' BEGIN { # en_US.ISO8859-1 -> en_..\.ISO8859-1 dialect = lang if (length(dialect) >= 6 && substr(dialect, 3, 1) == "_") dialect = substr(dialect, 1, 3) ".." \ substr(dialect, 6) printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect # en_US.ISO8859-1 -> en lang_abk = lang if (length(lang_abk) >= 3 && substr(lang_abk, 3, 1) == "_") lang_abk = substr(lang_abk, 1, 2) printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n", lang_abk } function find_token(buffer, token) { if (split(buffer, tokens, /,/) == 0) return 0 found = 0 for (t in tokens) if (token == tokens[t]) { found = 1; break } return found } function add_keymap(desc,mark,keym) { marks[keym] = mark name = keym gsub(/[^[:alnum:]_]/, "_", name) gsub(/'\''/, "'\''\\'\'\''", desc); printf "f_keymap_checkfile %s && " \ "f_keymap_register %s '\'%s\'' %s %u\n", keym, name, desc, keym, mark } !/^[[:space:]]*(#|$)/ { sub(/^[[:space:]]*/, "", $0) keym = $1 if (keym ~ /^(MENU|FONT)$/) next lg = ($2 == "" ? lang_default : $2) # Match the entry and store the type of match we made # as the mark value (so that if we make a better match # later on with a higher mark, it overwrites previous) mark = marks[keym]; if (find_token(lg, lang)) add_keymap($3, 4, keym) # Best match else if (mark <= 3 && find_token(lg, dialect)) add_keymap($3, 3, keym) else if (mark <= 2 && find_token(lg, lang_abk)) add_keymap($3, 2, keym) else if (mark <= 1 && find_token(lg, lang_default)) add_keymap($3, 1, keym) else if (mark <= 0) add_keymap($3, 0, keym) } ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )" # # Look for keymaps not in database # local direntry keym name set +f # glob for direntry in "$DEFAULT_KEYMAP_DIR"/*; do [ "${direntry##*.}" = ".kbd" ] || continue keym="${direntry##*/}" f_str2varname "$keym" name f_struct keymap_$name && continue f_keymap_checkfile "$keym" && f_keymap_register $name "${keym%.*}" "$keym" 0 f_dprintf "%s: not in kbdmap(5) database" "$keym" done # # Sort the items by their descriptions # f_dprintf "%s: Sorting keymap entries by description..." $fname KEYMAPS=$( for k in $KEYMAPS; do echo -n "$k " # NOTE: Translate '8x8' to '8x08' before sending to # sort(1) so that things work out as we might expect. debug= keymap_$k get desc | awk 'gsub(/8x8/,"8x08")||1' done | sort -k2 | awk '{ printf "%s%s", (started ? " " : ""), $1; started = 1 }' ) return $SUCCESS } # f_keymap_kbdcontrol $keymap # # Install keyboard map file from $keymap. # f_keymap_kbdcontrol() { local keymap="$1" [ "$keymap" ] || return $SUCCESS # Fixup keymap if it doesn't already contain at least one `/' [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap" [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap" } ############################################################ MAIN # # Scan for keymaps unless requeted otherwise # f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL" case "$KEYMAP_SELF_SCAN_ALL" in ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; *) f_keymap_get_all esac f_count NKEYMAPS $KEYMAPS f_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS f_dprintf "%s: Successfully loaded." keymap.subr fi # ! $_KEYMAP_SUBR diff --git a/usr.sbin/bsdconfig/usermgmt/share/user.subr b/usr.sbin/bsdconfig/usermgmt/share/user.subr index e6beb54a6065..d0e38878b348 100644 --- a/usr.sbin/bsdconfig/usermgmt/share/user.subr +++ b/usr.sbin/bsdconfig/usermgmt/share/user.subr @@ -1,1183 +1,1183 @@ if [ ! "$_USERMGMT_USER_SUBR" ]; then _USERMGMT_USER_SUBR=1 # # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012-2014 Devin Teske +# Copyright (c) 2012-2015 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..." usermgmt/user.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/strings.subr f_include $BSDCFG_SHARE/usermgmt/group_input.subr f_include $BSDCFG_SHARE/usermgmt/user_input.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ CONFIGURATION # set some reasonable defaults if /etc/adduser.conf does not exist. [ -f /etc/adduser.conf ] && f_include /etc/adduser.conf : ${defaultclass:=""} : ${defaultshell:="/bin/sh"} : ${homeprefix:="/home"} : ${passwdtype:="yes"} : ${udotdir:="/usr/share/skel"} : ${uexpire:=""} # Default account expire time. Format is similar to upwexpire variable. : ${ugecos:="User &"} : ${upwexpire:=""} # The default password expiration time. Format of the date is either a # UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where dd is # the day, mmm is the month in either numeric or alphabetic format, and # yy[yy] is either a two or four digit year. This variable also accepts # a relative date in the form of n[mhdwoy] where n is a decimal, octal # (leading 0) or hexadecimal (leading 0x) digit followed by the number # of Minutes, Hours, Days, Weeks, Months or Years from the current date # at which the expiration time is to be set. # # uexpire and upwexpire from adduser.conf(5) differ only slightly from what # pw(8) accepts as `date' argument(s); pw(8) requires a leading `+' for the # relative date syntax (n[mhdwoy]). # case "$uexpire" in *[mhdwoy]) f_isinteger "${uexpire%[mhdwoy]}" && uexpire="+$uexpire" esac case "$upwexpire" in *[mhdwoy]) f_isinteger "${upwexpire%[mhdwoy]}" && upwexpire="+$upwexpire" esac ############################################################ FUNCTIONS # f_user_create_homedir $user # # Create home directory for $user. # f_user_create_homedir() { local funcname=f_user_create_homedir local user="$1" [ "$user" ] || return $FAILURE local user_account_expire user_class user_gecos user_gid user_home_dir local user_member_groups user_name user_password user_password_expire local user_shell user_uid # Variables created by f_input_user() below f_input_user "$user" || return $FAILURE f_dprintf "Creating home directory \`%s' for user \`%s'" \ "$user_home_dir" "$user" local _user_gid _user_home_dir _user_uid f_shell_escape "$user_gid" _user_gid f_shell_escape "$user_home_dir" _user_home_dir f_shell_escape "$user_uid" _user_uid f_eval_catch $funcname mkdir "mkdir -p '%s'" "$_user_home_dir" || return $FAILURE f_eval_catch $funcname chown "chown '%i:%i' '%s'" \ "$_user_uid" "$_user_gid" "$_user_home_dir" || return $FAILURE } # f_user_copy_dotfiles $user # # Copy `skel' dot-files from $udotdir (global inherited from /etc/adduser.conf) # to the home-directory of $user. Attempts to create the home-directory first # if it doesn't exist. # f_user_copy_dotfiles() { local funcname=f_user_copy_dotfiles local user="$1" [ "$udotdir" ] || return $FAILURE [ "$user" ] || return $FAILURE local user_account_expire user_class user_gecos user_gid user_home_dir local user_member_groups user_name user_password user_password_expire local user_shell user_uid # Variables created by f_input_user() below f_input_user "$user" || return $FAILURE f_dprintf "Copying dot-files from \`%s' to \`%s'" \ "$udotdir" "$user_home_dir" # Attempt to create the home directory if it doesn't exist [ -d "$user_home_dir" ] || f_user_create_homedir "$user" || return $FAILURE local _user_gid _user_home_dir _user_uid f_shell_escape "$user_gid" _user_gid f_shell_escape "$user_home_dir" _user_home_dir f_shell_escape "$user_uid" _user_uid local - # Localize `set' to this function set +f # Enable glob pattern-matching for paths cd "$udotdir" || return $FAILURE local _file file retval for file in dot.*; do [ -e "$file" ] || continue # no-match f_shell_escape "$file" "_file" f_eval_catch $funcname cp "cp -n '%s' '%s'" \ "$_file" "$_user_home_dir/${_file#dot}" retval=$? [ $retval -eq $SUCCESS ] || break f_eval_catch $funcname chown \ "chown -h '%i:%i' '%s'" \ "$_user_uid" "$_user_gid" \ "$_user_home_dir/${_file#dot}" retval=$? [ $retval -eq $SUCCESS ] || break done cd - return $retval } # f_user_add [$user] # # Create a login account. If both $user (as a first argument) and $VAR_USER are # unset or NULL and we are running interactively, prompt the end-user to enter # the name of a new login account and (if $VAR_NO_CONFIRM is unset or NULL) # prompt the end-user to answer some questions about the new account. Variables # that can be used to script user input: # # VAR_USER [Optional if running interactively] # The login to add. Ignored if given non-NULL first-argument. # VAR_USER_ACCOUNT_EXPIRE [Optional] # The account expiration time. Format is similar to # VAR_USER_PASSWORD_EXPIRE variable below. Default is to never # expire the account. # VAR_USER_DOTFILES_CREATE [Optional] # If non-NULL, populate the user's home directory with the # template files found in $udotdir (`/usr/share/skel' default). # VAR_USER_GECOS [Optional] # Often the full name of the account holder. Default is NULL. # VAR_USER_GID [Optional] # Numerical primary-group ID to use. If NULL or unset, the group # ID is automatically chosen. # VAR_USER_GROUPS [Optional] # Comma-separated list of additional groups to which the user is # a member of. Default is NULL (no additional groups). # VAR_USER_HOME [Optional] # The home directory to set. If NULL or unset, the home directory # is automatically calculated. # VAR_USER_HOME_CREATE [Optional] # If non-NULL, create the user's home directory if it doesn't # already exist. # VAR_USER_LOGIN_CLASS [Optional] # Login class to use when creating the login. Default is NULL. # VAR_USER_PASSWORD [Optional] # Unencrypted password to use. If unset or NULL, password # authentication for the login is disabled. # VAR_USER_PASSWORD_EXPIRE [Optional] # The password expiration time. Format of the date is either a # UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where # dd is the day, mmm is the month in either numeric or alphabetic # format, and yy[yy] is either a two or four digit year. This # variable also accepts a relative date in the form of +n[mhdwoy] # where n is a decimal, octal (leading 0) or hexadecimal (leading # 0x) digit followed by the number of Minutes, Hours, Days, # Weeks, Months or Years from the current date at which the # expiration time is to be set. Default is to never expire the # account password. # VAR_USER_SHELL [Optional] # Path to login shell to use. Default is `/bin/sh'. # VAR_USER_UID [Optional] # Numerical user ID to use. If NULL or unset, the user ID is # automatically chosen. # # Returns success if the user account was successfully created. # f_user_add() { local funcname=f_user_add local title # Calculated below local alert=f_show_msg no_confirm= f_getvar $VAR_NO_CONFIRM no_confirm [ "$no_confirm" ] && alert=f_show_info local input f_getvar 3:-\$$VAR_USER input "$1" # # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID # instead of name. Work-around is to also pass `-u UID' at the same # time (any UID will do; but `-1' is appropriate for this context). # if [ "$input" ] && f_quietly pw usershow -n "$input" -u -1; then f_show_err "$msg_login_already_used" "$input" return $FAILURE fi local user_name="$input" while f_interactive && [ ! "$user_name" ]; do f_dialog_input_name user_name "$user_name" || return $SUCCESS [ "$user_name" ] || f_show_err "$msg_please_enter_a_user_name" done if [ ! "$user_name" ]; then f_show_err "$msg_no_user_specified" return $FAILURE fi local user_account_expire user_class user_gecos user_gid user_home_dir local user_member_groups user_password user_password_expire user_shell local user_uid user_dotfiles_create= user_home_create= f_getvar $VAR_USER_ACCOUNT_EXPIRE-\$uexpire user_account_expire f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create f_getvar $VAR_USER_GECOS-\$ugecos user_gecos f_getvar $VAR_USER_GID user_gid f_getvar $VAR_USER_GROUPS user_member_groups f_getvar $VAR_USER_HOME:-\${homeprefix%/}/\$user_name \ user_home_dir f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create f_getvar $VAR_USER_LOGIN_CLASS-\$defaultclass user_class f_getvar $VAR_USER_PASSWORD user_password f_getvar $VAR_USER_PASSWORD_EXPIRE-\$upwexpire user_password_expire f_getvar $VAR_USER_SHELL-\$defaultshell user_shell f_getvar $VAR_USER_UID user_uid # Create home-dir if no script-override and does not exist f_isset $VAR_USER_HOME_CREATE || [ -d "$user_home_dir" ] || user_home_create="$msg_yes" # Copy dotfiles if home-dir creation is desired, does not yet exist, # and no script-override has been set f_isset $VAR_USER_DOTFILES_CREATE || [ "$user_home_create" != "$msg_yes" ] || [ -d "$user_home_dir" ] || user_dotfiles_create="$msg_yes" # Create home-dir if copying dotfiles but home-dir does not exist [ "$user_dotfiles_create" -a ! -d "$user_home_dir" ] && user_home_create="$msg_yes" # Set flags for meaningful NULL values if-provided local no_account_expire= no_password_expire= null_gecos= null_members= local user_password_disable= f_isset $VAR_USER_ACCOUNT_EXPIRE && [ ! "$user_account_expire" ] && no_account_expire=1 f_isset $VAR_USER_GECOS && [ ! "$user_gecos" ] && null_gecos=1 f_isset $VAR_USER_GROUPS && [ ! "$user_member_groups" ] && null_members=1 f_isset $VAR_USER_PASSWORD && [ ! "$user_password" ] && user_password_disable=1 f_isset $VAR_USER_PASSWORD_EXPIRE && [ ! "$user_password_expire" ] && no_password_expire=1 if f_interactive && [ ! "$no_confirm" ]; then f_dialog_noyes \ "$msg_use_default_values_for_all_account_details" retval=$? if [ $retval -eq $DIALOG_ESC ]; then return $SUCCESS elif [ $retval -ne $DIALOG_OK ]; then # # Ask series of questions to pre-fill the editor screen # # Defaults used in each dialog should allow the user to # simply hit ENTER to proceed, because cancelling any # single dialog will cause them to be returned to the # previous menu. # f_dialog_input_gecos user_gecos "$user_gecos" || return $FAILURE if [ "$passwdtype" = "yes" ]; then f_dialog_input_password user_password \ user_password_disable || return $FAILURE fi f_dialog_input_uid user_uid "$user_uid" || return $FAILURE f_dialog_input_gid user_gid "$user_gid" || return $FAILURE f_dialog_input_member_groups user_member_groups \ "$user_member_groups" || return $FAILURE f_dialog_input_class user_class "$user_class" || return $FAILURE f_dialog_input_expire_password user_password_expire \ "$user_password_expire" || return $FAILURE f_dialog_input_expire_account user_account_expire \ "$user_account_expire" || return $FAILURE f_dialog_input_home_dir user_home_dir \ "$user_home_dir" || return $FAILURE if [ ! -d "$user_home_dir" ]; then f_dialog_input_home_create user_home_create || return $FAILURE if [ "$user_home_create" = "$msg_yes" ]; then f_dialog_input_dotfiles_create \ user_dotfiles_create || return $FAILURE fi fi f_dialog_input_shell user_shell "$user_shell" || return $FAILURE fi fi # # Loop until the user decides to Exit, Cancel, or presses ESC # title="$msg_add $msg_user: $user_name" if f_interactive; then local mtag retval defaultitem= while :; do f_dialog_title "$title" f_dialog_menu_user_add "$defaultitem" retval=$? f_dialog_title_restore f_dialog_menutag_fetch mtag f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" defaultitem="$mtag" # Return if user either pressed ESC or chose Cancel/No [ $retval -eq $DIALOG_OK ] || return $FAILURE case "$mtag" in X) # Add/Exit local var for var in account_expire class gecos gid home_dir \ member_groups name password_expire shell uid \ ; do local _user_$var eval f_shell_escape \"\$user_$var\" _user_$var done local cmd="pw useradd -n '$_user_name'" [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'" [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'" [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'" [ "$user_account_expire" -o \ "$no_account_expire" ] && cmd="$cmd -e '$_user_account_expire'" [ "$user_class" -o "$null_class" ] && cmd="$cmd -L '$_user_class'" [ "$user_gecos" -o "$null_gecos" ] && cmd="$cmd -c '$_user_gecos'" [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'" [ "$user_member_groups" ] && cmd="$cmd -G '$_user_member_groups'" [ "$user_password_expire" -o \ "$no_password_expire" ] && cmd="$cmd -p '$_user_password_expire'" # Execute the command if [ "$user_password_disable" ]; then f_eval_catch $funcname pw '%s -h -' "$cmd" elif [ "$user_password" ]; then echo "$user_password" | f_eval_catch \ $funcname pw '%s -h 0' "$cmd" else f_eval_catch $funcname pw '%s' "$cmd" fi || continue # Create home directory if desired [ "${user_home_create:-$msg_no}" != "$msg_no" ] && f_user_create_homedir "$user_name" # Copy dotfiles if desired [ "${user_dotfiles_create:-$msg_no}" != \ "$msg_no" ] && f_user_copy_dotfiles "$user_name" break # to success ;; 1) # Login (prompt for new login name) f_dialog_input_name input "$user_name" || continue if f_quietly pw usershow -n "$input" -u -1; then f_show_err "$msg_login_already_used" "$input" continue fi user_name="$input" title="$msg_add $msg_user: $user_name" user_home_dir="${homeprefix%/}/$user_name" ;; 2) # Full Name f_dialog_input_gecos user_gecos "$user_gecos" && [ ! "$user_gecos" ] && null_gecos=1 ;; 3) # Password f_dialog_input_password \ user_password user_password_disable ;; 4) # User ID f_dialog_input_uid user_uid "$user_uid" ;; 5) # Group ID f_dialog_input_gid user_gid "$user_gid" ;; 6) # Member of Groups f_dialog_input_member_groups \ user_member_groups "$user_member_groups" && [ ! "$user_member_groups" ] && null_members=1 ;; 7) # Login Class f_dialog_input_class user_class "$user_class" && [ ! "$user_class" ] && null_class=1 ;; 8) # Password Expires On f_dialog_input_expire_password \ user_password_expire "$user_password_expire" && [ ! "$user_password_expire" ] && no_password_expire=1 ;; 9) # Account Expires On f_dialog_input_expire_account \ user_account_expire "$user_account_expire" && [ ! "$user_account_expire" ] && no_account_expire=1 ;; A) # Home Directory f_dialog_input_home_dir \ user_home_dir "$user_home_dir" ;; B) # Shell f_dialog_input_shell user_shell "$user_shell" ;; C) # Create Home Directory? if [ "${user_home_create:-$msg_no}" != "$msg_no" ] then user_home_create="$msg_no" else user_home_create="$msg_yes" fi ;; D) # Create Dotfiles? if [ "${user_dotfiles_create:-$msg_no}" != \ "$msg_no" ] then user_dotfiles_create="$msg_no" else user_dotfiles_create="$msg_yes" fi ;; esac done else local var for var in account_expire class gecos gid home_dir \ member_groups name password_expire shell uid \ ; do local _user_$var eval f_shell_escape \"\$user_$var\" _user_$var done # Form the command local cmd="pw useradd -n '$_user_name'" [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'" [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'" [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'" [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'" [ "$user_account_expire" -o "$no_account_expire" ] && cmd="$cmd -e '$_user_account_expire'" [ "$user_class" -o "$null_class" ] && cmd="$cmd -L '$_user_class'" [ "$user_gecos" -o "$null_gecos" ] && cmd="$cmd -c '$_user_gecos'" [ "$user_member_groups" -o "$null_members" ] && cmd="$cmd -G '$_user_member_groups'" [ "$user_password_expire" -o "$no_password_expire" ] && cmd="$cmd -p '$_user_password_expire'" # Execute the command local retval err if [ "$user_password_disable" ]; then f_eval_catch -k err $funcname pw '%s -h -' "$cmd" elif [ "$user_password" ]; then err=$( echo "$user_password" | f_eval_catch -de \ $funcname pw '%s -h 0' "$cmd" 2>&1 ) else f_eval_catch -k err $funcname pw '%s' "$cmd" fi retval=$? if [ $retval -ne $SUCCESS ]; then f_show_err "%s" "$err" return $retval fi # Create home directory if desired [ "${user_home_create:-$msg_no}" != "$msg_no" ] && f_user_create_homedir "$user_name" # Copy dotfiles if desired [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] && f_user_copy_dotfiles "$user_name" fi f_dialog_title "$title" $alert "$msg_login_added" f_dialog_title_restore [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1 return $SUCCESS } # f_user_delete [$user] # # Delete a user. If both $user (as a first argument) and $VAR_USER are unset or # NULL and we are running interactively, prompt the end-user to select a user # account from a list of those available. Variables that can be used to script # user input: # # VAR_USER [Optional if running interactively] # The user to delete. Ignored if given non-NULL first-argument. # # Returns success if the user account was successfully deleted. # f_user_delete() { local funcname=f_user_delete local title # Calculated below local alert=f_show_msg no_confirm= f_getvar $VAR_NO_CONFIRM no_confirm [ "$no_confirm" ] && alert=f_show_info local input f_getvar 3:-\$$VAR_USER input "$1" if f_interactive && [ ! "$input" ]; then f_dialog_menu_user_list || return $SUCCESS f_dialog_menutag_fetch input [ "$input" = "X $msg_exit" ] && return $SUCCESS elif [ ! "$input" ]; then f_show_err "$msg_no_user_specified" return $FAILURE fi local user_account_expire user_class user_gecos user_gid user_home_dir local user_member_groups user_name user_password user_password_expire local user_shell user_uid # Variables created by f_input_user() below if [ "$input" ] && ! f_input_user "$input"; then f_show_err "$msg_login_not_found" "$input" return $FAILURE fi local user_group_delete= user_home_delete= f_getvar $VAR_USER_GROUP_DELETE:-\$msg_no user_group_delete f_getvar $VAR_USER_HOME_DELETE:-\$msg_no user_home_delete # Attempt to translate user GID into a group name local user_group if user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ); then user_group="${user_group%%:*}" # Default to delete the primary group if no script-override and # exists with same name as the user (same logic used by pw(8)) f_isset $VAR_USER_GROUP_DELETE || [ "$user_group" != "$user_name" ] || user_group_delete="$msg_yes" fi # # Loop until the user decides to Exit, Cancel, or presses ESC # title="$msg_delete $msg_user: $user_name" if f_interactive; then local mtag retval defaultitem= while :; do f_dialog_title "$title" f_dialog_menu_user_delete "$user_name" "$defaultitem" retval=$? f_dialog_title_restore f_dialog_menutag_fetch mtag f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" defaultitem="$mtag" # Return if user either pressed ESC or chose Cancel/No [ $retval -eq $DIALOG_OK ] || return $FAILURE case "$mtag" in X) # Delete/Exit f_shell_escape "$user_uid" _user_uid # Save group information in case pw(8) deletes it # and we wanted to keep it (to be restored below) if [ "${user_group_delete:-$msg_no}" = "$msg_no" ] then local v vars="gid members name password" for v in $vars; do local group_$var; done f_input_group "$user_group" # Remove user-to-delete from group members # NB: Otherwise group restoration could fail local name length=0 _members= while [ $length -ne ${#group_members} ]; do name="${group_members%%,*}" [ "$name" != "$user_name" ] && _members="$_members,$name" length=${#group_members} group_members="${group_members#*,}" done group_members="${_members#,}" # Create escaped variables for f_eval_catch() for v in $vars; do local _group_$v eval f_shell_escape \ \"\$group_$v\" _group_$v done fi # Delete the user (if asked to delete home directory # display [X]dialog notification to show activity) local cmd="pw userdel -u '$_user_uid'" if [ "$user_home_delete" = "$msg_yes" -a \ "$USE_XDIALOG" ] then local err err=$( exec 9>&1 f_eval_catch -e $funcname pw \ "%s -r" "$cmd" \ >&$DIALOG_TERMINAL_PASSTHRU_FD 2>&9 | f_xdialog_info \ "$msg_deleting_home_directory" ) [ ! "$err" ] elif [ "$user_home_delete" = "$msg_yes" ]; then f_dialog_info "$msg_deleting_home_directory" f_eval_catch $funcname pw '%s -r' "$cmd" else f_eval_catch $funcname pw '%s' "$cmd" fi || continue # # pw(8) may conditionally delete the primary group, # which may not be what is desired. # # If we've been asked to delete the group and pw(8) # chose not to, delete it. Otherwise, if we're told # to NOT delete the group, we may need to restore it # since pw(8) doesn't have a flag to tell `userdel' # to not delete the group. # # NB: If primary group and user have different names # the group may not have been deleted (again, see PR # 169471 and SVN r263114 for details). # if [ "${user_group_delete:-$msg_no}" != "$msg_no" ] then f_quietly pw groupshow -g "$user_gid" && f_eval_catch $funcname pw \ "pw groupdel -g '%s'" "$_user_gid" elif ! f_quietly pw groupshow -g "$group_gid" && [ "$group_name" -a "$group_gid" ] then # Group deleted by pw(8), so restore it local cmd="pw groupadd -n '$_group_name'" cmd="$cmd -g '$_group_gid'" cmd="$cmd -M '$_group_members'" # Get the group password (pw(8) groupshow does # NOT provide this (even if running privileged) local group_password_enc group_password_enc=$( getent group | awk -F: ' !/^[[:space:]]*(#|$)/ && \ $1 == ENVIRON["group_name"] && \ $3 == ENVIRON["group_gid"] && \ $4 == ENVIRON["group_members"] \ { print $2; exit } ' ) if [ "$group_password_enc" ]; then echo "$group_password_enc" | f_eval_catch $funcname \ pw '%s -H 0' "$cmd" else f_eval_catch $funcname \ pw '%s -h -' "$cmd" fi fi break # to success ;; 1) # Login (select different login from list) f_dialog_menu_user_list "$user_name" || continue f_dialog_menutag_fetch mtag [ "$mtag" = "X $msg_exit" ] && continue if ! f_input_user "$mtag"; then f_show_err "$msg_login_not_found" "$mtag" # Attempt to fall back to previous selection f_input_user "$input" || return $FAILURE else input="$mtag" fi title="$msg_delete $msg_user: $user_name" ;; C) # Delete Primary Group? if [ "${user_group_delete:-$msg_no}" != "$msg_no" ] then user_group_delete="$msg_no" else user_group_delete="$msg_yes" fi ;; D) # Delete Home Directory? if [ "${user_home_delete:-$msg_no}" != "$msg_no" ] then user_home_delete="$msg_no" else user_home_delete="$msg_yes" fi ;; esac done else f_shell_escape "$user_uid" _user_uid # Save group information in case pw(8) deletes it # and we wanted to keep it (to be restored below) if [ "${user_group_delete:-$msg_no}" = "$msg_no" ]; then local v vars="gid members name password" for v in $vars; do local group_$v; done f_input_group "$user_group" # Remove user we're about to delete from group members # NB: Otherwise group restoration could fail local name length=0 _members= while [ $length -ne ${#group_members} ]; do name="${group_members%%,*}" [ "$name" != "$user_name" ] && _members="$_members,$name" length=${#group_members} group_members="${group_members#*,}" done group_members="${_members#,}" # Create escaped variables for later f_eval_catch() for v in $vars; do local _group_$v eval f_shell_escape \"\$group_$v\" _group_$v done fi # Delete the user (if asked to delete home directory # display [X]dialog notification to show activity) local err cmd="pw userdel -u '$_user_uid'" if [ "$user_home_delete" = "$msg_yes" -a "$USE_XDIALOG" ]; then err=$( exec 9>&1 f_eval_catch -de $funcname pw \ '%s -r' "$cmd" 2>&9 | f_xdialog_info \ "$msg_deleting_home_directory" ) [ ! "$err" ] elif [ "$user_home_delete" = "$msg_yes" ]; then f_dialog_info "$msg_deleting_home_directory" f_eval_catch -k err $funcname pw '%s -r' "$cmd" else f_eval_catch -k err $funcname pw '%s' "$cmd" fi local retval=$? if [ $retval -ne $SUCCESS ]; then f_show_err "%s" "$err" return $retval fi # # pw(8) may conditionally delete the primary group, which may # not be what is desired. # # If we've been asked to delete the group and pw(8) chose not # to, delete it. Otherwise, if we're told to NOT delete the # group, we may need to restore it since pw(8) doesn't have a # flag to tell `userdel' to not delete the group. # # NB: If primary group and user have different names the group # may not have been deleted (again, see PR 169471 and SVN # r263114 for details). # if [ "${user_group_delete:-$msg_no}" != "$msg_no" ] then f_quietly pw groupshow -g "$user_gid" && f_eval_catch $funcname pw \ "pw groupdel -g '%s'" "$_user_gid" elif ! f_quietly pw groupshow -g "$group_gid" && [ "$group_name" -a "$group_gid" ] then # Group deleted by pw(8), so restore it local cmd="pw groupadd -n '$_group_name'" cmd="$cmd -g '$_group_gid'" cmd="$cmd -M '$_group_members'" local group_password_enc group_password_enc=$( getent group | awk -F: ' !/^[[:space:]]*(#|$)/ && \ $1 == ENVIRON["group_name"] && \ $3 == ENVIRON["group_gid"] && \ $4 == ENVIRON["group_members"] \ { print $2; exit } ' ) if [ "$group_password_enc" ]; then echo "$group_password_enc" | f_eval_catch $funcname \ pw '%s -H 0' "$cmd" else f_eval_catch $funcname pw '%s -h -' "$cmd" fi fi fi f_dialog_title "$title" $alert "$msg_login_deleted" f_dialog_title_restore [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1 return $SUCCESS } # f_user_edit [$user] # # Modify a login account. If both $user (as a first argument) and $VAR_USER are # unset or NULL and we are running interactively, prompt the end-user to select # a login account from a list of those available. Variables that can be used to # script user input: # # VAR_USER [Optional if running interactively] # The login to modify. Ignored if given non-NULL first-argument. # VAR_USER_ACCOUNT_EXPIRE [Optional] # The account expiration time. Format is similar to # VAR_USER_PASSWORD_EXPIRE variable below. If unset, account # expiry is unchanged. If set but NULL, account expiration is # disabled (same as setting a value of `0'). # VAR_USER_DOTFILES_CREATE [Optional] # If non-NULL, re-populate the user's home directory with the # template files found in $udotdir (`/usr/share/skel' default). # VAR_USER_GECOS [Optional] # Often the full name of the account holder. If unset, the GECOS # field is unmodified. If set but NULL, the field is blanked. # VAR_USER_GID [Optional] # Numerical primary-group ID to set. If NULL or unset, the group # ID is unchanged. # VAR_USER_GROUPS [Optional] # Comma-separated list of additional groups to which the user is # a member of. If set but NULL, group memberships are reset (this # login will not be a member of any additional groups besides the # primary group). If unset, group membership is unmodified. # VAR_USER_HOME [Optional] # The home directory to set. If NULL or unset, the home directory # is unchanged. # VAR_USER_HOME_CREATE [Optional] # If non-NULL, create the user's home directory if it doesn't # already exist. # VAR_USER_LOGIN_CLASS [Optional] # Login class to set. If unset, the login class is unchanged. If # set but NULL, the field is blanked. # VAR_USER_PASSWORD [Optional] # Unencrypted password to set. If unset, the login password is # unmodified. If set but NULL, password authentication for the # login is disabled. # VAR_USER_PASSWORD_EXPIRE [Optional] # The password expiration time. Format of the date is either a # UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where # dd is the day, mmm is the month in either numeric or alphabetic # format, and yy[yy] is either a two or four digit year. This # variable also accepts a relative date in the form of +n[mhdwoy] # where n is a decimal, octal (leading 0) or hexadecimal (leading # 0x) digit followed by the number of Minutes, Hours, Days, # Weeks, Months or Years from the current date at which the # expiration time is to be set. If unset, password expiry is # unchanged. If set but NULL, password expiration is disabled # (same as setting a value of `0'). # VAR_USER_SHELL [Optional] # Path to login shell to set. If NULL or unset, the shell is # unchanged. # VAR_USER_UID [Optional] # Numerical user ID to set. If NULL or unset, the user ID is # unchanged. # # Returns success if the user account was successfully modified. # f_user_edit() { local funcname=f_user_edit local title # Calculated below local alert=f_show_msg no_confirm= f_getvar $VAR_NO_CONFIRM no_confirm [ "$no_confirm" ] && alert=f_show_info local input f_getvar 3:-\$$VAR_USER input "$1" # # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID # instead of name. Work-around is to also pass `-u UID' at the same # time (any UID will do; but `-1' is appropriate for this context). # if [ "$input" ] && ! f_quietly pw usershow -n "$input" -u -1; then f_show_err "$msg_login_not_found" "$input" return $FAILURE fi if f_interactive && [ ! "$input" ]; then f_dialog_menu_user_list || return $SUCCESS f_dialog_menutag_fetch input [ "$input" = "X $msg_exit" ] && return $SUCCESS elif [ ! "$input" ]; then f_show_err "$msg_no_user_specified" return $FAILURE fi local user_account_expire user_class user_gecos user_gid user_home_dir local user_member_groups user_name user_password user_password_expire local user_shell user_uid # Variables created by f_input_user() below if ! f_input_user "$input"; then f_show_err "$msg_login_not_found" "$input" return $FAILURE fi # # Override values probed by f_input_user() with desired values # f_isset $VAR_USER_GID && f_getvar $VAR_USER_GID user_gid f_isset $VAR_USER_HOME && f_getvar $VAR_USER_HOME user_home_dir f_isset $VAR_USER_SHELL && f_getvar $VAR_USER_SHELL user_shell f_isset $VAR_USER_UID && f_getvar $VAR_USER_UID user_uid local user_dotfiles_create= user_home_create= f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create local no_account_expire= if f_isset $VAR_USER_ACCOUNT_EXPIRE; then f_getvar $VAR_USER_ACCOUNT_EXPIRE user_account_expire [ "$user_account_expire" ] || no_account_expire=1 fi local null_gecos= if f_isset $VAR_USER_GECOS; then f_getvar $VAR_USER_GECOS user_gecos [ "$user_gecos" ] || null_gecos=1 fi local null_members= if f_isset $VAR_USER_GROUPS; then f_getvar $VAR_USER_GROUPS user_member_groups [ "$user_member_groups" ] || null_members=1 fi local null_class= if f_isset $VAR_USER_LOGIN_CLASS; then f_getvar $VAR_USER_LOGIN_CLASS user_class [ "$user_class" ] || null_class=1 fi local user_password_disable= if f_isset $VAR_USER_PASSWORD; then f_getvar $VAR_USER_PASSWORD user_password [ "$user_password" ] || user_password_disable=1 fi local no_password_expire= if f_isset $VAR_USER_PASSWORD_EXPIRE; then f_getvar $VAR_USER_PASSWORD_EXPIRE user_password_expire [ "$user_password_expire" ] || no_password_expire=1 fi # # Loop until the user decides to Exit, Cancel, or presses ESC # title="$msg_edit_view $msg_user: $user_name" if f_interactive; then local mtag retval defaultitem= while :; do f_dialog_title "$title" f_dialog_menu_user_edit "$defaultitem" retval=$? f_dialog_title_restore f_dialog_menutag_fetch mtag f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" defaultitem="$mtag" # Return if user either pressed ESC or chose Cancel/No [ $retval -eq $DIALOG_OK ] || return $FAILURE case "$mtag" in X) # Save/Exit local var for var in account_expire class gecos gid home_dir \ member_groups name password_expire shell uid \ ; do local _user_$var eval f_shell_escape \"\$user_$var\" _user_$var done local cmd="pw usermod -n '$_user_name'" [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'" [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'" [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'" [ "$user_account_expire" -o \ "$no_account_expire" ] && cmd="$cmd -e '$_user_account_expire'" [ "$user_class" -o "$null_class" ] && cmd="$cmd -L '$_user_class'" [ "$user_gecos" -o "$null_gecos" ] && cmd="$cmd -c '$_user_gecos'" [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'" [ "$user_member_groups" -o "$null_members" ] && cmd="$cmd -G '$_user_member_groups'" [ "$user_password_expire" -o \ "$no_password_expire" ] && cmd="$cmd -p '$_user_password_expire'" # Execute the command if [ "$user_password_disable" ]; then f_eval_catch $funcname pw '%s -h -' "$cmd" elif [ "$user_password" ]; then echo "$user_password" | f_eval_catch \ $funcname pw '%s -h 0' "$cmd" else f_eval_catch $funcname pw '%s' "$cmd" fi || continue # Create home directory if desired [ "${user_home_create:-$msg_no}" != "$msg_no" ] && f_user_create_homedir "$user_name" # Copy dotfiles if desired [ "${user_dotfiles_create:-$msg_no}" != \ "$msg_no" ] && f_user_copy_dotfiles "$user_name" break # to success ;; 1) # Login (select different login from list) f_dialog_menu_user_list "$user_name" || continue f_dialog_menutag_fetch mtag [ "$mtag" = "X $msg_exit" ] && continue if ! f_input_user "$mtag"; then f_show_err "$msg_login_not_found" "$mtag" # Attempt to fall back to previous selection f_input_user "$input" || return $FAILURE else input="$mtag" fi title="$msg_edit_view $msg_user: $user_name" ;; 2) # Full Name f_dialog_input_gecos user_gecos "$user_gecos" && [ ! "$user_gecos" ] && null_gecos=1 ;; 3) # Password f_dialog_input_password \ user_password user_password_disable ;; 4) # User ID f_dialog_input_uid user_uid "$user_uid" ;; 5) # Group ID f_dialog_input_gid user_gid "$user_gid" ;; 6) # Member of Groups f_dialog_input_member_groups \ user_member_groups "$user_member_groups" && [ ! "$user_member_groups" ] && null_members=1 ;; 7) # Login Class f_dialog_input_class user_class "$user_class" && [ ! "$user_class" ] && null_class=1 ;; 8) # Password Expires On f_dialog_input_expire_password \ user_password_expire "$user_password_expire" && [ ! "$user_password_expire" ] && no_password_expire=1 ;; 9) # Account Expires On f_dialog_input_expire_account \ user_account_expire "$user_account_expire" && [ ! "$user_account_expire" ] && no_account_expire=1 ;; A) # Home Directory f_dialog_input_home_dir \ user_home_dir "$user_home_dir" ;; B) # Shell f_dialog_input_shell user_shell "$user_shell" ;; C) # Create Home Directory? if [ "${user_home_create:-$msg_no}" != "$msg_no" ] then user_home_create="$msg_no" else user_home_create="$msg_yes" fi ;; D) # Create Dotfiles? if [ "${user_dotfiles_create:-$msg_no}" != \ "$msg_no" ] then user_dotfiles_create="$msg_no" else user_dotfiles_create="$msg_yes" fi ;; esac done else local var for var in account_expire class gecos gid home_dir \ member_groups name password_expire shell uid \ ; do local _user_$var eval f_shell_escape \"\$user_$var\" _user_$var done # Form the command local cmd="pw usermod -n '$_user_name'" [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'" [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'" [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'" [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'" [ "$user_account_expire" -o "$no_account_expire" ] && cmd="$cmd -e '$_user_account_expire'" [ "$user_class" -o "$null_class" ] && cmd="$cmd -L '$_user_class'" [ "$user_gecos" -o "$null_gecos" ] && cmd="$cmd -c '$_user_gecos'" [ "$user_member_groups" -o "$null_members" ] && cmd="$cmd -G '$_user_member_groups'" [ "$user_password_expire" -o "$no_password_expire" ] && cmd="$cmd -p '$_user_password_expire'" # Execute the command local retval err if [ "$user_password_disable" ]; then f_eval_catch -k err $funcname pw '%s -h -' "$cmd" elif [ "$user_password" ]; then err=$( echo "$user_password" | f_eval_catch -de \ $funcname pw '%s -h 0' "$cmd" 2>&1 ) else f_eval_catch -k err $funcname pw '%s' "$cmd" fi retval=$? if [ $retval -ne $SUCCESS ]; then f_show_err "%s" "$err" return $retval fi # Create home directory if desired [ "${user_home_create:-$msg_no}" != "$msg_no" ] && f_user_create_homedir "$user_name" # Copy dotfiles if desired [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] && f_user_copy_dotfiles "$user_name" fi f_dialog_title "$title" $alert "$msg_login_updated" f_dialog_title_restore [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1 return $SUCCESS } ############################################################ MAIN f_dprintf "%s: Successfully loaded." usermgmt/user.subr fi # ! $_USERMGMT_USER_SUBR