group_input.subr revision 251547
1249259Sdimif [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
2249259Sdim#
3249259Sdim# Copyright (c) 2012 Ron McDowell
4249259Sdim# Copyright (c) 2012-2013 Devin Teske
5249259Sdim# All rights reserved.
6249259Sdim#
7249259Sdim# Redistribution and use in source and binary forms, with or without
8249259Sdim# modification, are permitted provided that the following conditions
9249259Sdim# are met:
10249259Sdim# 1. Redistributions of source code must retain the above copyright
11249259Sdim#    notice, this list of conditions and the following disclaimer.
12249259Sdim# 2. Redistributions in binary form must reproduce the above copyright
13249259Sdim#    notice, this list of conditions and the following disclaimer in the
14249259Sdim#    documentation and/or other materials provided with the distribution.
15249259Sdim#
16249259Sdim# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17249259Sdim# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18249259Sdim# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19249259Sdim# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20249259Sdim# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21249259Sdim# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22249259Sdim# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23249259Sdim# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24249259Sdim# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25249259Sdim# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26249259Sdim# SUCH DAMAGE.
27249259Sdim#
28249259Sdim# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr 251547 2013-06-08 18:23:41Z dteske $
29249259Sdim#
30249259Sdim############################################################ INCLUDES
31249259Sdim
32249259SdimBSDCFG_SHARE="/usr/share/bsdconfig"
33249259Sdim. $BSDCFG_SHARE/common.subr || exit 1
34249259Sdimf_dprintf "%s: loading includes..." usermgmt/group_input.subr
35249259Sdimf_include $BSDCFG_SHARE/dialog.subr
36249259Sdimf_include $BSDCFG_SHARE/strings.subr
37249259Sdim
38249259SdimBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
39249259Sdimf_include_lang $BSDCFG_LIBE/include/messages.subr
40249259Sdimf_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
41249259Sdim
42249259Sdim############################################################ FUNCTIONS
43249259Sdim
44249259Sdim# f_input_group $group
45249259Sdim#
46249259Sdim# Given $group name or id, create the environment variables group_name,
47249259Sdim# group_gid, and group_members (and group_password is reset to NULL).
48249259Sdim#
49249259Sdimf_input_group()
50249259Sdim{
51249259Sdim	eval $( pw groupshow "$1" | awk -F: '
52249259Sdim	{
53249259Sdim		printf "group_name='\'%s\''\n", $1
54249259Sdim		printf "group_password=\n"
55249259Sdim		printf "group_gid='\'%s\''\n", $3
56249259Sdim		printf "group_members='\'%s\''\n", $4
57249259Sdim		exit
58249259Sdim	}' )
59249259Sdim}
60249259Sdim
61249259Sdim# f_dialog_menu_group_list [$default]
62249259Sdim#
63249259Sdim# Allows the user to select a group from a list. Optionally, if present and
64249259Sdim# non-NULL, initially highlight $default group.
65249259Sdim#
66249259Sdimf_dialog_menu_group_list()
67249259Sdim{
68249259Sdim	local prompt=
69249259Sdim	local menu_list="
70249259Sdim		'X $msg_exit' ''
71249259Sdim	" # END-QUOTE
72249259Sdim	local defaultitem="$1"
73249259Sdim	local hline="$hline_alnum_punc_tab_enter"
74249259Sdim
75249259Sdim	# Add groups from group(5)
76249259Sdim	menu_list="$menu_list $( pw groupshow -a | awk -F: '
77249259Sdim		!/^[[:space:]]*(#|$)/ {
78249259Sdim			printf "'\'%s\'\ \'%s\''\n", $1, $1
79249259Sdim		}'
80249259Sdim	)"
81249259Sdim
82249259Sdim	local height width rows
83249259Sdim	eval f_dialog_menu_size height width rows \
84249259Sdim	                        \"\$DIALOG_TITLE\"     \
85249259Sdim	                        \"\$DIALOG_BACKTITLE\" \
86249259Sdim	                        \"\$prompt\"           \
87249259Sdim	                        \"\$hline\"            \
88249259Sdim	                        $menu_list
89249259Sdim
90249259Sdim	local menu_choice
91249259Sdim	menu_choice=$( eval $DIALOG \
92249259Sdim		--title \"\$DIALOG_TITLE\"         \
93249259Sdim		--backtitle \"\$DIALOG_BACKTITLE\" \
94249259Sdim		--hline \"\$hline\"                \
95249259Sdim		--ok-label \"\$msg_ok\"            \
96249259Sdim		--cancel-label \"\$msg_cancel\"    \
97249259Sdim		--default-item \"\$defaultitem\"   \
98249259Sdim		--menu \"\$prompt\"                \
99249259Sdim		$height $width $rows               \
100249259Sdim		$menu_list                         \
101249259Sdim		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
102249259Sdim	)
103249259Sdim	local retval=$?
104249259Sdim	f_dialog_menutag_store -s "$menu_choice"
105249259Sdim	return $retval
106249259Sdim}
107249259Sdim
108249259Sdim# f_dialog_input_group_name [$group_name]
109249259Sdim#
110249259Sdim# Allows the user to enter a new groupname for a given group. If the user does
111249259Sdim# not cancel or press ESC, the $group_name variable will hold the
112249259Sdim# newly-configured value upon return.
113249259Sdim#
114249259Sdim# If $cur_group_name is defined, the user can enter that and by-pass error-
115249259Sdim# checking (allowing the user to "revert" to an old value without, for example,
116249259Sdim# being told that the groupname already exists).
117249259Sdim#
118249259Sdimf_dialog_input_group_name()
119249259Sdim{
120249259Sdim	#
121249259Sdim	# Loop until the user provides taint-free/valid input
122249259Sdim	#
123249259Sdim	local _name="$1" _input="$1"
124249259Sdim	while :; do
125249259Sdim
126249259Sdim		# Return if user has either pressed ESC or chosen Cancel/No
127249259Sdim		f_dialog_input _input "$msg_group" "$_input" \
128249259Sdim		               "$hline_alnum_tab_enter" || return
129249259Sdim
130249259Sdim		# Check for no-change
131249259Sdim		[ "$_input" = "$_name" ] && return $SUCCESS
132249259Sdim
133249259Sdim		# Check for reversion
134249259Sdim		if [ "$_input" = "$cur_group_name" ]; then
135249259Sdim			group_name="$cur_group_name"
136249259Sdim			return $SUCCESS
137249259Sdim		fi
138249259Sdim
139249259Sdim		# Check for NULL entry
140249259Sdim		if [ ! "$_input" ]; then
141249259Sdim			f_dialog_msgbox "$msg_group_is_empty"
142249259Sdim			continue
143249259Sdim		fi
144249259Sdim
145249259Sdim		# Check for invalid entry
146249259Sdim		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
147249259Sdim			f_dialog_msgbox "$msg_group_must_start_with_letter"
148249259Sdim			continue
149249259Sdim		fi
150249259Sdim
151249259Sdim		# Check for duplicate entry
152249259Sdim		if f_quietly pw groupshow -n "$_input"; then
153249259Sdim			f_show_msg "$msg_group_already_used" "$_input"
154249259Sdim			continue
155249259Sdim		fi
156249259Sdim
157249259Sdim		group_name="$_input"
158249259Sdim		break
159249259Sdim	done
160249259Sdim	save_flag=1
161249259Sdim
162249259Sdim	f_dprintf "group_name: [%s]->[%s]" "$cur_group_name" "$group_name"
163249259Sdim
164249259Sdim	return $SUCCESS
165249259Sdim}
166249259Sdim
167249259Sdim# f_dialog_input_group_password
168249259Sdim#
169249259Sdim# Prompt the user to enter a password (twice).
170249259Sdim#
171249259Sdimf_dialog_input_group_password()
172249259Sdim{
173249259Sdim	local prompt1="$msg_group_password"
174249259Sdim	local prompt2="$msg_reenter_group_password"
175249259Sdim	local hline="$hline_alnum_punc_tab_enter"
176249259Sdim
177249259Sdim	local height1 width1
178249259Sdim	f_dialog_inputbox_size height1 width1 \
179249259Sdim	        	"$DIALOG_TITLE"     \
180249259Sdim	        	"$DIALOG_BACKTITLE" \
181249259Sdim	        	"$prompt1"          \
182249259Sdim	        	""                  \
183249259Sdim	        	"$hline"
184249259Sdim
185249259Sdim	local height2 width2
186249259Sdim	f_dialog_inputbox_size height2 width2 \
187249259Sdim	        	"$DIALOG_TITLE"     \
188249259Sdim	        	"$DIALOG_BACKTITLE" \
189249259Sdim	        	"$prompt2"          \
190249259Sdim	        	""                  \
191249259Sdim	        	"$hline"
192249259Sdim
193249259Sdim	#
194249259Sdim	# Loop until the user provides taint-free/valid input
195249259Sdim	#
196249259Sdim	local retval _password1 _password2
197249259Sdim	while :; do
198249259Sdim		_password1=$( $DIALOG \
199249259Sdim			--title "$DIALOG_TITLE"         \
200249259Sdim			--backtitle "$DIALOG_BACKTITLE" \
201249259Sdim			--hline "$hline"                \
202249259Sdim			--ok-label "$msg_ok"            \
203249259Sdim			--cancel-label "$msg_cancel"    \
204249259Sdim			--insecure                      \
205249259Sdim			--passwordbox "$prompt1"        \
206249259Sdim			$height1 $width1                \
207249259Sdim			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
208249259Sdim		)
209249259Sdim		retval=$?
210249259Sdim		debug= f_dialog_line_sanitize _password1
211249259Sdim
212249259Sdim		# Return if user has either pressed ESC or chosen Cancel/No
213249259Sdim		[ $retval -eq $SUCCESS ] || return $retval
214249259Sdim
215249259Sdim		_password2=$( $DIALOG \
216249259Sdim			--title "$DIALOG_TITLE"         \
217249259Sdim			--backtitle "$DIALOG_BACKTITLE" \
218249259Sdim			--hline "$hline"                \
219249259Sdim			--ok-label "$msg_ok"            \
220249259Sdim			--cancel-label "$msg_cancel"    \
221249259Sdim			--insecure                      \
222249259Sdim			--passwordbox "$prompt2"        \
223249259Sdim			$height2 $width2                \
224249259Sdim			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
225249259Sdim		)
226249259Sdim		retval=$?
227249259Sdim		debug= f_dialog_line_sanitize _password2
228249259Sdim
229249259Sdim		# Return if user has either pressed ESC or chosen Cancel/No
230249259Sdim		[ $retval -eq $SUCCESS ] || return $retval
231249259Sdim
232249259Sdim		# Check for password mismatch
233249259Sdim		if [ "$_password1" != "$_password2" ]; then
234249259Sdim			f_dialog_msgbox "$msg_group_passwords_do_not_match"
235249259Sdim			continue
236249259Sdim		fi
237249259Sdim
238249259Sdim		# Check for NULL entry
239249259Sdim		if [ ! "$_password1" ]; then
240249259Sdim			f_dialog_yesno "$msg_disable_password_auth_for_group"
241249259Sdim			local retval=$?
242249259Sdim			if [ $retval -eq 255 ]; then # ESC was pressed
243249259Sdim				return $retval
244249259Sdim			elif [ $retval -eq $SUCCESS ]; then
245249259Sdim				pw_group_password_disable=1
246249259Sdim			else
247249259Sdim				continue # back to password prompt
248249259Sdim			fi
249249259Sdim		else
250249259Sdim			pw_group_password_disable=
251249259Sdim		fi
252249259Sdim
253249259Sdim		group_password="$_password1"
254249259Sdim		break
255249259Sdim	done
256249259Sdim	save_flag=1
257249259Sdim
258249259Sdim	f_dprintf "group_password: [%s]->[%s]" \
259249259Sdim	          "$cur_group_password" "$group_password"
260249259Sdim
261249259Sdim	return $SUCCESS
262249259Sdim}
263249259Sdim
264249259Sdim# f_dialog_input_group_gid [$group_gid]
265249259Sdim#
266249259Sdim# Allow the user to enter a new GID for a given group. If the user does not
267249259Sdim# cancel or press ESC, the $group_gid variable will hold the newly-configured
268249259Sdim# value upon return.
269249259Sdim#
270249259Sdimf_dialog_input_group_gid()
271249259Sdim{
272249259Sdim	local _input="$1"
273249259Sdim
274249259Sdim	# Return if user has either pressed ESC or chosen Cancel/No
275249259Sdim	f_dialog_input _input "$msg_group_id_leave_empty_for_default" \
276249259Sdim	               "$_input" "$hline_num_tab_enter" || return
277249259Sdim
278249259Sdim	group_gid="$_input"
279249259Sdim	save_flag=1
280249259Sdim
281249259Sdim	f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid"
282249259Sdim
283249259Sdim	return $SUCCESS
284249259Sdim}
285249259Sdim
286249259Sdim# f_dialog_input_group_members [$group_members]
287249259Sdim#
288249259Sdim# Allow the user to modify a list of members for a given group. If the user
289249259Sdim# does not cancel or press ESC, the $group_members variable will hold the
290249259Sdim# newly-configured value upon return.
291249259Sdim#
292249259Sdimf_dialog_input_group_members()
293249259Sdim{
294249259Sdim	local _input="$1"
295249259Sdim	local prompt="$msg_group_members:"
296249259Sdim	local menu_list="
297249259Sdim		'X' '$msg_continue'
298249259Sdim		'1' '$msg_select_group_members_from_list'
299249259Sdim		'2' '$msg_enter_group_members_manually'
300249259Sdim	" # END-QUOTE
301249259Sdim	local defaultitem=
302249259Sdim	local hline="$hline_num_arrows_tab_enter"
303249259Sdim
304249259Sdim	local mheight mwidth mrows
305249259Sdim	eval f_dialog_menu_size mheight mwidth mrows \
306249259Sdim	                        \"\$DIALOG_TITLE\"     \
307249259Sdim	                        \"\$DIALOG_BACKTITLE\" \
308249259Sdim	                        \"\$prompt\"           \
309249259Sdim	                        \"\$hline\"            \
310249259Sdim	                        $menu_list
311249259Sdim
312249259Sdim	local menu_choice retval
313249259Sdim	while :; do
314249259Sdim		menu_choice=$( eval $DIALOG \
315249259Sdim			--title \"\$DIALOG_TITLE\"         \
316249259Sdim			--backtitle \"\$DIALOG_BACKTITLE\" \
317249259Sdim			--hline \"\$hline\"                \
318249259Sdim			--ok-label \"\$msg_ok\"            \
319249259Sdim			--cancel-label \"\$msg_cancel\"    \
320249259Sdim			--default-item \"\$defaultitem\"   \
321249259Sdim			--menu \"\$prompt\"                \
322249259Sdim			$mheight $mwidth $mrows            \
323249259Sdim			$menu_list                         \
324249259Sdim			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
325249259Sdim		)
326249259Sdim		retval=$?
327249259Sdim		f_dialog_data_sanitize menu_choice
328249259Sdim		defaultitem="$menu_choice"
329249259Sdim		f_dprintf "retval=%u menu_choice=[%s]" $retval "$menu_choice"
330249259Sdim
331249259Sdim		# Return if user has either pressed ESC or chosen Cancel/No
332249259Sdim		[ $retval -eq $SUCCESS ] || return $retval
333249259Sdim
334249259Sdim		local _group_members
335249259Sdim		case "$menu_choice" in
336249259Sdim		X) # Exit
337249259Sdim			break ;;
338249259Sdim		1) # Select Group Members from a list
339249259Sdim			local user check_list=
340249259Sdim			for user in $( pw usershow -a |
341249259Sdim				awk -F: '!/^[[:space:]]*(#|$)/{print $1}'
342249259Sdim			); do
343249259Sdim				# Format of a checklist entry: tag item status
344249259Sdim				if echo "$_input" | grep -q "\<$user\>"; then
345249259Sdim					check_list="$check_list $user '' on"
346249259Sdim				else
347249259Sdim					check_list="$check_list $user '' off"
348249259Sdim				fi
349249259Sdim			done
350249259Sdim
351249259Sdim			local cheight cwidth crows
352249259Sdim			eval f_dialog_checklist_size cheight cwidth crows \
353249259Sdim			                             \"\$DIALOG_TITLE\"     \
354249259Sdim			                             \"\$DIALOG_BACKTITLE\" \
355249259Sdim			                             \"\$prompt\"           \
356249259Sdim			                             \"\$hline\"            \
357249259Sdim			                             $check_list
358263508Sdim			_group_members=$( eval $DIALOG \
359263508Sdim				--title \"\$DIALOG_TITLE\"         \
360263508Sdim				--backtitle \"\$DIALOG_BACKTITLE\" \
361263508Sdim				--separate-output                  \
362263508Sdim				--hline \"\$hline\"                \
363249259Sdim				--ok-label \"\$msg_ok\"            \
364249259Sdim				--cancel-label \"\$msg_cancel\"    \
365249259Sdim				--checklist \"\$prompt\"           \
366249259Sdim				$cheight $cwidth $crows            \
367249259Sdim				$check_list                        \
368249259Sdim				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
369249259Sdim			) || continue
370249259Sdim				# Return to previous menu if user either
371249259Sdim				# pressed ESC or chose Cancel/No
372249259Sdim			f_dialog_data_sanitize _group_members
373
374			# Convert the newline separated list into a comma-
375			# separated one so that if the user switches over to
376			# manual editing, list reflects checklist selections
377			_group_members=$( echo "$_group_members" |
378				tr '\n' ' ' |
379				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//'
380			)
381
382			_input="$_group_members"
383			;;
384		2) # Enter Group Members manually
385			local p="$msg_group_members ($msg_separated_by_commas)"
386
387			f_dialog_input _group_members "$p" "$_input" \
388			               "$hline_num_tab_enter" || continue
389				# Return to previous menu if user either
390				# pressed ESC or chose Cancel/No
391
392			_input="$_group_members"
393			;;
394		esac
395	done
396
397	group_members="$_input"
398	save_flag=1
399	f_dprintf "group_members: [%s]->[%s]" \
400	          "$cur_group_members" "$group_members"
401
402	return $SUCCESS
403}
404
405############################################################ MAIN
406
407f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
408
409fi # ! $_USERMGMT_GROUP_INPUT_SUBR
410