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