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