]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.sbin/bsdconfig/usermgmt/share/group_input.subr
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.sbin / bsdconfig / usermgmt / share / group_input.subr
1 if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
2 #
3 # Copyright (c) 2012 Ron McDowell
4 # Copyright (c) 2012-2014 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
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
37
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
41
42 ############################################################ FUNCTIONS
43
44 # f_input_group $group
45 #
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).
48 #
49 f_input_group()
50 {
51         local funcname=f_input_group
52         local group="$1"
53
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
59         }
60         {
61                 found = $1 != ""
62                 set_value("name",     $1)
63                 set_value("password", "")
64                 set_value("gid",      $3)
65                 set_value("members",  $4)
66                 exit
67         }
68         END { if (!found) print "false" }' )"
69 }
70
71 # f_dialog_menu_group_list [$default]
72 #
73 # Allows the user to select a group from a list. Optionally, if present and
74 # non-NULL, initially highlight $default group.
75 #
76 f_dialog_menu_group_list()
77 {
78         local prompt=
79         local menu_list="
80                 'X $msg_exit' ''
81         " # END-QUOTE
82         local defaultitem="$1"
83         local hline="$hline_alnum_punc_tab_enter"
84
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
91                 }
92                 !/^[[:space:]]*(#|$)/ { mprint($1, $1) }
93         ' )"
94
95         local height width rows
96         eval f_dialog_menu_size height width rows \
97                                 \"\$DIALOG_TITLE\"     \
98                                 \"\$DIALOG_BACKTITLE\" \
99                                 \"\$prompt\"           \
100                                 \"\$hline\"            \
101                                 $menu_list
102
103         local menu_choice
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               \
113                 $menu_list                         \
114                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
115         )
116         local retval=$?
117         f_dialog_menutag_store -s "$menu_choice"
118         return $retval
119 }
120
121 # f_dialog_input_group_name $var_to_set [$group_name]
122 #
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
125 # upon return.
126 #
127 f_dialog_input_group_name()
128 {
129         local __var_to_set="$1" __name="$2"
130
131         #
132         # Loop until the user provides taint-free/valid input
133         #
134         local __input="$__name"
135         while :; do
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 $?
139
140                 # Check for no-change
141                 if [ "$__input" = "$__name" ]; then
142                         setvar "$__var_to_set" "$__input"
143                         return $DIALOG_OK
144                 fi
145
146                 # Check for NULL entry
147                 if [ ! "$__input" ]; then
148                         f_show_msg "$msg_group_is_empty"
149                         continue
150                 fi
151
152                 # Check for invalid entry
153                 case "$__input" in [!a-zA-Z]*)
154                         f_show_msg "$msg_group_must_start_with_letter"
155                         continue
156                 esac
157
158                 # Check for duplicate entry
159                 if f_quietly pw groupshow -n "$__input"; then
160                         f_show_msg "$msg_group_already_used" "$__input"
161                         continue
162                 fi
163
164                 setvar "$__var_to_set" "$__input"
165                 break
166         done
167
168         return $DIALOG_OK
169 }
170
171 # f_dialog_input_group_password $var_to_set $dvar_to_set
172 #
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.
178 #
179 f_dialog_input_group_password()
180 {
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"
185
186         local __height1 __width1
187         f_dialog_inputbox_size __height1 __width1 \
188                         "$DIALOG_TITLE"     \
189                         "$DIALOG_BACKTITLE" \
190                         "$__prompt1"        \
191                         ""                  \
192                         "$__hline"
193
194         local __height2 __width2
195         f_dialog_inputbox_size __height2 __width2 \
196                         "$DIALOG_TITLE"     \
197                         "$DIALOG_BACKTITLE" \
198                         "$__prompt2"        \
199                         ""                  \
200                         "$__hline"
201
202         #
203         # Loop until the user provides taint-free/valid input
204         #
205         local __retval __password1 __password2
206         while :; do
207                 __password1=$( $DIALOG \
208                         --title "$DIALOG_TITLE"         \
209                         --backtitle "$DIALOG_BACKTITLE" \
210                         --hline "$__hline"              \
211                         --ok-label "$msg_ok"            \
212                         --cancel-label "$msg_cancel"    \
213                         --insecure                      \
214                         --passwordbox "$__prompt1"      \
215                         $__height1 $__width1            \
216                         2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
217                 )
218                 __retval=$?
219                 debug= f_dialog_line_sanitize __password1
220
221                 # Return if user has either pressed ESC or chosen Cancel/No
222                 [ $__retval -eq $DIALOG_OK ] || return $__retval
223
224                 __password2=$( $DIALOG \
225                         --title "$DIALOG_TITLE"         \
226                         --backtitle "$DIALOG_BACKTITLE" \
227                         --hline "$__hline"              \
228                         --ok-label "$msg_ok"            \
229                         --cancel-label "$msg_cancel"    \
230                         --insecure                      \
231                         --passwordbox "$__prompt2"      \
232                         $__height2 $__width2            \
233                         2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
234                 )
235                 __retval=$?
236                 debug= f_dialog_line_sanitize __password2
237
238                 # Return if user has either pressed ESC or chosen Cancel/No
239                 [ $__retval -eq $DIALOG_OK ] || return $__retval
240
241                 # Check for password mismatch
242                 if [ "$__password1" != "$__password2" ]; then
243                         f_show_msg "$msg_group_passwords_do_not_match"
244                         continue
245                 fi
246
247                 # Check for NULL entry
248                 if [ ! "$__password1" ]; then
249                         f_dialog_yesno "$msg_disable_password_auth_for_group"
250                         __retval=$?
251                         if [ $__retval -eq $DIALOG_ESC ]; then
252                                 return $__retval
253                         elif [ $__retval -eq $DIALOG_OK ]; then
254                                 setvar "$__dvar_to_set" 1
255                         else
256                                 continue # back to password prompt
257                         fi
258                 else
259                         setvar "$__dvar_to_set" ""
260                 fi
261
262                 setvar "$__var_to_set" "$__password1"
263                 break
264         done
265
266         return $DIALOG_OK
267 }
268
269 # f_dialog_input_group_gid $var_to_set [$group_gid]
270 #
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
273 # value upon return.
274 #
275 f_dialog_input_group_gid()
276 {
277         local __var_to_set="$1" __input="$2"
278
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 $?
282
283         setvar "$__var_to_set" "$__input"
284         return $DIALOG_OK
285 }
286
287 # f_dialog_input_group_members $var_to_set [$group_members]
288 #
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.
292 #
293 f_dialog_input_group_members()
294 {
295         local __var_to_set="$1" __input="$2"
296         local __prompt="$msg_group_members:"
297         local __menu_list="
298                 'X' '$msg_continue'
299                 '1' '$msg_select_group_members_from_list'
300                 '2' '$msg_enter_group_members_manually'
301         " # END-QUOTE
302         local __defaultitem=
303         local __hline="$hline_num_arrows_tab_enter"
304
305         local __mheight __mwidth __mrows
306         eval f_dialog_menu_size __mheight __mwidth __mrows \
307                                 \"\$DIALOG_TITLE\"     \
308                                 \"\$DIALOG_BACKTITLE\" \
309                                 \"\$__prompt\"         \
310                                 \"\$__hline\"          \
311                                 $__menu_list
312
313         local __menu_choice __retval
314         while :; do
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      \
324                         $__menu_list                       \
325                         2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
326                 )
327                 __retval=$?
328                 f_dialog_data_sanitize __menu_choice
329                 __defaultitem="$__menu_choice"
330                 f_dprintf "retval=%u menu_choice=[%s]" \
331                           $__retval "$__menu_choice"
332
333                 # Return if user has either pressed ESC or chosen Cancel/No
334                 [ $__retval -eq $DIALOG_OK ] || return $__retval
335
336                 local __group_members
337                 case "$__menu_choice" in
338                 X) # Exit
339                         break ;;
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
348
349                                 # Format of a checklist entry: tag item status
350                                 __check_list="$__check_list '$__user' ''"
351                                 case "$__input" in
352                                 "$__u"|"$__u",*|*,"$__u",*|*,"$__u")
353                                         __check_list="$__check_list on" ;;
354                                 *)
355                                         __check_list="$__check_list off"
356                                 esac
357
358                                 __length=${#__user_list}
359                                 __user_list="${__user_list#*$NL}" # Kill line
360                         done
361
362                         local __cheight __cwidth __crows
363                         eval f_dialog_checklist_size \
364                                 __cheight __cwidth __crows \
365                                 \"\$DIALOG_TITLE\"     \
366                                 \"\$DIALOG_BACKTITLE\" \
367                                 \"\$__prompt\"         \
368                                 \"\$__hline\"          \
369                                 $__check_list
370                         __group_members=$( eval $DIALOG \
371                                 --title \"\$DIALOG_TITLE\"         \
372                                 --backtitle \"\$DIALOG_BACKTITLE\" \
373                                 --separate-output                  \
374                                 --hline \"\$__hline\"              \
375                                 --ok-label \"\$msg_ok\"            \
376                                 --cancel-label \"\$msg_cancel\"    \
377                                 --checklist \"\$__prompt\"         \
378                                 $__cheight $__cwidth $__crows      \
379                                 $__check_list                      \
380                                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
381                         ) || continue
382                                 # Return to previous menu if user either
383                                 # pressed ESC or chose Cancel/No
384                         f_dialog_data_sanitize __group_members
385
386                         #
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
390                         #
391                         f_replaceall "$__group_members" "[$NL]" "," __input
392                         ;;
393                 2) # Enter Group Members manually
394                         local __prompt2="$msg_group_members"
395                         __prompt2="$__prompt2 ($msg_separated_by_commas)"
396
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
402
403                         __input="$__group_members"
404                         ;;
405                 esac
406         done
407
408         setvar "$__var_to_set" "$__input"
409         return $DIALOG_OK
410 }
411
412 # f_dialog_menu_group_add [$defaultitem]
413 #
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
419 # menu.
420 #
421 f_dialog_menu_group_add()
422 {
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"
427
428         # Localize potentially hostile variables and escape their values
429         # to the local variable (see f_shell_escape() of `strings.subr')
430         local var
431         for var in gid members name; do
432                 local _group_$var
433                 eval f_shell_escape \"\$group_$var\" _group_$var
434         done
435
436         menu_list="
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'
442         " # END-QUOTE
443
444         local height width rows
445         eval f_dialog_menu_size height width rows \
446                                 \"\$DIALOG_TITLE\"     \
447                                 \"\$DIALOG_BACKTITLE\" \
448                                 \"\$prompt\"           \
449                                 \"\$hline\"            \
450                                 $menu_list
451
452         local menu_choice
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               \
462                 $menu_list                         \
463                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
464         )
465         local retval=$?
466         f_dialog_data_sanitize menu_choice
467         f_dialog_menutag_store "$menu_choice"
468         return $retval
469 }
470
471 # f_dialog_menu_group_delete $group [$defaultitem]
472 #
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.
479 #
480 f_dialog_menu_group_delete()
481 {
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"
486
487         local group_name group_password group_gid group_members
488         f_input_group "$1"
489
490         # Localize potentially hostile variables and escape their values
491         # to the local variable (see f_shell_escape() of `strings.subr')
492         local var
493         for var in gid members name; do
494                 local _group_$var
495                 eval f_shell_escape \"\$group_$var\" _group_$var
496         done
497
498         menu_list="
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'
504         " # END-QUOTE
505
506         local height width rows
507         eval f_dialog_menu_size height width rows \
508                                 \"\$DIALOG_TITLE\"     \
509                                 \"\$DIALOG_BACKTITLE\" \
510                                 \"\$prompt\"           \
511                                 \"\$hline\"            \
512                                 $menu_list
513
514         local menu_choice
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               \
524                 $menu_list                         \
525                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
526         )
527         local retval=$?
528         f_dialog_data_sanitize menu_choice
529         f_dialog_menutag_store "$menu_choice"
530         return $retval
531 }
532
533 # f_dialog_menu_group_edit [$defaultitem]
534 #
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
540 # menu.
541 #
542 f_dialog_menu_group_edit()
543 {
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"
548
549         # Localize potentially hostile variables and escape their values
550         # to the local variable (see f_shell_escape() of `strings.subr')
551         local var
552         for var in gid members name; do
553                 local _group_$var
554                 eval f_shell_escape \"\$group_$var\" _group_$var
555         done
556
557         menu_list="
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'
563         " # END-QUOTE
564
565         local height width rows
566         eval f_dialog_menu_size height width rows \
567                                 \"\$DIALOG_TITLE\"     \
568                                 \"\$DIALOG_BACKTITLE\" \
569                                 \"\$prompt\"           \
570                                 \"\$hline\"            \
571                                 $menu_list
572
573         local menu_choice
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               \
583                 $menu_list                         \
584                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
585         )
586         local retval=$?
587         f_dialog_data_sanitize menu_choice
588         f_dialog_menutag_store "$menu_choice"
589         return $retval
590 }
591
592 ############################################################ MAIN
593
594 f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
595
596 fi # ! $_USERMGMT_GROUP_INPUT_SUBR