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