if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1 # # Copyright (c) 2012 Ron McDowell # Copyright (c) 2012 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_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/strings.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" f_include_lang $BSDCFG_LIBE/include/messages.subr f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ CONFIGURATION # # Default location of shells(5) # : ${ETC_SHELLS:=/etc/shells} ############################################################ FUNCTIONS # f_get_member_groups $user # # Get a list of additional groups $user is a member of in group(5). # f_get_member_groups() { echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" ) } # f_input_user $user # # Given $user name or id, create the environment variables pw_name, pw_uid, # pw_gid, pw_class, pw_password_expire, pw_account_expire, pw_gecos, # pw_home_dir, pw_shell, and pw_member_groups (and pw_password is reset to # NULL). # f_input_user() { local user="$1" eval $( pw usershow "$user" | awk -F: ' { printf "pw_name='\'%s\''\n", $1 printf "pw_password=\n" printf "pw_uid='\'%s\''\n", $3 printf "pw_gid='\'%s\''\n", $4 printf "pw_class='\'%s\''\n", $5 printf "pw_password_expire='\'%s\''\n", $6 printf "pw_account_expire='\'%s\''\n", $7 printf "pw_gecos='\'%s\''\n", $8 printf "pw_home_dir='\'%s\''\n", $9 printf "pw_shell='\'%s\''\n", $10 }' ) pw_member_groups=$( f_get_member_groups "$user" ) } # f_dialog_menu_user_list # # Allows the user to select a login from a list. # f_dialog_menu_user_list() { local menu_list size local hline="$hline_alnum_punc_tab_enter" menu_list=" 'X $msg_exit' '' " # END-QUOTE # Add users from passwd(5) menu_list="$menu_list $( pw usershow -a | awk -F: ' !/^[[:space:]]*(#|$)/ { printf "'\'%s\'\ \'%s\''\n", $1, $8 }' )" size=$( eval f_dialog_menu_size \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\" \ \"\$hline\" \ $menu_list ) local dialog_menu dialog_menu=$( eval $DIALOG \ --clear --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --menu \"\" $size $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? setvar DIALOG_MENU_$$ "$dialog_menu" return $retval } # f_dialog_input_member_groups [$member_groups] # # Allows the user to edit group memberships for a given user. If the user does # not cancel or press ESC, the $pw_member_groups variable will hold the newly- # configured value upon return. # f_dialog_input_member_groups() { local msg="$( printf "$msg_member_of_groups" )" local hline="$hline_alnum_tab_enter" # # Loop until the user provides taint-free/valid input # local size retval all_groups checklist_groups="" _member_groups="$1" all_groups=$( pw groupshow -a | awk -F: ' !/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' ) for grp in $all_groups; do checklist_groups="$checklist_groups $grp $grp" if echo "$_member_groups" | grep -q "\<$grp\>"; then checklist_groups="$checklist_groups on" else checklist_groups="$checklist_groups off" fi done while :; do size=$( eval f_dialog_radiolist_size \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\" \ \"\$hline\" \ $checklist_groups ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --separate-output \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --checklist \"\$msg\" $size \ $checklist_groups \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _member_groups=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval # # Validate each of the groups the user has entered # local group all_groups_valid=1 for group in $_member_groups; do if ! f_quietly pw groupshow -n "$group"; then f_show_msg "$msg_group_not_found" "$group" all_groups_valid= break fi done [ "$all_groups_valid" ] || continue pw_member_groups="$_member_groups" break done save_flag=1 local debug="pw_member_groups:" f_dprintf "$debug [$cur_pw_member_groups]->[$pw_member_groups]" return $SUCCESS } # f_dialog_input_name [$name] # # Allows the user to enter a new username for a given user. If the user does # not cancel or press ESC, the $pw_name variable will hold the newly-configured # value upon return. # # If $cur_pw_name is defined, the user can enter that and by-pass error- # checking (allowing the user to "revert" to an old value without, for example, # being told that the username already exists). # f_dialog_input_name() { local msg="$( printf "$msg_login" )" local hline="$hline_alnum_tab_enter" # # Loop until the user provides taint-free/valid input # local size retval _name="$1" _input="$1" while :; do size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval # Check for no-change [ "$_input" = "$_name" ] && return $SUCCESS # Check for reversion if [ "$_input" = "$cur_pw_name" ]; then pw_name="$cur_pw_name" return $SUCCESS fi # Check for NULL entry if [ ! "$_input" ]; then f_show_msg "$msg_login_is_empty" continue fi # Check for invalid entry if ! echo "$_input" | grep -q "^[[:alpha:]]"; then f_show_msg "$msg_login_must_start_with_letter" continue fi # Check for duplicate entry if f_quietly pw usershow -n "$_input"; then f_show_msg "$msg_login_already_used" "$_input" continue fi pw_name="$_input" break done save_flag=1 f_dprintf "pw_name: [$cur_pw_name]->[$pw_name]" return $SUCCESS } # f_dialog_input_password # # Prompt the user to enter a password (twice). # f_dialog_input_password() { local hline="$hline_alnum_punc_tab_enter" local msg size rmsg rsize msg=$( printf "$msg_password" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "" \ "$hline" ) rmsg=$( printf "$msg_reenter_password" ) rsize=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$rmsg" \ "" \ "$hline" ) # # Loop until the user provides taint-free/valid input # local retval _password1 _password2 while :; do local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --insecure \ --passwordbox \"\$msg\" $size \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _password1=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --insecure \ --passwordbox \"\$rmsg\" $rsize \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _password2=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval # Check for password mismatch if [ "$_password1" != "$_password2" ]; then f_show_msg "$msg_passwords_do_not_match" continue fi # Check for NULL entry if [ ! "$_password1" ]; then f_dialog_yesno \ "$msg_disable_password_auth_for_account" || continue pw_password_disable=1 else pw_password_disable= fi pw_password="$_password1" break done save_flag=1 f_dprintf "pw_password: [$cur_pw_password]->[$pw_password]" return $SUCCESS } # f_dialog_input_gecos [$gecos] # # Allow the user to enter new GECOS information for a given user. This # information is commonly used to store the ``Full Name'' of the user. If the # user does not cancel or press ESC, the $pw_gecos variable will hold the # newly-configured value upon return. # f_dialog_input_gecos() { local msg size retval _input="$1" local hline="$hline_alnum_punc_tab_enter" msg=$( printf "$msg_full_name" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_gecos="$_input" save_flag=1 f_dprintf "pw_gecos: [$cur_pw_gecos]->[$pw_gecos]" return $SUCCESS } # f_dialog_input_uid [$uid] # # Allow the user to enter a new UID for a given user. If the user does not # cancel or press ESC, the $pw_uid variable will hold the newly-configured # value upon return. # f_dialog_input_uid() { local msg size retval _input="$1" local hline="$hline_num_tab_enter" msg=$( printf "$msg_user_id_leave_empty_for_default" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_uid="$_input" save_flag=1 f_dprintf "pw_uid: [$cur_pw_uid]->[$pw_uid]" return $SUCCESS } # f_dialog_input_gid [$gid] # # Allow the user to enter a new primary GID for a given user. If the user does # not cancel or press ESC, the $pw_gid variable will hold the newly-configured # value upon return. # f_dialog_input_gid() { local msg size retval _input="$1" local hline="$hline_num_tab_enter" msg=$( printf "$msg_group_id_leave_empty_for_default" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_gid="$_input" save_flag=1 f_dprintf "pw_gid: [$cur_pw_gid]->[$pw_gid]" return $SUCCESS } # f_dialog_input_class [$class] # # Allow the user to enter a new login class for a given user. If the user does # not cancel or press ESC, the $pw_class variable will hold the newly- # configured value upon return. # f_dialog_input_class() { local msg size retval _input="$1" local hline="$hline_alnum_tab_enter" msg=$( printf "$msg_login_class" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_class="$_input" save_flag=1 f_dprintf "pw_class: [$cur_pw_class]->[$pw_class]" return $SUCCESS } # f_dialog_input_change [$seconds] # # Allow the user to enter a date/time (in number-of-seconds since the `epoch') # for when a given user's password must be changed. If the user does not cancel # or press ESC, the $pw_password_expire variable will hold the newly- # configured value upon return. # f_dialog_input_change() { local calendar_size timebox_size local msg menu_size size retval _input="$1" local hline="$hline_num_arrows_tab_enter" local menu_list=" '1' '$msg_password_does_not_expire' '2' '$msg_edit_date_time_with_a_calendar' '3' '$msg_enter_number_of_days_into_the_future' '4' '$msg_enter_value_manually' " # END-QUOTE # # Loop until the user provides taint-free/cancellation-free input # while :; do msg="$msg_password_expires_on" menu_size=$( eval f_dialog_menu_size \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$msg\" \ \"\$hline\" \ $menu_list ) local dialog_menu dialog_menu=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --menu \"\$msg\" $menu_size \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_MENU_$$ "$dialog_menu" date_type=$( f_dialog_menutag ) f_dprintf "retval=$retval date_type=[$date_type]" # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval case "$date_type" in 1) # Password does not expire _input="" break ;; 2) # Edit date/time with a calendar local _input_date _input_time ret_date ret_time local secs="$_input" { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= _input_date=$( date -j -f "%s" -- "$secs" \ "+%d %m %Y" 2> /dev/null ) calendar_size=$( f_dialog_calendar_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --calendar \"\$msg\" $calendar_size \ $_input_date \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_date=$( f_dialog_inputstr ) f_dprintf "retval=$retval ret_date=[$ret_date]" # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input_time= [ "$secs" ] && _input_time=$( date -j \ -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) timebox_size=$( f_dialog_timebox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --timebox \"\$msg\" $timebox_size \ $_input_time \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_time=$( f_dialog_inputstr ) f_dprintf "retval=$retval ret_time=[$ret_time]" # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input=$( date \ -j -f "%d/%m/%Y %T" \ -- "$ret_date $ret_time" \ +%s 2> /dev/null ) f_dprintf "_input=[$_input]" break ;; 3) # Enter number of days into the future local ret_days seconds="$( date +%s )" f_isinteger "$_input" || _input=0 [ $_input -gt 0 -a $_input -gt $seconds ] && ret_days=$(( ( $_input - $seconds ) / 86400 )) f_isinteger "$ret_days" && ret_days=$(( $ret_days + 1 )) msg="$msg_password_expires_in_how_many_days" size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$ret_days" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$ret_days\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_days=$( f_dialog_inputstr ) # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue # Taint-check the user's input if ! f_isinteger "$ret_days"; then f_show_msg "$msg_invalid_number_of_days" continue fi f_dprintf "ret_days=[$ret_days]" case "$ret_days" in [-+]*) _input=$( date -v${ret_days}d +%s );; 0) _input=$( date +%s );; *) _input=$( date -v+${ret_days}d +%s );; esac f_dprintf "_input=[$_input]" break ;; 4) # Enter value manually local ret_secs msg=$( printf "$msg_number_of_seconds_since_epoch" \ "$( date -r 1 "+%c %Z" )" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_secs=$( f_dialog_inputstr ) # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input="$ret_secs" # Taint-check the user's input if ! f_isinteger "${_input:-0}"; then f_show_msg "$msg_invalid_number_of_seconds" continue fi f_dprintf "_input=[$_input]" break ;; esac done # Loop forever pw_password_expire="$_input" save_flag=1 local debug=pw_password_expire f_dprintf "$debug: [$cur_pw_password_expire]->[$pw_password_expire]" return $SUCCESS } # f_dialog_input_expire [$seconds] # # Allow the user to enter a date/time (in number-of-seconds since the `epoch') # for when a given user's account should become expired. If the user does not # cancel or press ESC, the $pw_account_expire variable will hold the newly- # configured value upon return. # f_dialog_input_expire() { local calendar_size timebox_size local msg menu_size size retval _input="$1" local hline="$hline_num_arrows_tab_enter" local menu_list=" '1' '$msg_account_does_not_expire' '2' '$msg_edit_date_time_with_a_calendar' '3' '$msg_enter_number_of_days_into_the_future' '4' '$msg_enter_value_manually' " # END-QUOTE # # Loop until the user provides taint-free/cancellation-free input # while :; do msg="$msg_account_expires_on" menu_size=$( eval f_dialog_menu_size \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$msg\" \ \"\$hline\" \ $menu_list ) local dialog_menu dialog_menu=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --menu \"\$msg\" $menu_size \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_MENU_$$ "$dialog_menu" date_type=$( f_dialog_menutag ) f_dprintf "retval=$retval date_type=[$date_type]" # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval case "$date_type" in 1) # Account does not expire _input="" break ;; 2) # Edit date/time with a calendar local _input_date _input_time ret_date ret_time local secs="$_input" { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= _input_date=$( date -j -f "%s" -- "$secs" \ "+%d %m %Y" 2> /dev/null ) calendar_size=$( f_dialog_calendar_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --calendar \"\$msg\" $calendar_size \ $_input_date \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_date=$( f_dialog_inputstr ) f_dprintf "retval=$retval ret_date=[$ret_date]" # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input_time= [ "$secs" ] && _input_time=$( date -j \ -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) timebox_size=$( f_dialog_timebox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$hline" ) dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --timebox \"\$msg\" $timebox_size \ $_input_time \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_time=$( f_dialog_inputstr ) f_dprintf "retval=$retval ret_time=[$ret_time]" # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input=$( date \ -j -f "%d/%m/%Y %T" \ -- "$ret_date $ret_time" \ +%s 2> /dev/null ) f_dprintf "_input=[$_input]" break ;; 3) # Enter number of days into the future local ret_days seconds="$( date +%s )" f_isinteger "$_input" || _input=0 [ $_input -gt 0 -a $_input -gt $seconds ] && ret_days=$(( ( $_input - $seconds ) / 86400 )) f_isinteger "$ret_days" && ret_days=$(( $ret_days + 1 )) msg="$msg_account_expires_in_how_many_days" size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$ret_days" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$ret_days\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_days=$( f_dialog_inputstr ) # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue # Taint-check the user's input if ! f_isinteger "$ret_days"; then f_show_msg "$msg_invalid_number_of_days" continue fi f_dprintf "ret_days=[$ret_days]" case "$ret_days" in [-+]*) _input=$( date -v${ret_days}d +%s );; 0) _input=$( date +%s );; *) _input=$( date -v+${ret_days}d +%s );; esac f_dprintf "_input=[$_input]" break ;; 4) # Enter value manually local ret_secs msg=$( printf "$msg_number_of_seconds_since_epoch" \ "$( date -r 1 "+%c %Z" )" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" ret_secs=$( f_dialog_inputstr ) # Return to menu if either ESC or Cancel/No [ $retval -eq $SUCCESS ] || continue _input="$ret_secs" # Taint-check the user's input if ! f_isinteger "${_input:-0}"; then f_show_msg "$msg_invalid_number_of_seconds" continue fi f_dprintf "_input=[$_input]" break ;; esac done # Loop forever pw_account_expire="$_input" save_flag=1 local debug=pw_account_expire f_dprintf "$debug: [$cur_pw_account_expire]->[$pw_account_expire]" return $SUCCESS } # f_dialog_input_home_dir [$home_dir] # # Allow the user to enter a new home directory for a given user. If the user # does not cancel or press ESC, the $pw_home_dir variable will hold the newly- # configured value upon return. # f_dialog_input_home_dir() { local msg size retval _input="$1" local hline="$hline_alnum_punc_tab_enter" msg=$( printf "$msg_home_directory" ) size=$( f_dialog_inputbox_size \ "$DIALOG_TITLE" \ "$DIALOG_BACKTITLE" \ "$msg" \ "$_input" \ "$hline" ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --inputbox \"\$msg\" $size \ \"\$_input\" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_home_dir="$_input" save_flag=1 f_dprintf "pw_home_dir: [$cur_pw_home_dir]->[$pw_home_dir]" return $SUCCESS } # f_dialog_input_home_create # # Prompt the user to confirm creation of a given user's home directory. If the # user does not cancel (by choosing "No") or press ESC, the $pw_home_create # variable will hold $msg_yes upon return, otherwise $msg_no. Use these return # variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. # f_dialog_input_home_create() { local retval f_dialog_yesno "$msg_create_home_directory" retval=$? if [ $retval -eq $SUCCESS ]; then pw_home_create="$msg_yes" else pw_home_create="$msg_no" fi save_flag=1 f_dprintf "pw_home_create: [$cur_pw_home_create]->[$pw_home_create]" [ $retval -ne 255 ] # return failure if user pressed ESC } # f_dialog_input_group_delete # # Prompt the user to confirm deletion of a given user's primary group. If the # user does not cancel (by choosing "No") or press ESC, the $pw_group_delete # variable will hold $msg_yes upon return, otherwise $msg_no. Use these return # variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. # f_dialog_input_group_delete() { local retval if f_isinteger "$pw_gid"; then if [ $pw_gid -lt 1000 ]; then f_dialog_noyes "$msg_delete_primary_group" else f_dialog_yesno "$msg_delete_primary_group" fi elif [ "$pw_gid" ]; then local gid=0 gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' ) if f_isinteger "$gid" && [ $gid -lt 1000 ]; then f_dialog_noyes "$msg_delete_primary_group" else f_dialog_yesno "$msg_delete_primary_group" fi else f_dialog_yesno "$msg_delete_primary_group" fi retval=$? if [ $retval -eq $SUCCESS ]; then pw_group_delete="$msg_yes" else pw_group_delete="$msg_no" fi save_flag=1 f_dprintf "pw_group_delete: [$cur_pw_group_delete]->[$pw_group_delete]" [ $retval -ne 255 ] # return failure if user pressed ESC } # f_dialog_input_home_delete # # Prompt the user to confirm deletion of a given user's home directory. If the # user does not cancel (by choosing "No") or press ESC, the $pw_home_delete # variable will hold $msg_yes upon return, otherwise $msg_no. Use these return # variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. # f_dialog_input_home_delete() { local retval f_dialog_yesno "$msg_delete_home_directory" retval=$? if [ $retval -eq $SUCCESS ]; then pw_home_delete="$msg_yes" else pw_home_delete="$msg_no" fi save_flag=1 f_dprintf "pw_home_delete: [$cur_pw_home_delete]->[$pw_home_delete]" [ $retval -ne 255 ] # return failure if user pressed ESC } # f_dialog_input_dotfiles_create # # Prompt the user to confirm population of a given user's home directory with # sample dotfiles. If the user does not cancel (by choosing "No") or press ESC, # the $pw_dotfiles_create variable will hold $msg_yes upon return, otherwise # $msg_no. Use these return variables ($msg_yes and $msg_no) for comparison to # be i18n-compatible. # f_dialog_input_dotfiles_create() { local retval f_dialog_yesno "$msg_create_dotfiles" retval=$? if [ $retval -eq $SUCCESS ]; then pw_dotfiles_create="$msg_yes" else pw_dotfiles_create="$msg_no" fi save_flag=1 local debug="pw_dotfiles_create:" f_dprintf "$debug: [$cur_pw_dotfiles_create]->[$pw_dotfiles_create]" [ $retval -ne 255 ] # return failure if user pressed ESC } # f_dialog_input_shell [$shell] # # Allow the user to select a new login shell for a given user. If the user does # not cancel or press ESC, the $pw_home_dir variable will hold the newly- # configured value upon return. # # f_dialog_input_shell() { local size retval shells shell_list _input="$1" local hline="$hline_arrows_space_tab_enter" local prompt="$msg_select_login_shell" shells=$( awk '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" ) shell_list=$( for shell in $shells; do if [ "$shell" = "$_input" ]; then echo "'$shell' '' 'on'" else echo "'$shell' '' 'off'" fi done ) size=$( eval f_dialog_radiolist_size \ \"\$DIALOG_TITLE\" \ \"\$DIALOG_BACKTITLE\" \ \"\$prompt\" \ \"\$hline\" \ $shell_list ) local dialog_inputbox dialog_inputbox=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --radiolist \"\$prompt\" $size \ $shell_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) retval=$? setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" _input=$( f_dialog_inputstr ) # Return if user has either pressed ESC or chosen Cancel/No [ $retval -eq $SUCCESS ] || return $retval pw_shell="$_input" save_flag=1 f_dprintf "pw_shell: [$cur_pw_shell]->[$pw_shell]" return $SUCCESS } fi # ! $_USERMGMT_USER_INPUT_SUBR