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