group_input.subr revision 245437
1238438Sdteskeif [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
2238438Sdteske#
3238438Sdteske# Copyright (c) 2012 Ron McDowell
4238438Sdteske# Copyright (c) 2012 Devin Teske
5238438Sdteske# All rights reserved.
6238438Sdteske#
7238438Sdteske# Redistribution and use in source and binary forms, with or without
8238438Sdteske# modification, are permitted provided that the following conditions
9238438Sdteske# are met:
10238438Sdteske# 1. Redistributions of source code must retain the above copyright
11238438Sdteske#    notice, this list of conditions and the following disclaimer.
12238438Sdteske# 2. Redistributions in binary form must reproduce the above copyright
13238438Sdteske#    notice, this list of conditions and the following disclaimer in the
14238438Sdteske#    documentation and/or other materials provided with the distribution.
15238438Sdteske#
16238438Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17238438Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18238438Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19238438Sdteske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20238438Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21238438Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22238438Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23238438Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24238438Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25238438Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26238438Sdteske# SUCH DAMAGE.
27238438Sdteske#
28238438Sdteske# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr 245437 2013-01-14 21:03:34Z dteske $
29238438Sdteske#
30238438Sdteske############################################################ INCLUDES
31238438Sdteske
32240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig"
33240684Sdteske. $BSDCFG_SHARE/common.subr || exit 1
34244675Sdteskef_dprintf "%s: loading includes..." usermgmt/group_input.subr
35240684Sdteskef_include $BSDCFG_SHARE/dialog.subr
36240684Sdteskef_include $BSDCFG_SHARE/strings.subr
37240684Sdteske
38240684SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
39238438Sdteskef_include_lang $BSDCFG_LIBE/include/messages.subr
40238438Sdteskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
41238438Sdteske
42238438Sdteske############################################################ FUNCTIONS
43238438Sdteske
44238438Sdteske# f_input_group $group
45238438Sdteske#
46238438Sdteske# Given $group name or id, create the environment variables group_name,
47238438Sdteske# group_gid, and group_members (and group_password is reset to NULL).
48238438Sdteske#
49238438Sdteskef_input_group()
50238438Sdteske{
51238438Sdteske	eval $( pw groupshow "$1" | awk -F: '
52238438Sdteske	{
53238438Sdteske		printf "group_name='\'%s\''\n", $1
54238438Sdteske		printf "group_password=\n"
55238438Sdteske		printf "group_gid='\'%s\''\n", $3
56238438Sdteske		printf "group_members='\'%s\''\n", $4
57238438Sdteske		exit
58238438Sdteske	}' )
59238438Sdteske}
60238438Sdteske
61238438Sdteske# f_dialog_menu_group_list
62238438Sdteske#
63238438Sdteske# Allows the user to select a group from a list.
64238438Sdteske#
65238438Sdteskef_dialog_menu_group_list()
66238438Sdteske{
67238438Sdteske	local menu_list size
68238438Sdteske	local hline="$hline_alnum_punc_tab_enter"
69238438Sdteske
70238438Sdteske	menu_list="
71238438Sdteske		'X $msg_exit' ''
72238438Sdteske	" # END-QUOTE
73238438Sdteske
74238438Sdteske	# Add groups from group(5)
75238438Sdteske	menu_list="$menu_list $( pw groupshow -a | awk -F: '
76238438Sdteske		!/^[[:space:]]*(#|$)/ {
77238438Sdteske			printf "'\'%s\'\ \'%s\''\n", $1, $1
78238438Sdteske		}'
79238438Sdteske	)"
80238438Sdteske
81238438Sdteske	size=$( eval f_dialog_menu_size \
82238438Sdteske	        	\"\$DIALOG_TITLE\"     \
83238438Sdteske	        	\"\$DIALOG_BACKTITLE\" \
84238438Sdteske	        	\"\"                   \
85238438Sdteske	        	\"\$hline\"            \
86238438Sdteske	        	$menu_list             )
87238438Sdteske
88240768Sdteske	local dialog_menu
89240768Sdteske	dialog_menu=$( eval $DIALOG \
90238438Sdteske		--clear --title \"\$DIALOG_TITLE\" \
91238438Sdteske		--backtitle \"\$DIALOG_BACKTITLE\" \
92238438Sdteske		--hline \"\$hline\"                \
93238438Sdteske		--ok-label \"\$msg_ok\"            \
94238438Sdteske		--cancel-label \"\$msg_cancel\"    \
95238438Sdteske		--menu \"\" $size $menu_list       \
96240768Sdteske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
97240768Sdteske	)
98240768Sdteske	local retval=$?
99240768Sdteske	setvar DIALOG_MENU_$$ "$dialog_menu"
100240768Sdteske	return $retval
101238438Sdteske}
102238438Sdteske
103238438Sdteske# f_dialog_input_group_name [$group_name]
104238438Sdteske#
105238438Sdteske# Allows the user to enter a new groupname for a given group. If the user does
106238438Sdteske# not cancel or press ESC, the $group_name variable will hold the
107238438Sdteske# newly-configured value upon return.
108238438Sdteske#
109238438Sdteske# If $cur_group_name is defined, the user can enter that and by-pass error-
110238438Sdteske# checking (allowing the user to "revert" to an old value without, for example,
111238438Sdteske# being told that the groupname already exists).
112238438Sdteske#
113238438Sdteskef_dialog_input_group_name()
114238438Sdteske{
115238438Sdteske	#
116238438Sdteske	# Loop until the user provides taint-free/valid input
117238438Sdteske	#
118244548Sdteske	local _name="$1" _input="$1"
119238438Sdteske	while :; do
120238438Sdteske
121238438Sdteske		# Return if user has either pressed ESC or chosen Cancel/No
122244548Sdteske		_input=$( f_dialog_input "$msg_group" "$_input" \
123244548Sdteske		                         "$hline_alnum_tab_enter"
124244548Sdteske		        ) || return
125238438Sdteske
126238438Sdteske		# Check for no-change
127238438Sdteske		[ "$_input" = "$_name" ] && return $SUCCESS
128238438Sdteske
129238438Sdteske		# Check for reversion
130238438Sdteske		if [ "$_input" = "$cur_group_name" ]; then
131238438Sdteske			group_name="$cur_group_name"
132238438Sdteske			return $SUCCESS
133238438Sdteske		fi
134238438Sdteske
135238438Sdteske		# Check for NULL entry
136238438Sdteske		if [ ! "$_input" ]; then
137245437Sdteske			f_dialog_msgbox "$msg_group_is_empty"
138238438Sdteske			continue
139238438Sdteske		fi
140238438Sdteske
141238438Sdteske		# Check for invalid entry
142238438Sdteske		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
143245437Sdteske			f_dialog_msgbox "$msg_group_must_start_with_letter"
144238438Sdteske			continue
145238438Sdteske		fi
146238438Sdteske
147238438Sdteske		# Check for duplicate entry
148238438Sdteske		if f_quietly pw groupshow -n "$_input"; then
149238438Sdteske			f_show_msg "$msg_group_already_used" "$_input"
150238438Sdteske			continue
151238438Sdteske		fi
152238438Sdteske
153238438Sdteske		group_name="$_input"
154238438Sdteske		break
155238438Sdteske	done
156238438Sdteske	save_flag=1
157238438Sdteske
158244550Sdteske	f_dprintf "group_name: [%s]->[%s]" "$cur_group_name" "$group_name"
159238438Sdteske
160238438Sdteske	return $SUCCESS
161238438Sdteske}
162238438Sdteske
163238438Sdteske# f_dialog_input_group_password
164238438Sdteske#
165238438Sdteske# Prompt the user to enter a password (twice).
166238438Sdteske#
167238438Sdteskef_dialog_input_group_password()
168238438Sdteske{
169238438Sdteske	local hline="$hline_alnum_punc_tab_enter"
170238438Sdteske	local msg size rmsg rsize
171238438Sdteske
172238438Sdteske	msg=$( printf "$msg_group_password" )
173238438Sdteske	size=$( f_dialog_inputbox_size \
174238438Sdteske	        	"$DIALOG_TITLE"     \
175238438Sdteske	        	"$DIALOG_BACKTITLE" \
176238438Sdteske	        	"$msg"              \
177238438Sdteske	        	""                  \
178238438Sdteske	        	"$hline"            )
179238438Sdteske
180238438Sdteske	rmsg=$( printf "$msg_reenter_group_password" )
181238438Sdteske	rsize=$( f_dialog_inputbox_size \
182238438Sdteske	        	"$DIALOG_TITLE"     \
183238438Sdteske	        	"$DIALOG_BACKTITLE" \
184238438Sdteske	        	"$rmsg"             \
185238438Sdteske	        	""                  \
186238438Sdteske	        	"$hline"            )
187238438Sdteske
188238438Sdteske	#
189238438Sdteske	# Loop until the user provides taint-free/valid input
190238438Sdteske	#
191238438Sdteske	local retval _password1 _password2
192238438Sdteske	while :; do
193240768Sdteske		local dialog_inputbox
194240768Sdteske		dialog_inputbox=$( eval $DIALOG \
195238438Sdteske			--title \"\$DIALOG_TITLE\"         \
196238438Sdteske			--backtitle \"\$DIALOG_BACKTITLE\" \
197238438Sdteske			--hline \"\$hline\"                \
198238438Sdteske			--ok-label \"\$msg_ok\"            \
199238438Sdteske			--cancel-label \"\$msg_cancel\"    \
200238438Sdteske			--insecure                         \
201238438Sdteske			--passwordbox \"\$msg\" $size      \
202240768Sdteske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
203240768Sdteske		)
204238438Sdteske
205238438Sdteske		retval=$?
206240768Sdteske		setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
207238438Sdteske		_password1=$( f_dialog_inputstr )
208238438Sdteske
209238438Sdteske		# Return if user has either pressed ESC or chosen Cancel/No
210238438Sdteske		[ $retval -eq $SUCCESS ] || return $retval
211238438Sdteske
212240768Sdteske		dialog_inputbox=$( eval $DIALOG \
213238438Sdteske			--title \"\$DIALOG_TITLE\"         \
214238438Sdteske			--backtitle \"\$DIALOG_BACKTITLE\" \
215238438Sdteske			--hline \"\$hline\"                \
216238438Sdteske			--ok-label \"\$msg_ok\"            \
217238438Sdteske			--cancel-label \"\$msg_cancel\"    \
218238438Sdteske			--insecure                         \
219238438Sdteske			--passwordbox \"\$rmsg\" $rsize    \
220240768Sdteske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
221240768Sdteske		)
222238438Sdteske
223238438Sdteske		retval=$?
224240768Sdteske		setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
225238438Sdteske		_password2=$( f_dialog_inputstr )
226238438Sdteske
227238438Sdteske		# Return if user has either pressed ESC or chosen Cancel/No
228238438Sdteske		[ $retval -eq $SUCCESS ] || return $retval
229238438Sdteske
230238438Sdteske		# Check for password mismatch
231238438Sdteske		if [ "$_password1" != "$_password2" ]; then
232245437Sdteske			f_dialog_msgbox "$msg_group_passwords_do_not_match"
233238438Sdteske			continue
234238438Sdteske		fi
235238438Sdteske
236238438Sdteske		# Check for NULL entry
237238438Sdteske		if [ ! "$_password1" ]; then
238238438Sdteske			f_dialog_yesno \
239238438Sdteske				"$msg_disable_password_auth_for_group" ||
240238438Sdteske				continue
241238438Sdteske			pw_group_password_disable=1
242238438Sdteske		else
243238438Sdteske			pw_group_password_disable=
244238438Sdteske		fi
245238438Sdteske
246238438Sdteske		group_password="$_password1"
247238438Sdteske		break
248238438Sdteske	done
249238438Sdteske	save_flag=1
250238438Sdteske
251244550Sdteske	f_dprintf "group_password: [%s]->[%s]" \
252244550Sdteske	          "$cur_group_password" "$group_password"
253238438Sdteske
254238438Sdteske	return $SUCCESS
255238438Sdteske}
256238438Sdteske
257238438Sdteske# f_dialog_input_group_gid [$group_gid]
258238438Sdteske#
259238438Sdteske# Allow the user to enter a new GID for a given group. If the user does not
260238438Sdteske# cancel or press ESC, the $group_gid variable will hold the newly-configured
261238438Sdteske# value upon return.
262238438Sdteske#
263238438Sdteskef_dialog_input_group_gid()
264238438Sdteske{
265244548Sdteske	local _input="$1"
266238438Sdteske
267238438Sdteske	# Return if user has either pressed ESC or chosen Cancel/No
268244548Sdteske	_input=$( f_dialog_input "$msg_group_id_leave_empty_for_default" \
269244548Sdteske	                         "$_input" "$hline_num_tab_enter"
270244548Sdteske	        ) || return
271238438Sdteske
272238438Sdteske	group_gid="$_input"
273238438Sdteske	save_flag=1
274238438Sdteske
275244550Sdteske	f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid"
276238438Sdteske
277238438Sdteske	return $SUCCESS
278238438Sdteske}
279238438Sdteske
280238438Sdteske# f_dialog_input_group_members [$group_members]
281238438Sdteske#
282238438Sdteske# Allow the user to modify a list of members for a given group. If the user does
283238438Sdteske# not cancel or press ESC, the $group_members variable will hold the newly-
284238438Sdteske# configured value upon return.
285238438Sdteske#
286238438Sdteskef_dialog_input_group_members()
287238438Sdteske{
288238438Sdteske	local menu_choice msg size retval _input="$1"
289238438Sdteske	local hline="$hline_num_arrows_tab_enter"
290238438Sdteske	local user 
291238438Sdteske	local menu_list
292238438Sdteske	local all_users_valid
293238438Sdteske	local _group_members
294238438Sdteske	local checklist_users
295238438Sdteske
296238438Sdteske	menu_list="
297238438Sdteske		'X' '$msg_continue'
298238438Sdteske		'1' '$msg_select_group_members_from_list'
299238438Sdteske		'2' '$msg_enter_group_members_manually'
300238438Sdteske	" # END-QUOTE
301238438Sdteske
302240768Sdteske	local dialog_menu
303238438Sdteske	while :; do
304238438Sdteske		msg="$msg_group_members:"
305238438Sdteske		menu_size=$( eval f_dialog_menu_size \
306238438Sdteske				\"\$DIALOG_TITLE\"     \
307238438Sdteske				\"\$DIALOG_BACKTITLE\" \
308238438Sdteske				\"\$msg\"              \
309238438Sdteske				\"\$hline\"            \
310238438Sdteske				$menu_list             )
311240768Sdteske		dialog_menu=$( eval $DIALOG \
312238438Sdteske			--title \"\$DIALOG_TITLE\"         \
313238438Sdteske			--backtitle \"\$DIALOG_BACKTITLE\" \
314238438Sdteske			--hline \"\$hline\"                \
315238438Sdteske			--ok-label \"\$msg_ok\"            \
316238438Sdteske			--cancel-label \"\$msg_cancel\"    \
317238438Sdteske			--menu \"\$msg\" $menu_size        \
318238438Sdteske			$menu_list                         \
319240768Sdteske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
320240768Sdteske		)
321238438Sdteske		retval=$?
322240768Sdteske		setvar DIALOG_MENU_$$ "$dialog_menu"
323238438Sdteske		menu_choice=$( f_dialog_menutag )
324244550Sdteske		f_dprintf "retval=%u menu_choice=[%s]" $retval "$menu_choice"
325238438Sdteske
326238438Sdteske		# Return if user has either pressed ESC or chosen Cancel/No
327238438Sdteske		[ $retval -eq $SUCCESS ] || return $retval
328238438Sdteske
329238438Sdteske		case "$menu_choice" in
330238438Sdteske		X) # Exit
331238438Sdteske			break ;;
332238438Sdteske		1) # Select Group Members from a list
333238438Sdteske			user_list=$( pw usershow -a | awk -F: '
334238438Sdteske				!/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' )
335238438Sdteske			checklist_users=
336238438Sdteske			for user in $user_list; do
337238438Sdteske				checklist_users="$checklist_users $user \"\""
338238438Sdteske				if echo "$_input" | grep -q "\<$user\>"; then
339238438Sdteske					checklist_users="$checklist_users on"
340238438Sdteske				else
341238438Sdteske					checklist_users="$checklist_users off"
342238438Sdteske				fi
343238438Sdteske			done
344238438Sdteske
345238438Sdteske			size=$( eval f_dialog_radiolist_size \
346238438Sdteske			        	\"\$DIALOG_TITLE\"     \
347238438Sdteske			        	\"\$DIALOG_BACKTITLE\" \
348238438Sdteske			        	\"\"                   \
349238438Sdteske			        	\"\$hline\"            \
350238438Sdteske			        	$checklist_users       )
351240768Sdteske			local dialog_inputbox
352240768Sdteske			dialog_inputbox=$( eval $DIALOG \
353238438Sdteske				--title \"\$DIALOG_TITLE\"         \
354238438Sdteske				--backtitle \"\$DIALOG_BACKTITLE\" \
355238438Sdteske				--separate-output                  \
356238438Sdteske				--hline \"\$hline\"                \
357238438Sdteske				--ok-label \"\$msg_ok\"            \
358238438Sdteske				--cancel-label \"\$msg_cancel\"    \
359238438Sdteske				--checklist \"\$msg\" $size        \
360238438Sdteske				$checklist_users                   \
361240768Sdteske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
362240768Sdteske			)
363238438Sdteske			retval=$?
364240768Sdteske			setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
365238438Sdteske			_group_members=$( f_dialog_inputstr | tr '\n' ' ' |
366238438Sdteske				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' )
367238438Sdteske
368238438Sdteske			# Return to previous menu if user has either
369238438Sdteske			#     pressed ESC or chosen Cancel/No
370238438Sdteske			[ $retval -eq $SUCCESS ] || continue
371238438Sdteske
372238438Sdteske			_input="$_group_members"
373238438Sdteske			;;
374238438Sdteske		2) # Enter Group Members manually
375244548Sdteske			msg="$msg_group_members ($msg_separated_by_commas)"
376238438Sdteske
377238438Sdteske			# Return to previous menu if user has either
378238438Sdteske			#     pressed ESC or chosen Cancel/No
379244548Sdteske			_group_members=$( f_dialog_input "$msg" "$_input" \
380244548Sdteske			                                 "$hline_num_tab_enter"
381244548Sdteske			                ) || continue
382238438Sdteske
383238438Sdteske			_input="$_group_members"
384238438Sdteske			;;
385238438Sdteske		esac
386238438Sdteske	done
387238438Sdteske
388238438Sdteske	group_members="$_input"
389238438Sdteske	save_flag=1
390244550Sdteske	f_dprintf "group_members: [%s]->[%s]" \
391244550Sdteske	          "$cur_group_members" "$group_members"
392238438Sdteske
393238438Sdteske	return $SUCCESS
394238438Sdteske}
395238438Sdteske
396244675Sdteske############################################################ MAIN
397244675Sdteske
398244675Sdteskef_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
399244675Sdteske
400238438Sdteskefi # ! $_USERMGMT_GROUP_INPUT_SUBR
401