1 if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
3 # Copyright (c) 2012 Ron McDowell
4 # Copyright (c) 2012-2014 Devin Teske
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
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.
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
30 ############################################################ INCLUDES
32 BSDCFG_SHARE="/usr/share/bsdconfig"
33 . $BSDCFG_SHARE/common.subr || exit 1
34 f_dprintf "%s: loading includes..." usermgmt/group_input.subr
35 f_include $BSDCFG_SHARE/dialog.subr
36 f_include $BSDCFG_SHARE/strings.subr
38 BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
39 f_include_lang $BSDCFG_LIBE/include/messages.subr
40 f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
42 ############################################################ FUNCTIONS
44 # f_input_group $group
46 # Given $group name or id, create the environment variables group_name,
47 # group_gid, and group_members (and group_password is reset to NULL).
51 local funcname=f_input_group
54 f_dprintf "$funcname: Getting info for group \`%s'" "$group"
55 eval "$( pw groupshow "$group" 2> /dev/null | awk -F: '
56 function set_value(var, value) {
57 gsub(/'\''/, "'\''\\'\'\''", value)
58 printf "group_%s='\'%s\''\n", var, value
63 set_value("password", "")
65 set_value("members", $4)
68 END { if (!found) print "false" }' )"
71 # f_dialog_menu_group_list [$default]
73 # Allows the user to select a group from a list. Optionally, if present and
74 # non-NULL, initially highlight $default group.
76 f_dialog_menu_group_list()
82 local defaultitem="$1"
83 local hline="$hline_alnum_punc_tab_enter"
85 # Add groups from group(5)
86 menu_list="$menu_list $( pw groupshow -a | awk -F: '
87 function mprint(tag, item) {
88 gsub(/'\''/, "'\''\\'\'\''", tag)
89 gsub(/'\''/, "'\''\\'\'\''", item)
90 printf "'\'%s\'\ \'%s\''\n", tag, item
92 !/^[[:space:]]*(#|$)/ { mprint($1, $1) }
95 local height width rows
96 eval f_dialog_menu_size height width rows \
98 \"\$DIALOG_BACKTITLE\" \
104 menu_choice=$( eval $DIALOG \
105 --title \"\$DIALOG_TITLE\" \
106 --backtitle \"\$DIALOG_BACKTITLE\" \
107 --hline \"\$hline\" \
108 --ok-label \"\$msg_ok\" \
109 --cancel-label \"\$msg_cancel\" \
110 --default-item \"\$defaultitem\" \
111 --menu \"\$prompt\" \
112 $height $width $rows \
114 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
117 f_dialog_menutag_store -s "$menu_choice"
121 # f_dialog_input_group_name $var_to_set [$group_name]
123 # Allows the user to enter a name for a new group. If the user does not cancel
124 # or press ESC, the $var_to_set variable will hold the newly-configured value
127 f_dialog_input_group_name()
129 local __var_to_set="$1" __name="$2"
132 # Loop until the user provides taint-free/valid input
134 local __input="$__name"
136 # Return if user has either pressed ESC or chosen Cancel/No
137 f_dialog_input __input "$msg_group" "$__input" \
138 "$hline_alnum_tab_enter" || return $?
140 # Check for no-change
141 if [ "$__input" = "$__name" ]; then
142 setvar "$__var_to_set" "$__input"
146 # Check for NULL entry
147 if [ ! "$__input" ]; then
148 f_show_msg "$msg_group_is_empty"
152 # Check for invalid entry
153 case "$__input" in [!a-zA-Z]*)
154 f_show_msg "$msg_group_must_start_with_letter"
158 # Check for duplicate entry
159 if f_quietly pw groupshow -n "$__input"; then
160 f_show_msg "$msg_group_already_used" "$__input"
164 setvar "$__var_to_set" "$__input"
171 # f_dialog_input_group_password $var_to_set $dvar_to_set
173 # Prompt the user to enter a password (twice). If the user does not cancel or
174 # press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
175 # user cancels or enters a NULL password (twice), they are given the choice to
176 # disable password authentication for the given group, wherein $dvar_to_set has
177 # a value of 1 to indicate password authentication should be disabled.
179 f_dialog_input_group_password()
181 local __var_to_set="$1" __dvar_to_set="$2"
182 local __prompt1="$msg_group_password"
183 local __prompt2="$msg_reenter_group_password"
184 local __hline="$hline_alnum_punc_tab_enter"
186 local __height1 __width1
187 f_dialog_inputbox_size __height1 __width1 \
189 "$DIALOG_BACKTITLE" \
194 local __height2 __width2
195 f_dialog_inputbox_size __height2 __width2 \
197 "$DIALOG_BACKTITLE" \
203 # Loop until the user provides taint-free/valid input
205 local __retval __password1 __password2
207 __password1=$( $DIALOG \
208 --title "$DIALOG_TITLE" \
209 --backtitle "$DIALOG_BACKTITLE" \
211 --ok-label "$msg_ok" \
212 --cancel-label "$msg_cancel" \
214 --passwordbox "$__prompt1" \
215 $__height1 $__width1 \
216 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
219 debug= f_dialog_line_sanitize __password1
221 # Return if user has either pressed ESC or chosen Cancel/No
222 [ $__retval -eq $DIALOG_OK ] || return $__retval
224 __password2=$( $DIALOG \
225 --title "$DIALOG_TITLE" \
226 --backtitle "$DIALOG_BACKTITLE" \
228 --ok-label "$msg_ok" \
229 --cancel-label "$msg_cancel" \
231 --passwordbox "$__prompt2" \
232 $__height2 $__width2 \
233 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
236 debug= f_dialog_line_sanitize __password2
238 # Return if user has either pressed ESC or chosen Cancel/No
239 [ $__retval -eq $DIALOG_OK ] || return $__retval
241 # Check for password mismatch
242 if [ "$__password1" != "$__password2" ]; then
243 f_show_msg "$msg_group_passwords_do_not_match"
247 # Check for NULL entry
248 if [ ! "$__password1" ]; then
249 f_dialog_yesno "$msg_disable_password_auth_for_group"
251 if [ $__retval -eq $DIALOG_ESC ]; then
253 elif [ $__retval -eq $DIALOG_OK ]; then
254 setvar "$__dvar_to_set" 1
256 continue # back to password prompt
259 setvar "$__dvar_to_set" ""
262 setvar "$__var_to_set" "$__password1"
269 # f_dialog_input_group_gid $var_to_set [$group_gid]
271 # Allow the user to enter a new GID for a given group. If the user does not
272 # cancel or press ESC, the $var_to_set variable will hold the newly-configured
275 f_dialog_input_group_gid()
277 local __var_to_set="$1" __input="$2"
279 # Return if user has either pressed ESC or chosen Cancel/No
280 f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
281 "$__input" "$hline_num_tab_enter" || return $?
283 setvar "$__var_to_set" "$__input"
287 # f_dialog_input_group_members $var_to_set [$group_members]
289 # Allow the user to modify a list of members for a given group. If the user
290 # does not cancel or press ESC, the $var_to_set variable will hold the newly-
291 # configured value upon return.
293 f_dialog_input_group_members()
295 local __var_to_set="$1" __input="$2"
296 local __prompt="$msg_group_members:"
299 '1' '$msg_select_group_members_from_list'
300 '2' '$msg_enter_group_members_manually'
303 local __hline="$hline_num_arrows_tab_enter"
305 local __mheight __mwidth __mrows
306 eval f_dialog_menu_size __mheight __mwidth __mrows \
308 \"\$DIALOG_BACKTITLE\" \
313 local __menu_choice __retval
315 __menu_choice=$( eval $DIALOG \
316 --title \"\$DIALOG_TITLE\" \
317 --backtitle \"\$DIALOG_BACKTITLE\" \
318 --hline \"\$__hline\" \
319 --ok-label \"\$msg_ok\" \
320 --cancel-label \"\$msg_cancel\" \
321 --default-item \"\$__defaultitem\" \
322 --menu \"\$__prompt\" \
323 $__mheight $__mwidth $__mrows \
325 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
328 f_dialog_data_sanitize __menu_choice
329 __defaultitem="$__menu_choice"
330 f_dprintf "retval=%u menu_choice=[%s]" \
331 $__retval "$__menu_choice"
333 # Return if user has either pressed ESC or chosen Cancel/No
334 [ $__retval -eq $DIALOG_OK ] || return $__retval
336 local __group_members
337 case "$__menu_choice" in
340 1) # Select Group Members from a list
341 local __check_list= # Calculated below
342 local __user_list __u __user __length=0
343 __user_list=$( pw usershow -a |
344 awk -F: '!/^[[:space:]]*(#|$)/{print $1}' )
345 while [ $__length -ne ${#__user_list} ]; do
346 __u="${__user_list%%$NL*}" # First line
347 f_shell_escape "$__u" __user
349 # Format of a checklist entry: tag item status
350 __check_list="$__check_list '$__user' ''"
352 "$__u"|"$__u",*|*,"$__u",*|*,"$__u")
353 __check_list="$__check_list on" ;;
355 __check_list="$__check_list off"
358 __length=${#__user_list}
359 __user_list="${__user_list#*$NL}" # Kill line
362 local __cheight __cwidth __crows
363 eval f_dialog_checklist_size \
364 __cheight __cwidth __crows \
366 \"\$DIALOG_BACKTITLE\" \
370 __group_members=$( eval $DIALOG \
371 --title \"\$DIALOG_TITLE\" \
372 --backtitle \"\$DIALOG_BACKTITLE\" \
374 --hline \"\$__hline\" \
375 --ok-label \"\$msg_ok\" \
376 --cancel-label \"\$msg_cancel\" \
377 --checklist \"\$__prompt\" \
378 $__cheight $__cwidth $__crows \
380 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
382 # Return to previous menu if user either
383 # pressed ESC or chose Cancel/No
384 f_dialog_data_sanitize __group_members
387 # Convert the newline separated list into a comma-
388 # separated one so that if the user switches over to
389 # manual editing, list reflects checklist selections
391 f_replaceall "$__group_members" "[$NL]" "," __input
393 2) # Enter Group Members manually
394 local __prompt2="$msg_group_members"
395 __prompt2="$__prompt2 ($msg_separated_by_commas)"
397 f_dialog_input __group_members \
398 "$__prompt2" "$__input" \
399 "$hline_num_tab_enter" || continue
400 # Return to previous menu if user either
401 # pressed ESC or chose Cancel/No
403 __input="$__group_members"
408 setvar "$__var_to_set" "$__input"
412 # f_dialog_menu_group_add [$defaultitem]
414 # Present a menu detailing the properties of a group that is about to be added.
415 # The user's menu choice is available using f_dialog_menutag_fetch(). Returns
416 # success unless the user chose Cancel or pressed ESC. Data to display is taken
417 # from environment variables group_name, group_gid, and group_members. If
418 # $defaultitem is present and non-NULL, initially highlight the item in the
421 f_dialog_menu_group_add()
423 local prompt="$msg_save_exit_or_cancel"
424 local menu_list # Calculated below
425 local defaultitem="$1"
426 local hline="$hline_arrows_tab_enter"
428 # Localize potentially hostile variables and escape their values
429 # to the local variable (see f_shell_escape() of `strings.subr')
431 for var in gid members name; do
433 eval f_shell_escape \"\$group_$var\" _group_$var
437 'X' '$msg_add/$msg_exit'
438 '1' '$msg_group: $_group_name'
439 '2' '$msg_password: -----'
440 '3' '$msg_group_id: $_group_gid'
441 '4' '$msg_group_members: $_group_members'
444 local height width rows
445 eval f_dialog_menu_size height width rows \
447 \"\$DIALOG_BACKTITLE\" \
453 menu_choice=$( eval $DIALOG \
454 --title \"\$DIALOG_TITLE\" \
455 --backtitle \"\$DIALOG_BACKTITLE\" \
456 --hline \"\$hline\" \
457 --ok-label \"\$msg_ok\" \
458 --cancel-label \"\$msg_cancel\" \
459 --default-item \"\$defaultitem\" \
460 --menu \"\$prompt\" \
461 $height $width $rows \
463 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
466 f_dialog_data_sanitize menu_choice
467 f_dialog_menutag_store "$menu_choice"
471 # f_dialog_menu_group_delete $group [$defaultitem]
473 # Present a menu detailing the properties of a group that is about to be
474 # deleted. The user's menu choice is available using f_dialog_menutag_fetch().
475 # Returns success unless the user chose Cancel or pressed ESC. Data to display
476 # is populated automatically from the system accounting database for the given
477 # $group argument. If $defaultitem is present and non-NULL, initially highlight
478 # the item in the menu.
480 f_dialog_menu_group_delete()
482 local prompt="$msg_delete_exit_or_cancel"
483 local menu_list # Calculated below
484 local defaultitem="$2"
485 local hline="$hline_arrows_tab_enter"
487 local group_name group_password group_gid group_members
490 # Localize potentially hostile variables and escape their values
491 # to the local variable (see f_shell_escape() of `strings.subr')
493 for var in gid members name; do
495 eval f_shell_escape \"\$group_$var\" _group_$var
499 'X' '$msg_delete/$msg_exit'
500 '1' '$msg_group: $_group_name'
501 '-' '$msg_password: -----'
502 '-' '$msg_group_id: $_group_gid'
503 '-' '$msg_group_members: $_group_members'
506 local height width rows
507 eval f_dialog_menu_size height width rows \
509 \"\$DIALOG_BACKTITLE\" \
515 menu_choice=$( eval $DIALOG \
516 --title \"\$DIALOG_TITLE\" \
517 --backtitle \"\$DIALOG_BACKTITLE\" \
518 --hline \"\$hline\" \
519 --ok-label \"\$msg_ok\" \
520 --cancel-label \"\$msg_cancel\" \
521 --default-item \"\$defaultitem\" \
522 --menu \"\$prompt\" \
523 $height $width $rows \
525 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
528 f_dialog_data_sanitize menu_choice
529 f_dialog_menutag_store "$menu_choice"
533 # f_dialog_menu_group_edit [$defaultitem]
535 # Present a menu detailing the properties of a group that is about to be
536 # modified. The user's menu choice is available using f_dialog_menutag_fetch().
537 # Returns success unless the user chose Cancel or pressed ESC. Data to display
538 # is taken from environment variables group_name, group_gid, and group_members.
539 # If $defaultitem is present and non-NULL, initially highlight the item in the
542 f_dialog_menu_group_edit()
544 local prompt="$msg_save_exit_or_cancel"
545 local menu_list # Calculated below
546 local defaultitem="$1"
547 local hline="$hline_arrows_tab_enter"
549 # Localize potentially hostile variables and escape their values
550 # to the local variable (see f_shell_escape() of `strings.subr')
552 for var in gid members name; do
554 eval f_shell_escape \"\$group_$var\" _group_$var
558 'X' '$msg_save/$msg_exit'
559 '1' '$msg_group: $_group_name'
560 '2' '$msg_password: -----'
561 '3' '$msg_group_id: $_group_gid'
562 '4' '$msg_group_members: $_group_members'
565 local height width rows
566 eval f_dialog_menu_size height width rows \
568 \"\$DIALOG_BACKTITLE\" \
574 menu_choice=$( eval $DIALOG \
575 --title \"\$DIALOG_TITLE\" \
576 --backtitle \"\$DIALOG_BACKTITLE\" \
577 --hline \"\$hline\" \
578 --ok-label \"\$msg_ok\" \
579 --cancel-label \"\$msg_cancel\" \
580 --default-item \"\$defaultitem\" \
581 --menu \"\$prompt\" \
582 $height $width $rows \
584 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
587 f_dialog_data_sanitize menu_choice
588 f_dialog_menutag_store "$menu_choice"
592 ############################################################ MAIN
594 f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
596 fi # ! $_USERMGMT_GROUP_INPUT_SUBR