1if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1 2# 3# Copyright (c) 2012 Ron McDowell 4# Copyright (c) 2012-2013 Devin Teske 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28# $FreeBSD$ 29# 30############################################################ INCLUDES 31 32BSDCFG_SHARE="/usr/share/bsdconfig" 33. $BSDCFG_SHARE/common.subr || exit 1 34f_dprintf "%s: loading includes..." usermgmt/user_input.subr 35f_include $BSDCFG_SHARE/dialog.subr 36f_include $BSDCFG_SHARE/strings.subr 37 38BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" 39f_include_lang $BSDCFG_LIBE/include/messages.subr 40f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr 41 42############################################################ CONFIGURATION 43 44# 45# Default location of shells(5) 46# 47: ${ETC_SHELLS:=/etc/shells} 48 49############################################################ FUNCTIONS 50 51# f_get_member_groups $user 52# 53# Get a list of additional groups $user is a member of in group(5). 54# 55f_get_member_groups() 56{ 57 echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" ) 58} 59 60# f_input_user $user 61# 62# Given $user name or id, create the environment variables pw_name, pw_uid, 63# pw_gid, pw_class, pw_password_expire, pw_account_expire, pw_gecos, 64# pw_home_dir, pw_shell, and pw_member_groups (and pw_password is reset to 65# NULL). 66# 67f_input_user() 68{ 69 local user="$1" 70 eval $( pw usershow "$user" | awk -F: ' 71 { 72 printf "pw_name='\'%s\''\n", $1 73 printf "pw_password=\n" 74 printf "pw_uid='\'%s\''\n", $3 75 printf "pw_gid='\'%s\''\n", $4 76 printf "pw_class='\'%s\''\n", $5 77 printf "pw_password_expire='\'%s\''\n", $6 78 printf "pw_account_expire='\'%s\''\n", $7 79 printf "pw_gecos='\'%s\''\n", $8 80 printf "pw_home_dir='\'%s\''\n", $9 81 printf "pw_shell='\'%s\''\n", $10 82 }' ) 83 pw_member_groups=$( f_get_member_groups "$user" ) 84} 85 86# f_dialog_menu_user_list [$default] 87# 88# Allows the user to select a login from a list. Optionally, if present and 89# non-NULL, initially highlight $default user. 90# 91f_dialog_menu_user_list() 92{ 93 local defaultitem="$1" 94 local menu_list size 95 local hline="$hline_alnum_punc_tab_enter" 96 97 menu_list=" 98 'X $msg_exit' '' 99 " # END-QUOTE 100 101 # Add users from passwd(5) 102 menu_list="$menu_list $( pw usershow -a | awk -F: ' 103 !/^[[:space:]]*(#|$)/ { 104 printf "'\'%s\'\ \'%s\''\n", $1, $8 105 }' 106 )" 107 108 size=$( eval f_dialog_menu_size \ 109 \"\$DIALOG_TITLE\" \ 110 \"\$DIALOG_BACKTITLE\" \ 111 \"\" \ 112 \"\$hline\" \ 113 $menu_list ) 114 115 local dialog_menu 116 dialog_menu=$( eval $DIALOG \ 117 --title \"\$DIALOG_TITLE\" \ 118 --backtitle \"\$DIALOG_BACKTITLE\" \ 119 --hline \"\$hline\" \ 120 --ok-label \"\$msg_ok\" \ 121 --cancel-label \"\$msg_cancel\" \ 122 --default-item \"\$defaultitem\" \ 123 --menu \"\" $size $menu_list \ 124 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 125 ) 126 local retval=$? 127 setvar DIALOG_MENU_$$ "$dialog_menu" 128 return $retval 129} 130 131# f_dialog_input_member_groups [$member_groups] 132# 133# Allows the user to edit group memberships for a given user. If the user does 134# not cancel or press ESC, the $pw_member_groups variable will hold the newly- 135# configured value upon return. 136# 137f_dialog_input_member_groups() 138{ 139 local msg="$( printf "$msg_member_of_groups" )" 140 local hline="$hline_alnum_space_tab_enter" 141 142 # 143 # Loop until the user provides taint-free/valid input 144 # 145 local size retval all_groups checklist_groups="" _member_groups="$1" 146 all_groups=$( pw groupshow -a | awk -F: ' 147 !/^[[:space:]]*(#|$)/ { 148 printf "%s\n", $1 149 }' 150 ) 151 for grp in $all_groups; do 152 checklist_groups="$checklist_groups $grp $grp" 153 if echo "$_member_groups" | grep -q "\<$grp\>"; then 154 checklist_groups="$checklist_groups on" 155 else 156 checklist_groups="$checklist_groups off" 157 fi 158 done 159 160 while :; do 161 size=$( eval f_dialog_radiolist_size \ 162 \"\$DIALOG_TITLE\" \ 163 \"\$DIALOG_BACKTITLE\" \ 164 \"\" \ 165 \"\$hline\" \ 166 $checklist_groups ) 167 local dialog_inputbox 168 dialog_inputbox=$( eval $DIALOG \ 169 --title \"\$DIALOG_TITLE\" \ 170 --backtitle \"\$DIALOG_BACKTITLE\" \ 171 --separate-output \ 172 --hline \"\$hline\" \ 173 --ok-label \"\$msg_ok\" \ 174 --cancel-label \"\$msg_cancel\" \ 175 --checklist \"\$msg\" $size \ 176 $checklist_groups \ 177 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 178 ) 179 180 retval=$? 181 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 182 _member_groups=$( f_dialog_inputstr ) 183 184 # Return if user has either pressed ESC or chosen Cancel/No 185 [ $retval -eq $SUCCESS ] || return $retval 186 187 # 188 # Validate each of the groups the user has entered 189 # 190 local group all_groups_valid=1 191 for group in $_member_groups; do 192 if ! f_quietly pw groupshow -n "$group"; then 193 f_show_msg "$msg_group_not_found" "$group" 194 all_groups_valid= 195 break 196 fi 197 done 198 [ "$all_groups_valid" ] || continue 199 200 pw_member_groups="$_member_groups" 201 break 202 done 203 save_flag=1 204 205 f_dprintf "pw_member_groups: [%s]->[%s]" \ 206 "$cur_pw_member_groups" "$pw_member_groups" 207 208 return $SUCCESS 209} 210 211# f_dialog_input_name [$name] 212# 213# Allows the user to enter a new username for a given user. If the user does 214# not cancel or press ESC, the $pw_name variable will hold the newly-configured 215# value upon return. 216# 217# If $cur_pw_name is defined, the user can enter that and by-pass error- 218# checking (allowing the user to "revert" to an old value without, for example, 219# being told that the username already exists). 220# 221f_dialog_input_name() 222{ 223 # 224 # Loop until the user provides taint-free/valid input 225 # 226 local _name="$1" _input="$1" 227 while :; do 228 229 # Return if user has either pressed ESC or chosen Cancel/No 230 _input=$( f_dialog_input "$msg_login" "$_input" \ 231 "$hline_alnum_tab_enter" 232 ) || return 233 234 # Check for no-change 235 [ "$_input" = "$_name" ] && return $SUCCESS 236 237 # Check for reversion 238 if [ "$_input" = "$cur_pw_name" ]; then 239 pw_name="$cur_pw_name" 240 return $SUCCESS 241 fi 242 243 # Check for NULL entry 244 if [ ! "$_input" ]; then 245 f_dialog_msgbox "$msg_login_is_empty" 246 continue 247 fi 248 249 # Check for invalid entry 250 if ! echo "$_input" | grep -q "^[[:alpha:]]"; then 251 f_dialog_msgbox "$msg_login_must_start_with_letter" 252 continue 253 fi 254 255 # Check for duplicate entry 256 if f_quietly pw usershow -n "$_input"; then 257 f_show_msg "$msg_login_already_used" "$_input" 258 continue 259 fi 260 261 pw_name="$_input" 262 break 263 done 264 save_flag=1 265 266 f_dprintf "pw_name: [%s]->[%s]" "$cur_pw_name" "$pw_name" 267 268 return $SUCCESS 269} 270 271# f_dialog_input_password 272# 273# Prompt the user to enter a password (twice). 274# 275f_dialog_input_password() 276{ 277 local hline="$hline_alnum_punc_tab_enter" 278 local msg size rmsg rsize 279 280 msg=$( printf "$msg_password" ) 281 size=$( f_dialog_inputbox_size \ 282 "$DIALOG_TITLE" \ 283 "$DIALOG_BACKTITLE" \ 284 "$msg" \ 285 "" \ 286 "$hline" ) 287 288 rmsg=$( printf "$msg_reenter_password" ) 289 rsize=$( f_dialog_inputbox_size \ 290 "$DIALOG_TITLE" \ 291 "$DIALOG_BACKTITLE" \ 292 "$rmsg" \ 293 "" \ 294 "$hline" ) 295 296 # 297 # Loop until the user provides taint-free/valid input 298 # 299 local retval _password1 _password2 300 while :; do 301 local dialog_inputbox 302 dialog_inputbox=$( eval $DIALOG \ 303 --title \"\$DIALOG_TITLE\" \ 304 --backtitle \"\$DIALOG_BACKTITLE\" \ 305 --hline \"\$hline\" \ 306 --ok-label \"\$msg_ok\" \ 307 --cancel-label \"\$msg_cancel\" \ 308 --insecure \ 309 --passwordbox \"\$msg\" $size \ 310 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 311 ) 312 313 retval=$? 314 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 315 _password1=$( f_dialog_inputstr ) 316 317 # Return if user has either pressed ESC or chosen Cancel/No 318 [ $retval -eq $SUCCESS ] || return $retval 319 320 dialog_inputbox=$( eval $DIALOG \ 321 --title \"\$DIALOG_TITLE\" \ 322 --backtitle \"\$DIALOG_BACKTITLE\" \ 323 --hline \"\$hline\" \ 324 --ok-label \"\$msg_ok\" \ 325 --cancel-label \"\$msg_cancel\" \ 326 --insecure \ 327 --passwordbox \"\$rmsg\" $rsize \ 328 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 329 ) 330 331 retval=$? 332 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 333 _password2=$( f_dialog_inputstr ) 334 335 # Return if user has either pressed ESC or chosen Cancel/No 336 [ $retval -eq $SUCCESS ] || return $retval 337 338 # Check for password mismatch 339 if [ "$_password1" != "$_password2" ]; then 340 f_dialog_msgbox "$msg_passwords_do_not_match" 341 continue 342 fi 343 344 # Check for NULL entry 345 if [ ! "$_password1" ]; then 346 f_dialog_yesno \ 347 "$msg_disable_password_auth_for_account" || 348 continue 349 pw_password_disable=1 350 else 351 pw_password_disable= 352 fi 353 354 pw_password="$_password1" 355 break 356 done 357 save_flag=1 358 359 f_dprintf "pw_password: [%s]->[%s]" "$cur_pw_password" "$pw_password" 360 361 return $SUCCESS 362} 363 364# f_dialog_input_gecos [$gecos] 365# 366# Allow the user to enter new GECOS information for a given user. This 367# information is commonly used to store the ``Full Name'' of the user. If the 368# user does not cancel or press ESC, the $pw_gecos variable will hold the 369# newly-configured value upon return. 370# 371f_dialog_input_gecos() 372{ 373 local _input="$1" 374 375 # Return if user has either pressed ESC or chosen Cancel/No 376 _input=$( f_dialog_input "$msg_full_name" "$_input" \ 377 "$hline_alnum_punc_tab_enter" 378 ) || return 379 380 pw_gecos="$_input" 381 save_flag=1 382 383 f_dprintf "pw_gecos: [%s]->[%s]" "$cur_pw_gecos" "$pw_gecos" 384 385 return $SUCCESS 386} 387 388# f_dialog_input_uid [$uid] 389# 390# Allow the user to enter a new UID for a given user. If the user does not 391# cancel or press ESC, the $pw_uid variable will hold the newly-configured 392# value upon return. 393# 394f_dialog_input_uid() 395{ 396 local _input="$1" 397 398 # Return if user has either pressed ESC or chosen Cancel/No 399 _input=$( f_dialog_input "$msg_user_id_leave_empty_for_default" \ 400 "$_input" "$hline_num_tab_enter" 401 ) || return 402 403 pw_uid="$_input" 404 save_flag=1 405 406 f_dprintf "pw_uid: [%s]->[%s]" "$cur_pw_uid" "$pw_uid" 407 408 return $SUCCESS 409} 410 411# f_dialog_input_gid [$gid] 412# 413# Allow the user to enter a new primary GID for a given user. If the user does 414# not cancel or press ESC, the $pw_gid variable will hold the newly-configured 415# value upon return. 416# 417f_dialog_input_gid() 418{ 419 local _input="$1" 420 421 # Return if user has either pressed ESC or chosen Cancel/No 422 _input=$( f_dialog_input "$msg_group_id_leave_empty_for_default" \ 423 "$_input" "$hline_num_tab_enter" 424 ) || return 425 426 pw_gid="$_input" 427 save_flag=1 428 429 f_dprintf "pw_gid: [%s]->[%s]" "$cur_pw_gid" "$pw_gid" 430 431 return $SUCCESS 432} 433 434# f_dialog_input_class [$class] 435# 436# Allow the user to enter a new login class for a given user. If the user does 437# not cancel or press ESC, the $pw_class variable will hold the newly- 438# configured value upon return. 439# 440f_dialog_input_class() 441{ 442 local _input="$1" 443 444 # Return if user has either pressed ESC or chosen Cancel/No 445 _input=$( f_dialog_input "$msg_login_class" "$_input" \ 446 "$hline_alnum_tab_enter" 447 ) || return 448 449 pw_class="$_input" 450 save_flag=1 451 452 f_dprintf "pw_class: [%s]->[%s]" "$cur_pw_class" "$pw_class" 453 454 return $SUCCESS 455} 456 457# f_dialog_input_change [$seconds] 458# 459# Allow the user to enter a date/time (in number-of-seconds since the `epoch') 460# for when a given user's password must be changed. If the user does not cancel 461# or press ESC, the $pw_password_expire variable will hold the newly- 462# configured value upon return. 463# 464f_dialog_input_change() 465{ 466 local calendar_size timebox_size 467 local msg menu_size size retval _input="$1" 468 local hline="$hline_num_arrows_tab_enter" 469 470 local menu_list=" 471 '1' '$msg_password_does_not_expire' 472 '2' '$msg_edit_date_time_with_a_calendar' 473 '3' '$msg_enter_number_of_days_into_the_future' 474 '4' '$msg_enter_value_manually' 475 " # END-QUOTE 476 477 # 478 # Loop until the user provides taint-free/cancellation-free input 479 # 480 while :; do 481 msg="$msg_password_expires_on" 482 menu_size=$( eval f_dialog_menu_size \ 483 \"\$DIALOG_TITLE\" \ 484 \"\$DIALOG_BACKTITLE\" \ 485 \"\$msg\" \ 486 \"\$hline\" \ 487 $menu_list ) 488 489 local dialog_menu 490 dialog_menu=$( eval $DIALOG \ 491 --title \"\$DIALOG_TITLE\" \ 492 --backtitle \"\$DIALOG_BACKTITLE\" \ 493 --hline \"\$hline\" \ 494 --ok-label \"\$msg_ok\" \ 495 --cancel-label \"\$msg_cancel\" \ 496 --menu \"\$msg\" $menu_size \ 497 $menu_list \ 498 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 499 ) 500 retval=$? 501 setvar DIALOG_MENU_$$ "$dialog_menu" 502 date_type=$( f_dialog_menutag ) 503 f_dprintf "retval=%u date_type=[%s]" $retval "$date_type" 504 505 # Return if user has either pressed ESC or chosen Cancel/No 506 [ $retval -eq $SUCCESS ] || return $retval 507 508 case "$date_type" in 509 1) # Password does not expire 510 _input="" 511 break ;; 512 513 2) # Edit date/time with a calendar 514 local _input_date _input_time ret_date ret_time 515 516 local secs="$_input" 517 { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= 518 _input_date=$( date -j -f "%s" -- "$secs" \ 519 "+%d %m %Y" 2> /dev/null ) 520 calendar_size=$( f_dialog_calendar_size \ 521 "$DIALOG_TITLE" \ 522 "$DIALOG_BACKTITLE" \ 523 "$msg" \ 524 "$hline" ) 525 local dialog_inputbox 526 dialog_inputbox=$( eval $DIALOG \ 527 --title \"\$DIALOG_TITLE\" \ 528 --backtitle \"\$DIALOG_BACKTITLE\" \ 529 --hline \"\$hline\" \ 530 --ok-label \"\$msg_ok\" \ 531 --cancel-label \"\$msg_cancel\" \ 532 --calendar \"\$msg\" $calendar_size \ 533 $_input_date \ 534 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 535 ) 536 retval=$? 537 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 538 ret_date=$( f_dialog_inputstr ) 539 f_dprintf "retval=%u ret_date=[%s]" $retval "$ret_date" 540 541 # Return to menu if either ESC or Cancel/No 542 [ $retval -eq $SUCCESS ] || continue 543 544 _input_time= 545 [ "$secs" ] && _input_time=$( date -j \ 546 -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) 547 timebox_size=$( f_dialog_timebox_size \ 548 "$DIALOG_TITLE" \ 549 "$DIALOG_BACKTITLE" \ 550 "$msg" \ 551 "$hline" ) 552 local dialog_inputbox 553 dialog_inputbox=$( eval $DIALOG \ 554 --title \"\$DIALOG_TITLE\" \ 555 --backtitle \"\$DIALOG_BACKTITLE\" \ 556 --hline \"\$hline\" \ 557 --ok-label \"\$msg_ok\" \ 558 --cancel-label \"\$msg_cancel\" \ 559 --timebox \"\$msg\" $timebox_size \ 560 $_input_time \ 561 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 562 ) 563 retval=$? 564 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 565 ret_time=$( f_dialog_inputstr ) 566 f_dprintf "retval=%u ret_time=[%s]" $retval "$ret_time" 567 568 # Return to menu if either ESC or Cancel/No 569 [ $retval -eq $SUCCESS ] || continue 570 571 _input=$( date \ 572 -j -f "%d/%m/%Y %T" \ 573 -- "$ret_date $ret_time" \ 574 +%s 2> /dev/null ) 575 f_dprintf "_input=[%s]" "$_input" 576 break ;; 577 578 3) # Enter number of days into the future 579 local ret_days seconds="$( date +%s )" 580 581 f_isinteger "$_input" || _input=0 582 [ $_input -gt 0 -a $_input -gt $seconds ] && 583 ret_days=$(( ( $_input - $seconds ) / 86400 )) 584 f_isinteger "$ret_days" && 585 ret_days=$(( $ret_days + 1 )) 586 587 # Return to menu if either ESC or Cancel/No 588 ret_days=$( f_dialog_input \ 589 "$msg_password_expires_in_how_many_days" \ 590 "$ret_days" "$hline" 591 ) || continue 592 593 # Taint-check the user's input 594 if ! f_isinteger "$ret_days"; then 595 f_dialog_msgbox "$msg_invalid_number_of_days" 596 continue 597 fi 598 599 f_dprintf "ret_days=[%s]" "$ret_days" 600 case "$ret_days" in 601 [-+]*) _input=$( date -v${ret_days}d +%s );; 602 0) _input=$( date +%s );; 603 *) _input=$( date -v+${ret_days}d +%s );; 604 esac 605 f_dprintf "_input=[%s]" "$_input" 606 break ;; 607 608 4) # Enter value manually 609 local ret_secs 610 611 msg=$( printf "$msg_number_of_seconds_since_epoch" \ 612 "$( date -r 1 "+%c %Z" )" ) 613 614 # Return to menu if either ESC or Cancel/No 615 ret_secs=$( f_dialog_input \ 616 "$msg" "$_input" "$hline" ) || continue 617 618 _input="$ret_secs" 619 620 # Taint-check the user's input 621 if ! f_isinteger "${_input:-0}"; then 622 f_dialog_msgbox \ 623 "$msg_invalid_number_of_seconds" 624 continue 625 fi 626 627 f_dprintf "_input=[%s]" "$_input" 628 break ;; 629 630 esac 631 632 done # Loop forever 633 634 pw_password_expire="$_input" 635 save_flag=1 636 637 f_dprintf "pw_password_expire: [%s]->[%s]" \ 638 "$cur_pw_password_expire" "$pw_password_expire" 639 640 return $SUCCESS 641} 642 643# f_dialog_input_expire [$seconds] 644# 645# Allow the user to enter a date/time (in number-of-seconds since the `epoch') 646# for when a given user's account should become expired. If the user does not 647# cancel or press ESC, the $pw_account_expire variable will hold the newly- 648# configured value upon return. 649# 650f_dialog_input_expire() 651{ 652 local calendar_size timebox_size 653 local msg menu_size size retval _input="$1" 654 local hline="$hline_num_arrows_tab_enter" 655 656 local menu_list=" 657 '1' '$msg_account_does_not_expire' 658 '2' '$msg_edit_date_time_with_a_calendar' 659 '3' '$msg_enter_number_of_days_into_the_future' 660 '4' '$msg_enter_value_manually' 661 " # END-QUOTE 662 663 # 664 # Loop until the user provides taint-free/cancellation-free input 665 # 666 while :; do 667 msg="$msg_account_expires_on" 668 menu_size=$( eval f_dialog_menu_size \ 669 \"\$DIALOG_TITLE\" \ 670 \"\$DIALOG_BACKTITLE\" \ 671 \"\$msg\" \ 672 \"\$hline\" \ 673 $menu_list ) 674 675 local dialog_menu 676 dialog_menu=$( eval $DIALOG \ 677 --title \"\$DIALOG_TITLE\" \ 678 --backtitle \"\$DIALOG_BACKTITLE\" \ 679 --hline \"\$hline\" \ 680 --ok-label \"\$msg_ok\" \ 681 --cancel-label \"\$msg_cancel\" \ 682 --menu \"\$msg\" $menu_size \ 683 $menu_list \ 684 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 685 ) 686 retval=$? 687 setvar DIALOG_MENU_$$ "$dialog_menu" 688 date_type=$( f_dialog_menutag ) 689 f_dprintf "retval=%u date_type=[%s]" $retval "$date_type" 690 691 # Return if user has either pressed ESC or chosen Cancel/No 692 [ $retval -eq $SUCCESS ] || return $retval 693 694 case "$date_type" in 695 1) # Account does not expire 696 _input="" 697 break ;; 698 699 2) # Edit date/time with a calendar 700 local _input_date _input_time ret_date ret_time 701 702 local secs="$_input" 703 { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= 704 _input_date=$( date -j -f "%s" -- "$secs" \ 705 "+%d %m %Y" 2> /dev/null ) 706 calendar_size=$( f_dialog_calendar_size \ 707 "$DIALOG_TITLE" \ 708 "$DIALOG_BACKTITLE" \ 709 "$msg" \ 710 "$hline" ) 711 local dialog_inputbox 712 dialog_inputbox=$( eval $DIALOG \ 713 --title \"\$DIALOG_TITLE\" \ 714 --backtitle \"\$DIALOG_BACKTITLE\" \ 715 --hline \"\$hline\" \ 716 --ok-label \"\$msg_ok\" \ 717 --cancel-label \"\$msg_cancel\" \ 718 --calendar \"\$msg\" $calendar_size \ 719 $_input_date \ 720 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 721 ) 722 retval=$? 723 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 724 ret_date=$( f_dialog_inputstr ) 725 f_dprintf "retval=%u ret_date=[%s]" $retval "$ret_date" 726 727 # Return to menu if either ESC or Cancel/No 728 [ $retval -eq $SUCCESS ] || continue 729 730 _input_time= 731 [ "$secs" ] && _input_time=$( date -j \ 732 -f %s -- "$_input" "+%H %M %S" 2> /dev/null ) 733 timebox_size=$( f_dialog_timebox_size \ 734 "$DIALOG_TITLE" \ 735 "$DIALOG_BACKTITLE" \ 736 "$msg" \ 737 "$hline" ) 738 dialog_inputbox=$( eval $DIALOG \ 739 --title \"\$DIALOG_TITLE\" \ 740 --backtitle \"\$DIALOG_BACKTITLE\" \ 741 --hline \"\$hline\" \ 742 --ok-label \"\$msg_ok\" \ 743 --cancel-label \"\$msg_cancel\" \ 744 --timebox \"\$msg\" $timebox_size \ 745 $_input_time \ 746 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 747 ) 748 retval=$? 749 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 750 ret_time=$( f_dialog_inputstr ) 751 f_dprintf "retval=%u ret_time=[%s]" $retval "$ret_time" 752 753 # Return to menu if either ESC or Cancel/No 754 [ $retval -eq $SUCCESS ] || continue 755 756 _input=$( date \ 757 -j -f "%d/%m/%Y %T" \ 758 -- "$ret_date $ret_time" \ 759 +%s 2> /dev/null ) 760 f_dprintf "_input=[%s]" "$_input" 761 break ;; 762 763 3) # Enter number of days into the future 764 local ret_days seconds="$( date +%s )" 765 766 f_isinteger "$_input" || _input=0 767 [ $_input -gt 0 -a $_input -gt $seconds ] && 768 ret_days=$(( ( $_input - $seconds ) / 86400 )) 769 f_isinteger "$ret_days" && 770 ret_days=$(( $ret_days + 1 )) 771 772 # Return to menu if either ESC or Cancel/No 773 ret_days=$( f_dialog_input \ 774 "$msg_account_expires_in_how_many_days" \ 775 "$ret_days" "$hline" 776 ) || continue 777 778 # Taint-check the user's input 779 if ! f_isinteger "$ret_days"; then 780 f_dialog_msgbox "$msg_invalid_number_of_days" 781 continue 782 fi 783 784 f_dprintf "ret_days=[%s]" "$ret_days" 785 case "$ret_days" in 786 [-+]*) _input=$( date -v${ret_days}d +%s );; 787 0) _input=$( date +%s );; 788 *) _input=$( date -v+${ret_days}d +%s );; 789 esac 790 f_dprintf "_input=[%s]" "$_input" 791 break ;; 792 793 4) # Enter value manually 794 local ret_secs 795 796 msg=$( printf "$msg_number_of_seconds_since_epoch" \ 797 "$( date -r 1 "+%c %Z" )" ) 798 799 # Return to menu if either ESC or Cancel/No 800 ret_secs=$( f_dialog_input \ 801 "$msg" "$_input" "$hline" ) || continue 802 803 _input="$ret_secs" 804 805 # Taint-check the user's input 806 if ! f_isinteger "${_input:-0}"; then 807 f_dialog_msgbox \ 808 "$msg_invalid_number_of_seconds" 809 continue 810 fi 811 812 f_dprintf "_input=[%s]" "$_input" 813 break ;; 814 815 esac 816 817 done # Loop forever 818 819 pw_account_expire="$_input" 820 save_flag=1 821 822 f_dprintf "pw_account_expire: [%s]->[%s]" \ 823 "$cur_pw_account_expire" "$pw_account_expire" 824 825 return $SUCCESS 826} 827 828# f_dialog_input_home_dir [$home_dir] 829# 830# Allow the user to enter a new home directory for a given user. If the user 831# does not cancel or press ESC, the $pw_home_dir variable will hold the newly- 832# configured value upon return. 833# 834f_dialog_input_home_dir() 835{ 836 local _input="$1" 837 838 # Return if user has either pressed ESC or chosen Cancel/No 839 _input=$( f_dialog_input "$msg_home_directory" "$_input" \ 840 "$hline_alnum_punc_tab_enter" 841 ) || return 842 843 pw_home_dir="$_input" 844 save_flag=1 845 846 f_dprintf "pw_home_dir: [%s]->[%s]" "$cur_pw_home_dir" "$pw_home_dir" 847 848 return $SUCCESS 849} 850 851# f_dialog_input_home_create 852# 853# Prompt the user to confirm creation of a given user's home directory. If the 854# user does not cancel (by choosing "No") or press ESC, the $pw_home_create 855# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return 856# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. 857# 858f_dialog_input_home_create() 859{ 860 local retval 861 862 f_dialog_yesno "$msg_create_home_directory" 863 retval=$? 864 865 if [ $retval -eq $SUCCESS ]; then 866 pw_home_create="$msg_yes" 867 else 868 pw_home_create="$msg_no" 869 fi 870 save_flag=1 871 872 f_dprintf "pw_home_create: [%s]->[%s]" \ 873 "$cur_pw_home_create" "$pw_home_create" 874 875 [ $retval -ne 255 ] # return failure if user pressed ESC 876} 877 878# f_dialog_input_group_delete 879# 880# Prompt the user to confirm deletion of a given user's primary group. If the 881# user does not cancel (by choosing "No") or press ESC, the $pw_group_delete 882# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return 883# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. 884# 885f_dialog_input_group_delete() 886{ 887 local retval 888 889 if f_isinteger "$pw_gid"; then 890 if [ $pw_gid -lt 1000 ]; then 891 f_dialog_noyes "$msg_delete_primary_group" 892 else 893 f_dialog_yesno "$msg_delete_primary_group" 894 fi 895 elif [ "$pw_gid" ]; then 896 local gid=0 897 gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' ) 898 if f_isinteger "$gid" && [ $gid -lt 1000 ]; then 899 f_dialog_noyes "$msg_delete_primary_group" 900 else 901 f_dialog_yesno "$msg_delete_primary_group" 902 fi 903 else 904 f_dialog_yesno "$msg_delete_primary_group" 905 fi 906 retval=$? 907 908 if [ $retval -eq $SUCCESS ]; then 909 pw_group_delete="$msg_yes" 910 else 911 pw_group_delete="$msg_no" 912 fi 913 save_flag=1 914 915 f_dprintf "pw_group_delete: [%s]->[%s]" \ 916 "$cur_pw_group_delete" "$pw_group_delete" 917 918 [ $retval -ne 255 ] # return failure if user pressed ESC 919} 920 921# f_dialog_input_home_delete 922# 923# Prompt the user to confirm deletion of a given user's home directory. If the 924# user does not cancel (by choosing "No") or press ESC, the $pw_home_delete 925# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return 926# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. 927# 928f_dialog_input_home_delete() 929{ 930 local retval 931 932 f_dialog_yesno "$msg_delete_home_directory" 933 retval=$? 934 935 if [ $retval -eq $SUCCESS ]; then 936 pw_home_delete="$msg_yes" 937 else 938 pw_home_delete="$msg_no" 939 fi 940 save_flag=1 941 942 f_dprintf "pw_home_delete: [%s]->[%s]" \ 943 "$cur_pw_home_delete" "$pw_home_delete" 944 945 [ $retval -ne 255 ] # return failure if user pressed ESC 946} 947 948# f_dialog_input_dotfiles_create 949# 950# Prompt the user to confirm population of a given user's home directory with 951# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC, 952# the $pw_dotfiles_create variable will hold $msg_yes upon return, otherwise 953# $msg_no. Use these return variables ($msg_yes and $msg_no) for comparison to 954# be i18n-compatible. 955# 956f_dialog_input_dotfiles_create() 957{ 958 local retval 959 960 f_dialog_yesno "$msg_create_dotfiles" 961 retval=$? 962 963 if [ $retval -eq $SUCCESS ]; then 964 pw_dotfiles_create="$msg_yes" 965 else 966 pw_dotfiles_create="$msg_no" 967 fi 968 save_flag=1 969 970 f_dprintf "pw_dotfiles_create: [%s]->[%s]" \ 971 "$cur_pw_dotfiles_create" "$pw_dotfiles_create" 972 973 [ $retval -ne 255 ] # return failure if user pressed ESC 974} 975 976# f_dialog_input_shell [$shell] 977# 978# Allow the user to select a new login shell for a given user. If the user does 979# not cancel or press ESC, the $pw_home_dir variable will hold the newly- 980# configured value upon return. 981# 982# 983f_dialog_input_shell() 984{ 985 local size retval shells shell_list _input="$1" 986 local hline="$hline_arrows_space_tab_enter" 987 local prompt="$msg_select_login_shell" 988 989 shells=$( awk '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" ) 990 shell_list=$( 991 for shell in $shells; do 992 if [ "$shell" = "$_input" ]; then 993 echo "'$shell' '' 'on'" 994 else 995 echo "'$shell' '' 'off'" 996 fi 997 done 998 ) 999 1000 size=$( eval f_dialog_radiolist_size \ 1001 \"\$DIALOG_TITLE\" \ 1002 \"\$DIALOG_BACKTITLE\" \ 1003 \"\$prompt\" \ 1004 \"\$hline\" \ 1005 $shell_list ) 1006 1007 local dialog_inputbox 1008 dialog_inputbox=$( eval $DIALOG \ 1009 --title \"\$DIALOG_TITLE\" \ 1010 --backtitle \"\$DIALOG_BACKTITLE\" \ 1011 --hline \"\$hline\" \ 1012 --ok-label \"\$msg_ok\" \ 1013 --cancel-label \"\$msg_cancel\" \ 1014 --radiolist \"\$prompt\" $size \ 1015 $shell_list \ 1016 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 1017 ) 1018 1019 retval=$? 1020 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox" 1021 _input=$( f_dialog_inputstr ) 1022 1023 # Return if user has either pressed ESC or chosen Cancel/No 1024 [ $retval -eq $SUCCESS ] || return $retval 1025 1026 pw_shell="$_input" 1027 save_flag=1 1028 1029 f_dprintf "pw_shell: [%s]->[%s]" "$cur_pw_shell" "$pw_shell" 1030 1031 return $SUCCESS 1032} 1033 1034############################################################ MAIN 1035 1036f_dprintf "%s: Successfully loaded." usermgmt/user_input.subr 1037 1038fi # ! $_USERMGMT_USER_INPUT_SUBR 1039