xref: /freebsd/usr.sbin/bsdconfig/usermgmt/share/group_input.subr (revision c6ec7d31830ab1c80edae95ad5e4b9dba10c47ac)
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: [%s]->[%s]" "$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: [%s]->[%s]" \
251	          "$cur_group_password" "$group_password"
252
253	return $SUCCESS
254}
255
256# f_dialog_input_group_gid [$group_gid]
257#
258# Allow the user to enter a new GID for a given group. If the user does not
259# cancel or press ESC, the $group_gid variable will hold the newly-configured
260# value upon return.
261#
262f_dialog_input_group_gid()
263{
264	local _input="$1"
265
266	# Return if user has either pressed ESC or chosen Cancel/No
267	_input=$( f_dialog_input "$msg_group_id_leave_empty_for_default" \
268	                         "$_input" "$hline_num_tab_enter"
269	        ) || return
270
271	group_gid="$_input"
272	save_flag=1
273
274	f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid"
275
276	return $SUCCESS
277}
278
279# f_dialog_input_group_members [$group_members]
280#
281# Allow the user to modify a list of members for a given group. If the user does
282# not cancel or press ESC, the $group_members variable will hold the newly-
283# configured value upon return.
284#
285f_dialog_input_group_members()
286{
287	local menu_choice msg size retval _input="$1"
288	local hline="$hline_num_arrows_tab_enter"
289	local user
290	local menu_list
291	local all_users_valid
292	local _group_members
293	local checklist_users
294
295	menu_list="
296		'X' '$msg_continue'
297		'1' '$msg_select_group_members_from_list'
298		'2' '$msg_enter_group_members_manually'
299	" # END-QUOTE
300
301	local dialog_menu
302	while :; do
303		msg="$msg_group_members:"
304		menu_size=$( eval f_dialog_menu_size \
305				\"\$DIALOG_TITLE\"     \
306				\"\$DIALOG_BACKTITLE\" \
307				\"\$msg\"              \
308				\"\$hline\"            \
309				$menu_list             )
310		dialog_menu=$( eval $DIALOG \
311			--title \"\$DIALOG_TITLE\"         \
312			--backtitle \"\$DIALOG_BACKTITLE\" \
313			--hline \"\$hline\"                \
314			--ok-label \"\$msg_ok\"            \
315			--cancel-label \"\$msg_cancel\"    \
316			--menu \"\$msg\" $menu_size        \
317			$menu_list                         \
318			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
319		)
320		retval=$?
321		setvar DIALOG_MENU_$$ "$dialog_menu"
322		menu_choice=$( f_dialog_menutag )
323		f_dprintf "retval=%u menu_choice=[%s]" $retval "$menu_choice"
324
325		# Return if user has either pressed ESC or chosen Cancel/No
326		[ $retval -eq $SUCCESS ] || return $retval
327
328		case "$menu_choice" in
329		X) # Exit
330			break ;;
331		1) # Select Group Members from a list
332			user_list=$( pw usershow -a | awk -F: '
333				!/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' )
334			checklist_users=
335			for user in $user_list; do
336				checklist_users="$checklist_users $user \"\""
337				if echo "$_input" | grep -q "\<$user\>"; then
338					checklist_users="$checklist_users on"
339				else
340					checklist_users="$checklist_users off"
341				fi
342			done
343
344			size=$( eval f_dialog_radiolist_size \
345			        	\"\$DIALOG_TITLE\"     \
346			        	\"\$DIALOG_BACKTITLE\" \
347			        	\"\"                   \
348			        	\"\$hline\"            \
349			        	$checklist_users       )
350			local dialog_inputbox
351			dialog_inputbox=$( eval $DIALOG \
352				--title \"\$DIALOG_TITLE\"         \
353				--backtitle \"\$DIALOG_BACKTITLE\" \
354				--separate-output                  \
355				--hline \"\$hline\"                \
356				--ok-label \"\$msg_ok\"            \
357				--cancel-label \"\$msg_cancel\"    \
358				--checklist \"\$msg\" $size        \
359				$checklist_users                   \
360				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
361			)
362			retval=$?
363			setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
364			_group_members=$( f_dialog_inputstr | tr '\n' ' ' |
365				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' )
366
367			# Return to previous menu if user has either
368			#     pressed ESC or chosen Cancel/No
369			[ $retval -eq $SUCCESS ] || continue
370
371			_input="$_group_members"
372			;;
373		2) # Enter Group Members manually
374			msg="$msg_group_members ($msg_separated_by_commas)"
375
376			# Return to previous menu if user has either
377			#     pressed ESC or chosen Cancel/No
378			_group_members=$( f_dialog_input "$msg" "$_input" \
379			                                 "$hline_num_tab_enter"
380			                ) || continue
381
382			_input="$_group_members"
383			;;
384		esac
385	done
386
387	group_members="$_input"
388	save_flag=1
389	f_dprintf "group_members: [%s]->[%s]" \
390	          "$cur_group_members" "$group_members"
391
392	return $SUCCESS
393}
394
395fi # ! $_USERMGMT_GROUP_INPUT_SUBR
396