xref: /src/usr.sbin/bsdconfig/usermgmt/share/group_input.subr (revision 15752fa8582f3f77b0504f977b08378b93c4c8a7)
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	local msg="$( printf "$msg_group" )"
115	local hline="$hline_alnum_tab_enter"
116
117	#
118	# Loop until the user provides taint-free/valid input
119	#
120	local size retval _name="$1" _input="$1"
121	while :; do
122		size=$( f_dialog_inputbox_size \
123		        	"$DIALOG_TITLE"     \
124		        	"$DIALOG_BACKTITLE" \
125		        	"$msg"              \
126		        	"$_input"           \
127		        	"$hline"            )
128
129		local dialog_inputbox
130		dialog_inputbox=$( eval $DIALOG \
131			--title \"\$DIALOG_TITLE\"         \
132			--backtitle \"\$DIALOG_BACKTITLE\" \
133			--hline \"\$hline\"                \
134			--ok-label \"\$msg_ok\"            \
135			--cancel-label \"\$msg_cancel\"    \
136			--inputbox \"\$msg\" $size         \
137			\"\$_input\"                       \
138			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
139		)
140
141		retval=$?
142		setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
143		_input=$( f_dialog_inputstr )
144
145		# Return if user has either pressed ESC or chosen Cancel/No
146		[ $retval -eq $SUCCESS ] || return $retval
147
148		# Check for no-change
149		[ "$_input" = "$_name" ] && return $SUCCESS
150
151		# Check for reversion
152		if [ "$_input" = "$cur_group_name" ]; then
153			group_name="$cur_group_name"
154			return $SUCCESS
155		fi
156
157		# Check for NULL entry
158		if [ ! "$_input" ]; then
159			f_show_msg "$msg_group_is_empty"
160			continue
161		fi
162
163		# Check for invalid entry
164		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
165			f_show_msg "$msg_group_must_start_with_letter"
166			continue
167		fi
168
169		# Check for duplicate entry
170		if f_quietly pw groupshow -n "$_input"; then
171			f_show_msg "$msg_group_already_used" "$_input"
172			continue
173		fi
174
175		group_name="$_input"
176		break
177	done
178	save_flag=1
179
180	f_dprintf "group_name: [$cur_group_name]->[$group_name]"
181
182	return $SUCCESS
183}
184
185# f_dialog_input_group_password
186#
187# Prompt the user to enter a password (twice).
188#
189f_dialog_input_group_password()
190{
191	local hline="$hline_alnum_punc_tab_enter"
192	local msg size rmsg rsize
193
194	msg=$( printf "$msg_group_password" )
195	size=$( f_dialog_inputbox_size \
196	        	"$DIALOG_TITLE"     \
197	        	"$DIALOG_BACKTITLE" \
198	        	"$msg"              \
199	        	""                  \
200	        	"$hline"            )
201
202	rmsg=$( printf "$msg_reenter_group_password" )
203	rsize=$( f_dialog_inputbox_size \
204	        	"$DIALOG_TITLE"     \
205	        	"$DIALOG_BACKTITLE" \
206	        	"$rmsg"             \
207	        	""                  \
208	        	"$hline"            )
209
210	#
211	# Loop until the user provides taint-free/valid input
212	#
213	local retval _password1 _password2
214	while :; do
215		local dialog_inputbox
216		dialog_inputbox=$( eval $DIALOG \
217			--title \"\$DIALOG_TITLE\"         \
218			--backtitle \"\$DIALOG_BACKTITLE\" \
219			--hline \"\$hline\"                \
220			--ok-label \"\$msg_ok\"            \
221			--cancel-label \"\$msg_cancel\"    \
222			--insecure                         \
223			--passwordbox \"\$msg\" $size      \
224			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
225		)
226
227		retval=$?
228		setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
229		_password1=$( f_dialog_inputstr )
230
231		# Return if user has either pressed ESC or chosen Cancel/No
232		[ $retval -eq $SUCCESS ] || return $retval
233
234		dialog_inputbox=$( eval $DIALOG \
235			--title \"\$DIALOG_TITLE\"         \
236			--backtitle \"\$DIALOG_BACKTITLE\" \
237			--hline \"\$hline\"                \
238			--ok-label \"\$msg_ok\"            \
239			--cancel-label \"\$msg_cancel\"    \
240			--insecure                         \
241			--passwordbox \"\$rmsg\" $rsize    \
242			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
243		)
244
245		retval=$?
246		setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
247		_password2=$( f_dialog_inputstr )
248
249		# Return if user has either pressed ESC or chosen Cancel/No
250		[ $retval -eq $SUCCESS ] || return $retval
251
252		# Check for password mismatch
253		if [ "$_password1" != "$_password2" ]; then
254			f_show_msg "$msg_group_passwords_do_not_match"
255			continue
256		fi
257
258		# Check for NULL entry
259		if [ ! "$_password1" ]; then
260			f_dialog_yesno \
261				"$msg_disable_password_auth_for_group" ||
262				continue
263			pw_group_password_disable=1
264		else
265			pw_group_password_disable=
266		fi
267
268		group_password="$_password1"
269		break
270	done
271	save_flag=1
272
273	f_dprintf "group_password: [$cur_group_password]->[$group_password]"
274
275	return $SUCCESS
276}
277
278# f_dialog_input_group_gid [$group_gid]
279#
280# Allow the user to enter a new GID for a given group. If the user does not
281# cancel or press ESC, the $group_gid variable will hold the newly-configured
282# value upon return.
283#
284f_dialog_input_group_gid()
285{
286	local msg size retval _input="$1"
287	local hline="$hline_num_tab_enter"
288
289	msg=$( printf "$msg_group_id_leave_empty_for_default" )
290	size=$( f_dialog_inputbox_size \
291	        	"$DIALOG_TITLE"     \
292	        	"$DIALOG_BACKTITLE" \
293	        	"$msg"              \
294	        	"$_input"           \
295	        	"$hline"            )
296
297	local dialog_inputbox
298	dialog_inputbox=$( eval $DIALOG \
299		--title \"\$DIALOG_TITLE\"         \
300		--backtitle \"\$DIALOG_BACKTITLE\" \
301		--hline \"\$hline\"                \
302		--ok-label \"\$msg_ok\"            \
303		--cancel-label \"\$msg_cancel\"    \
304		--inputbox \"\$msg\" $size         \
305		\"\$_input\"                       \
306		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
307	)
308
309	retval=$?
310	setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
311	_input=$( f_dialog_inputstr )
312
313	# Return if user has either pressed ESC or chosen Cancel/No
314	[ $retval -eq $SUCCESS ] || return $retval
315
316	group_gid="$_input"
317	save_flag=1
318
319	f_dprintf "group_gid: [$cur_group_gid]->[$group_gid]"
320
321	return $SUCCESS
322}
323
324# f_dialog_input_group_members [$group_members]
325#
326# Allow the user to modify a list of members for a given group. If the user does
327# not cancel or press ESC, the $group_members variable will hold the newly-
328# configured value upon return.
329#
330f_dialog_input_group_members()
331{
332	local menu_choice msg size retval _input="$1"
333	local hline="$hline_num_arrows_tab_enter"
334	local user
335	local menu_list
336	local all_users_valid
337	local _group_members
338	local checklist_users
339
340	menu_list="
341		'X' '$msg_continue'
342		'1' '$msg_select_group_members_from_list'
343		'2' '$msg_enter_group_members_manually'
344	" # END-QUOTE
345
346	local dialog_menu
347	while :; do
348		msg="$msg_group_members:"
349		menu_size=$( eval f_dialog_menu_size \
350				\"\$DIALOG_TITLE\"     \
351				\"\$DIALOG_BACKTITLE\" \
352				\"\$msg\"              \
353				\"\$hline\"            \
354				$menu_list             )
355		dialog_menu=$( eval $DIALOG \
356			--title \"\$DIALOG_TITLE\"         \
357			--backtitle \"\$DIALOG_BACKTITLE\" \
358			--hline \"\$hline\"                \
359			--ok-label \"\$msg_ok\"            \
360			--cancel-label \"\$msg_cancel\"    \
361			--menu \"\$msg\" $menu_size        \
362			$menu_list                         \
363			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
364		)
365		retval=$?
366		setvar DIALOG_MENU_$$ "$dialog_menu"
367		menu_choice=$( f_dialog_menutag )
368		f_dprintf "retval=$retval menu_choice=[$menu_choice]"
369
370		# Return if user has either pressed ESC or chosen Cancel/No
371		[ $retval -eq $SUCCESS ] || return $retval
372
373		case "$menu_choice" in
374		X) # Exit
375			break ;;
376		1) # Select Group Members from a list
377			user_list=$( pw usershow -a | awk -F: '
378				!/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' )
379			checklist_users=
380			for user in $user_list; do
381				checklist_users="$checklist_users $user \"\""
382				if echo "$_input" | grep -q "\<$user\>"; then
383					checklist_users="$checklist_users on"
384				else
385					checklist_users="$checklist_users off"
386				fi
387			done
388
389			size=$( eval f_dialog_radiolist_size \
390			        	\"\$DIALOG_TITLE\"     \
391			        	\"\$DIALOG_BACKTITLE\" \
392			        	\"\"                   \
393			        	\"\$hline\"            \
394			        	$checklist_users       )
395			local dialog_inputbox
396			dialog_inputbox=$( eval $DIALOG \
397				--title \"\$DIALOG_TITLE\"         \
398				--backtitle \"\$DIALOG_BACKTITLE\" \
399				--separate-output                  \
400				--hline \"\$hline\"                \
401				--ok-label \"\$msg_ok\"            \
402				--cancel-label \"\$msg_cancel\"    \
403				--checklist \"\$msg\" $size        \
404				$checklist_users                   \
405				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
406			)
407			retval=$?
408			setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
409			_group_members=$( f_dialog_inputstr | tr '\n' ' ' |
410				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' )
411
412			# Return to previous menu if user has either
413			#     pressed ESC or chosen Cancel/No
414			[ $retval -eq $SUCCESS ] || continue
415
416			_input="$_group_members"
417			;;
418		2) # Enter Group Members manually
419			hline="$hline_num_tab_enter"
420			msg=$(
421			  printf "$msg_group_members ($msg_separated_by_commas)"
422			)
423			size=$( f_dialog_inputbox_size \
424	        		"$DIALOG_TITLE"     \
425	        		"$DIALOG_BACKTITLE" \
426	        		"$msg"              \
427	        		"$_input"           \
428	        		"$hline"            )
429
430			local dialog_inputbox
431			dialog_inputbox=$( eval $DIALOG \
432				--title \"\$DIALOG_TITLE\"         \
433				--backtitle \"\$DIALOG_BACKTITLE\" \
434				--hline \"\$hline\"                \
435				--ok-label \"\$msg_ok\"            \
436				--cancel-label \"\$msg_cancel\"    \
437				--inputbox \"\$msg\" $size         \
438				\"\$_input\"                       \
439				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
440			)
441
442			retval=$?
443			setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
444			_group_members=$( f_dialog_inputstr )
445
446			# Return to previous menu if user has either
447			#     pressed ESC or chosen Cancel/No
448			[ $retval -eq $SUCCESS ] || continue
449
450			_input="$_group_members"
451			;;
452		esac
453	done
454
455	group_members="$_input"
456	save_flag=1
457	f_dprintf "group_members: [$cur_group_members]->[$group_members]"
458
459	return $SUCCESS
460}
461
462fi # ! $_USERMGMT_GROUP_INPUT_SUBR
463