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