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