group_input.subr revision 238438
1if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_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: head/usr.sbin/bsdconfig/usermgmt/include/group_input.subr 238438 2012-07-14 03:16:57Z dteske $
29#
30############################################################ INCLUDES
31
32BSDCFG_LIBE="/usr/libexec/bsdconfig"
33. $BSDCFG_LIBE/include/common.subr || exit 1
34f_include $BSDCFG_LIBE/include/dialog.subr
35f_include $BSDCFG_LIBE/include/strings.subr
36f_include_lang $BSDCFG_LIBE/include/messages.subr
37
38APP_DIR="070.usermgmt"
39f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
40
41############################################################ FUNCTIONS
42
43# f_input_group $group
44#
45# Given $group name or id, create the environment variables group_name,
46# group_gid, and group_members (and group_password is reset to NULL).
47#
48f_input_group()
49{
50	eval $( pw groupshow "$1" | awk -F: '
51	{
52		printf "group_name='\'%s\''\n", $1
53		printf "group_password=\n"
54		printf "group_gid='\'%s\''\n", $3
55		printf "group_members='\'%s\''\n", $4
56		exit
57	}' )
58}
59
60# f_dialog_menu_group_list
61#
62# Allows the user to select a group from a list.
63#
64f_dialog_menu_group_list()
65{
66	local menu_list size
67	local hline="$hline_alnum_punc_tab_enter"
68
69	menu_list="
70		'X $msg_exit' ''
71	" # END-QUOTE
72
73	# Add groups from group(5)
74	menu_list="$menu_list $( pw groupshow -a | awk -F: '
75		!/^[[:space:]]*(#|$)/ {
76			printf "'\'%s\'\ \'%s\''\n", $1, $1
77		}'
78	)"
79
80	size=$( eval f_dialog_menu_size \
81	        	\"\$DIALOG_TITLE\"     \
82	        	\"\$DIALOG_BACKTITLE\" \
83	        	\"\"                   \
84	        	\"\$hline\"            \
85	        	$menu_list             )
86
87	eval $DIALOG \
88		--clear --title \"\$DIALOG_TITLE\" \
89		--backtitle \"\$DIALOG_BACKTITLE\" \
90		--hline \"\$hline\"                \
91		--ok-label \"\$msg_ok\"            \
92		--cancel-label \"\$msg_cancel\"    \
93		--menu \"\" $size $menu_list       \
94		2> "$DIALOG_TMPDIR/dialog.menu.$$"
95}
96
97# f_dialog_input_group_name [$group_name]
98#
99# Allows the user to enter a new groupname for a given group. If the user does
100# not cancel or press ESC, the $group_name variable will hold the
101# newly-configured value upon return.
102#
103# If $cur_group_name is defined, the user can enter that and by-pass error-
104# checking (allowing the user to "revert" to an old value without, for example,
105# being told that the groupname already exists).
106#
107f_dialog_input_group_name()
108{
109	local msg="$( printf "$msg_group" )"
110	local hline="$hline_alnum_tab_enter"
111
112	#
113	# Loop until the user provides taint-free/valid input
114	#
115	local size retval _name="$1" _input="$1"
116	while :; do
117		size=$( f_dialog_inputbox_size \
118		        	"$DIALOG_TITLE"     \
119		        	"$DIALOG_BACKTITLE" \
120		        	"$msg"              \
121		        	"$_input"           \
122		        	"$hline"            )
123
124		eval $DIALOG \
125			--title \"\$DIALOG_TITLE\"         \
126			--backtitle \"\$DIALOG_BACKTITLE\" \
127			--hline \"\$hline\"                \
128			--ok-label \"\$msg_ok\"            \
129			--cancel-label \"\$msg_cancel\"    \
130			--inputbox \"\$msg\" $size         \
131			\"\$_input\"                       \
132			2> $DIALOG_TMPDIR/dialog.inputbox.$$
133
134		retval=$?
135		_input=$( f_dialog_inputstr )
136
137		# Return if user has either pressed ESC or chosen Cancel/No
138		[ $retval -eq $SUCCESS ] || return $retval
139
140		# Check for no-change
141		[ "$_input" = "$_name" ] && return $SUCCESS
142
143		# Check for reversion
144		if [ "$_input" = "$cur_group_name" ]; then
145			group_name="$cur_group_name"
146			return $SUCCESS
147		fi
148
149		# Check for NULL entry
150		if [ ! "$_input" ]; then
151			f_show_msg "$msg_group_is_empty"
152			continue
153		fi
154
155		# Check for invalid entry
156		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
157			f_show_msg "$msg_group_must_start_with_letter"
158			continue
159		fi
160
161		# Check for duplicate entry
162		if f_quietly pw groupshow -n "$_input"; then
163			f_show_msg "$msg_group_already_used" "$_input"
164			continue
165		fi
166
167		group_name="$_input"
168		break
169	done
170	save_flag=1
171
172	f_dprintf "group_name: [$cur_group_name]->[$group_name]"
173
174	return $SUCCESS
175}
176
177# f_dialog_input_group_password
178#
179# Prompt the user to enter a password (twice).
180#
181f_dialog_input_group_password()
182{
183	local hline="$hline_alnum_punc_tab_enter"
184	local msg size rmsg rsize
185
186	msg=$( printf "$msg_group_password" )
187	size=$( f_dialog_inputbox_size \
188	        	"$DIALOG_TITLE"     \
189	        	"$DIALOG_BACKTITLE" \
190	        	"$msg"              \
191	        	""                  \
192	        	"$hline"            )
193
194	rmsg=$( printf "$msg_reenter_group_password" )
195	rsize=$( f_dialog_inputbox_size \
196	        	"$DIALOG_TITLE"     \
197	        	"$DIALOG_BACKTITLE" \
198	        	"$rmsg"             \
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		eval $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 \"\$msg\" $size      \
215			2> $DIALOG_TMPDIR/dialog.inputbox.$$
216
217		retval=$?
218		_password1=$( f_dialog_inputstr )
219
220		# Return if user has either pressed ESC or chosen Cancel/No
221		[ $retval -eq $SUCCESS ] || return $retval
222
223		eval $DIALOG \
224			--title \"\$DIALOG_TITLE\"         \
225			--backtitle \"\$DIALOG_BACKTITLE\" \
226			--hline \"\$hline\"                \
227			--ok-label \"\$msg_ok\"            \
228			--cancel-label \"\$msg_cancel\"    \
229			--insecure                         \
230			--passwordbox \"\$rmsg\" $rsize    \
231			2> $DIALOG_TMPDIR/dialog.inputbox.$$
232
233		retval=$?
234		_password2=$( f_dialog_inputstr )
235
236		# Return if user has either pressed ESC or chosen Cancel/No
237		[ $retval -eq $SUCCESS ] || return $retval
238
239		# Check for password mismatch
240		if [ "$_password1" != "$_password2" ]; then
241			f_show_msg "$msg_group_passwords_do_not_match"
242			continue
243		fi
244
245		# Check for NULL entry
246		if [ ! "$_password1" ]; then
247			f_dialog_yesno \
248				"$msg_disable_password_auth_for_group" ||
249				continue
250			pw_group_password_disable=1
251		else
252			pw_group_password_disable=
253		fi
254
255		group_password="$_password1"
256		break
257	done
258	save_flag=1
259
260	f_dprintf "group_password: [$cur_group_password]->[$group_password]"
261
262	return $SUCCESS
263}
264
265# f_dialog_input_group_gid [$group_gid]
266#
267# Allow the user to enter a new GID for a given group. If the user does not
268# cancel or press ESC, the $group_gid variable will hold the newly-configured
269# value upon return.
270#
271f_dialog_input_group_gid()
272{
273	local msg size retval _input="$1"
274	local hline="$hline_num_tab_enter"
275
276	msg=$( printf "$msg_group_id_leave_empty_for_default" )
277	size=$( f_dialog_inputbox_size \
278	        	"$DIALOG_TITLE"     \
279	        	"$DIALOG_BACKTITLE" \
280	        	"$msg"              \
281	        	"$_input"           \
282	        	"$hline"            )
283
284	eval $DIALOG \
285		--title \"\$DIALOG_TITLE\"         \
286		--backtitle \"\$DIALOG_BACKTITLE\" \
287		--hline \"\$hline\"                \
288		--ok-label \"\$msg_ok\"            \
289		--cancel-label \"\$msg_cancel\"    \
290		--inputbox \"\$msg\" $size         \
291		\"\$_input\"                       \
292		2> $DIALOG_TMPDIR/dialog.inputbox.$$
293
294	retval=$?
295	_input=$( f_dialog_inputstr )
296
297	# Return if user has either pressed ESC or chosen Cancel/No
298	[ $retval -eq $SUCCESS ] || return $retval
299
300	group_gid="$_input"
301	save_flag=1
302
303	f_dprintf "group_gid: [$cur_group_gid]->[$group_gid]"
304
305	return $SUCCESS
306}
307
308# f_dialog_input_group_members [$group_members]
309#
310# Allow the user to modify a list of members for a given group. If the user does
311# not cancel or press ESC, the $group_members variable will hold the newly-
312# configured value upon return.
313#
314f_dialog_input_group_members()
315{
316	local menu_choice msg size retval _input="$1"
317	local hline="$hline_num_arrows_tab_enter"
318	local user 
319	local menu_list
320	local all_users_valid
321	local _group_members
322	local checklist_users
323
324	menu_list="
325		'X' '$msg_continue'
326		'1' '$msg_select_group_members_from_list'
327		'2' '$msg_enter_group_members_manually'
328	" # END-QUOTE
329
330	while :; do
331		msg="$msg_group_members:"
332		menu_size=$( eval f_dialog_menu_size \
333				\"\$DIALOG_TITLE\"     \
334				\"\$DIALOG_BACKTITLE\" \
335				\"\$msg\"              \
336				\"\$hline\"            \
337				$menu_list             )
338		eval $DIALOG \
339			--title \"\$DIALOG_TITLE\"         \
340			--backtitle \"\$DIALOG_BACKTITLE\" \
341			--hline \"\$hline\"                \
342			--ok-label \"\$msg_ok\"            \
343			--cancel-label \"\$msg_cancel\"    \
344			--menu \"\$msg\" $menu_size        \
345			$menu_list                         \
346			2> $DIALOG_TMPDIR/dialog.menu.$$
347		retval=$?
348		menu_choice=$( f_dialog_menutag )
349		f_dprintf "retval=$retval menu_choice=[$menu_choice]"
350
351		# Return if user has either pressed ESC or chosen Cancel/No
352		[ $retval -eq $SUCCESS ] || return $retval
353
354		case "$menu_choice" in
355		X) # Exit
356			break ;;
357		1) # Select Group Members from a list
358			user_list=$( pw usershow -a | awk -F: '
359				!/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' )
360			checklist_users=
361			for user in $user_list; do
362				checklist_users="$checklist_users $user \"\""
363				if echo "$_input" | grep -q "\<$user\>"; then
364					checklist_users="$checklist_users on"
365				else
366					checklist_users="$checklist_users off"
367				fi
368			done
369
370			size=$( eval f_dialog_radiolist_size \
371			        	\"\$DIALOG_TITLE\"     \
372			        	\"\$DIALOG_BACKTITLE\" \
373			        	\"\"                   \
374			        	\"\$hline\"            \
375			        	$checklist_users       )
376			eval $DIALOG \
377				--title \"\$DIALOG_TITLE\"         \
378				--backtitle \"\$DIALOG_BACKTITLE\" \
379				--separate-output                  \
380				--hline \"\$hline\"                \
381				--ok-label \"\$msg_ok\"            \
382				--cancel-label \"\$msg_cancel\"    \
383				--checklist \"\$msg\" $size        \
384				$checklist_users                   \
385				2> $DIALOG_TMPDIR/dialog.inputbox.$$
386			retval=$?
387			_group_members=$( f_dialog_inputstr | tr '\n' ' ' |
388				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' )
389
390			# Return to previous menu if user has either
391			#     pressed ESC or chosen Cancel/No
392			[ $retval -eq $SUCCESS ] || continue
393
394			_input="$_group_members"
395			;;
396		2) # Enter Group Members manually
397			hline="$hline_num_tab_enter"
398			msg=$(
399			  printf "$msg_group_members ($msg_separated_by_commas)"
400			)
401			size=$( f_dialog_inputbox_size \
402	        		"$DIALOG_TITLE"     \
403	        		"$DIALOG_BACKTITLE" \
404	        		"$msg"              \
405	        		"$_input"           \
406	        		"$hline"            )
407
408			eval $DIALOG \
409				--title \"\$DIALOG_TITLE\"         \
410				--backtitle \"\$DIALOG_BACKTITLE\" \
411				--hline \"\$hline\"                \
412				--ok-label \"\$msg_ok\"            \
413				--cancel-label \"\$msg_cancel\"    \
414				--inputbox \"\$msg\" $size         \
415				\"\$_input\"                       \
416				2> $DIALOG_TMPDIR/dialog.inputbox.$$
417
418			retval=$?
419			_group_members=$( f_dialog_inputstr )
420
421			# Return to previous menu if user has either
422			#     pressed ESC or chosen Cancel/No
423			[ $retval -eq $SUCCESS ] || continue
424
425			_input="$_group_members"
426			;;
427		esac
428	done
429
430	group_members="$_input"
431	save_flag=1
432	f_dprintf "group_members: [$cur_group_members]->[$group_members]"
433
434	return $SUCCESS
435}
436
437fi # ! $_USERMGMT_GROUP_INPUT_SUBR
438