Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Mar 2014 20:44:20 +0000 (UTC)
From:      Devin Teske <dteske@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262904 - in head/usr.sbin/bsdconfig: share usermgmt usermgmt/include usermgmt/share
Message-ID:  <201403072044.s27KiKCb039707@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dteske
Date: Fri Mar  7 20:44:19 2014
New Revision: 262904
URL: http://svnweb.freebsd.org/changeset/base/262904

Log:
  Rewrite groupmgmt -- hooking it into the scripting system with dispatch
  commands groupAdd, groupDelete, and groupEdit. Getting rid of the awkward-
  to-use `groupinput' bolt-on which Ron and I talked about rewriting.

Added:
  head/usr.sbin/bsdconfig/usermgmt/share/group.subr   (contents, props changed)
Deleted:
  head/usr.sbin/bsdconfig/usermgmt/groupinput
Modified:
  head/usr.sbin/bsdconfig/share/script.subr
  head/usr.sbin/bsdconfig/share/variable.subr
  head/usr.sbin/bsdconfig/usermgmt/Makefile
  head/usr.sbin/bsdconfig/usermgmt/groupadd
  head/usr.sbin/bsdconfig/usermgmt/groupdel
  head/usr.sbin/bsdconfig/usermgmt/groupedit
  head/usr.sbin/bsdconfig/usermgmt/include/messages.subr
  head/usr.sbin/bsdconfig/usermgmt/share/Makefile
  head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr

Modified: head/usr.sbin/bsdconfig/share/script.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/script.subr	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/share/script.subr	Fri Mar  7 20:44:19 2014	(r262904)
@@ -37,6 +37,7 @@ f_include $BSDCFG_SHARE/media/tcpip.subr
 f_include $BSDCFG_SHARE/mustberoot.subr
 f_include $BSDCFG_SHARE/networking/services.subr
 f_include $BSDCFG_SHARE/packages/packages.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
 f_include $BSDCFG_SHARE/variable.subr
 
 ############################################################ GLOBALS
@@ -198,6 +199,11 @@ f_resword_new packageAdd	f_package_add
 f_resword_new packageDelete	f_package_delete
 f_resword_new packageReinstall	f_package_reinstall
 
+# usermgmt/group.subr
+f_resword_new groupAdd		f_group_add
+f_resword_new groupDelete	f_group_delete
+f_resword_new groupEdit		f_group_edit
+
 # variable.subr
 f_resword_new installVarDefaults	f_variable_set_defaults
 f_resword_new dumpVariables		f_dump_variables

Modified: head/usr.sbin/bsdconfig/share/variable.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/variable.subr	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/share/variable.subr	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,6 +1,6 @@
 if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1
 #
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -241,6 +241,10 @@ f_variable_new VAR_FTP_PORT		ftpPort
 f_variable_new VAR_FTP_STATE		ftpState
 f_variable_new VAR_FTP_USER		ftpUser
 f_variable_new VAR_GATEWAY		defaultrouter
+f_variable_new VAR_GROUP		group
+f_variable_new VAR_GROUP_GID		groupGid
+f_variable_new VAR_GROUP_MEMBERS	groupMembers
+f_variable_new VAR_GROUP_PASSWORD	groupPassword
 f_variable_new VAR_HOSTNAME		hostname
 f_variable_new VAR_HTTP_DIR		httpDirectory
 f_variable_new VAR_HTTP_FTP_MODE	httpFtpMode

Modified: head/usr.sbin/bsdconfig/usermgmt/Makefile
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/Makefile	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/Makefile	Fri Mar  7 20:44:19 2014	(r262904)
@@ -8,8 +8,8 @@ FILESDIR=	${LIBEXECDIR}/bsdconfig/070.us
 FILES=		INDEX USAGE
 
 SCRIPTSDIR=	${FILESDIR}
-SCRIPTS=	groupadd groupdel groupedit groupinput \
-		useradd userdel useredit userinput usermgmt
+SCRIPTS=	groupadd groupdel groupedit useradd userdel useredit \
+		userinput usermgmt
 
 beforeinstall:
 	mkdir -p ${DESTDIR}${FILESDIR}

Modified: head/usr.sbin/bsdconfig/usermgmt/groupadd
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/groupadd	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/groupadd	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #-
 # Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,11 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
 . $BSDCFG_SHARE/common.subr || exit 1
 f_dprintf "%s: loading includes..." "$0"
 f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
 
 BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
 
 f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
 	pgm="${ipgm:-$pgm}"
@@ -55,9 +58,19 @@ done
 shift $(( $OPTIND - 1 ))
 
 #
-# Chain-load to groupinput to centralize code and minimize duplication
+# Initialize
 #
-$BSDCFG_LIBE/$APP_DIR/groupinput ${USE_XDIALOG:+-X} mode="Add"
+f_dialog_title "$msg_add $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Add a user
+#
+# NB: If given an argument on the command-line use it; otherwise fall-back to
+#     environment variable $group (handle $VAR_GROUP).
+#
+f_group_add ${1:+"$1"}
 
 ################################################################################
 # END

Modified: head/usr.sbin/bsdconfig/usermgmt/groupdel
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/groupdel	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/groupdel	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #-
 # Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
 f_dprintf "%s: loading includes..." "$0"
 f_include $BSDCFG_SHARE/dialog.subr
 f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
 f_include $BSDCFG_SHARE/usermgmt/group_input.subr
 
 BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
@@ -67,7 +68,7 @@ f_mustberoot_init
 #
 # Loop until the user Exits, Cancels or presses ESC
 #
-defaultitem=""
+defaultitem=
 while :; do
 	f_dialog_menu_group_list "$defaultitem"
 	retval=$?
@@ -81,8 +82,7 @@ while :; do
 
 	# Anything else is a group name
 
-	$BSDCFG_LIBE/$APP_DIR/groupinput \
-		${USE_XDIALOG:+-X} mode="Delete" group="$mtag"
+	f_group_delete "$mtag"
 done
 
 exit $SUCCESS

Modified: head/usr.sbin/bsdconfig/usermgmt/groupedit
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/groupedit	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/groupedit	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #-
 # Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
 f_dprintf "%s: loading includes..." "$0"
 f_include $BSDCFG_SHARE/dialog.subr
 f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
 f_include $BSDCFG_SHARE/usermgmt/group_input.subr
 
 BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
@@ -65,9 +66,17 @@ f_dialog_backtitle "${ipgm:+bsdconfig }$
 f_mustberoot_init
 
 #
-# Loop until the user Exits, Cancels or presses ESC
+# If given a group name, operate on it and exit
 #
-defaultitem=""
+if [ "$1" ]; then
+	f_group_edit "$1"
+	exit $SUCCESS
+fi
+
+#
+# Present a list of groups and loop until user Exits, Cancels or presses ESC
+#
+defaultitem=
 while :; do
 	f_dialog_menu_group_list "$defaultitem"
 	retval=$?
@@ -81,8 +90,7 @@ while :; do
 
 	# Anything else is a group name
 
-	$BSDCFG_LIBE/$APP_DIR/groupinput \
-		${USE_XDIALOG:+-X} mode="Edit/View" group="$mtag"
+	f_group_edit "$mtag"
 done
 
 exit $SUCCESS

Modified: head/usr.sbin/bsdconfig/usermgmt/include/messages.subr
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/include/messages.subr	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/include/messages.subr	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,5 +1,5 @@
 # Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -90,6 +90,7 @@ msg_login_updated="Login Updated"
 msg_member_of_groups="Member of Groups"
 msg_n_a="N/A"
 msg_no="No"
+msg_no_group_specified="No group specified!"
 msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:"
 msg_ok="OK"
 msg_password="Password"
@@ -97,6 +98,7 @@ msg_password_does_not_expire="Password d
 msg_password_expires_in_how_many_days="Password expires in how many days?"
 msg_password_expires_on="Password Expires on"
 msg_passwords_do_not_match="Passwords do not match."
+msg_please_enter_a_group_name="Please enter a group name!"
 msg_reenter_group_password="Re-enter Group Password"
 msg_reenter_password="Re-enter Password"
 msg_save="Save"

Modified: head/usr.sbin/bsdconfig/usermgmt/share/Makefile
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/share/Makefile	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/share/Makefile	Fri Mar  7 20:44:19 2014	(r262904)
@@ -3,7 +3,7 @@
 NO_OBJ=
 
 FILESDIR=	${SHAREDIR}/bsdconfig/usermgmt
-FILES=		group_input.subr user_input.subr
+FILES=		group.subr group_input.subr user_input.subr
 
 beforeinstall:
 	mkdir -p ${DESTDIR}${FILESDIR}

Added: head/usr.sbin/bsdconfig/usermgmt/share/group.subr
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsdconfig/usermgmt/share/group.subr	Fri Mar  7 20:44:19 2014	(r262904)
@@ -0,0 +1,484 @@
+if [ ! "$_USERMGMT_GROUP_SUBR" ]; then _USERMGMT_GROUP_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/group.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${passwdtype:="yes"}
+
+############################################################ FUNCTIONS
+
+# f_group_add [$group]
+#
+# Add a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to enter the name
+# of a new group and (if $VAR_NO_CONFIRM is unset or NULL) prompt the user to
+# answer some questions about the new group. Variables that can be used to
+# script user input:
+#
+# 	VAR_GROUP [Optional if running interactively]
+# 		The group to add. Ignored if given non-NULL first-argument.
+#	VAR_GROUP_GID [Optional]
+# 		Numerical group ID to use. If NULL or unset, the group ID is
+# 		automatically chosen.
+# 	VAR_GROUP_MEMBERS [Optional]
+# 		Comma separated list of users that are a member of this group.
+# 	VAR_GROUP_PASSWORD [Optional]
+# 		newgrp(1) password to set for the group. Default if NULL or
+# 		unset is to disable newgrp(1) password authentication.
+#
+# Returns success if the group was successfully added.
+#
+f_group_add()
+{
+	local funcname=f_group_add
+	local title # Calculated below
+	local alert=f_show_msg no_confirm=
+
+	f_getvar $VAR_NO_CONFIRM no_confirm
+	[ "$no_confirm" ] && alert=f_show_info
+
+	local input
+	f_getvar 3:-\$$VAR_GROUP input "$1"
+
+	#
+	# NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+	# instead of name. Work-around is to also pass `-g GID' at the same
+	# time (any GID will do; but `-1' is appropriate for this context).
+	#
+	if [ "$input" ] && f_quietly pw groupshow -n "$input" -g -1; then
+		f_show_err "$msg_group_already_used" "$input"
+		return $FAILURE
+	fi
+
+	local group_name="$input"
+	while f_interactive && [ ! "$group_name" ]; do
+		f_dialog_input_group_name group_name "$group_name" ||
+			return $SUCCESS
+		[ "$group_name" ] ||
+			f_show_err "$msg_please_enter_a_group_name"
+	done
+
+	local group_password group_gid group_members
+	f_getvar $VAR_GROUP_PASSWORD	group_password
+	f_getvar $VAR_GROUP_GID		group_gid
+	f_getvar $VAR_GROUP_MEMBERS	group_members
+
+	local group_password_disable=
+	f_interactive || [ "$group_password" ] || group_password_disable=1
+
+	if f_interactive && [ ! "$no_confirm" ]; then
+		f_dialog_noyes \
+			"$msg_use_default_values_for_all_account_details"
+		retval=$?
+		if [ $retval -eq $DIALOG_ESC ]; then
+			return $SUCCESS
+		elif [ $retval -ne $DIALOG_OK ]; then
+			#
+			# Ask series of questions to pre-fill the editor screen
+			#
+			# Defaults used in each dialog should allow the user to
+			# simply hit ENTER to proceed and cancelling a single
+			# dialog cause them to return to the previous menu.
+			#
+	
+			if [ "$passwdtype" = "yes" ]; then
+				f_dialog_input_group_password group_password \
+					group_password_disable ||
+					return $FAILURE
+			fi
+			f_dialog_input_group_gid group_gid "$group_gid" ||
+				return $FAILURE
+			f_dialog_input_group_members group_members \
+				"$group_members" || return $FAILURE
+		fi
+	fi
+
+	#
+	# Loop until the user decides to Exit, Cancel, or presses ESC
+	#
+	title="$msg_add $msg_group: $group_name"
+	if f_interactive; then
+		local mtag retval defaultitem=
+		while :; do
+			f_dialog_title "$title"
+			f_dialog_menu_group_add "$defaultitem"
+			retval=$?
+			f_dialog_title_restore
+			f_dialog_menutag_fetch mtag
+			f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+			defaultitem="$mtag"
+
+			# Return if user either pressed ESC or chose Cancel/No
+			[ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+			case "$mtag" in
+			X) # Add/Exit
+			   local cmd="pw groupadd -n '$group_name'"
+			   [ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+			   [ "$group_members" ] &&
+			   	cmd="$cmd -M '$group_members'"
+
+			   # Execute the command (break on success)
+			   if [ "$group_password_disable" ]; then
+			   	f_eval_catch $funcname pw '%s -h -' "$cmd"
+			   elif [ "$group_password" ]; then
+			   	echo "$group_password" |
+			   		f_eval_catch $funcname \
+			   		pw '%s -h 0' "$cmd"
+			   else
+			   	f_eval_catch $funcname pw '%s' "$cmd"
+			   fi && break
+			   ;;
+			1) # Group Name (prompt for new group name)
+			   f_dialog_input_group_name input "$group_name" ||
+			   	continue
+			   if f_quietly pw groupshow -n "$input" -g -1; then
+			   	f_show_err "$msg_group_already_used" "$input"
+			   	continue
+			   fi
+			   group_name="$input"
+			   title="$msg_add $msg_group: $group_name"
+			   ;;
+			2) # Password
+			   f_dialog_input_group_password group_password \
+			   	group_password_disable
+			   ;;
+			3) # Group ID
+			   f_dialog_input_group_gid group_gid "$group_gid"
+			   ;;
+			4) # Group Members
+			   f_dialog_input_group_members group_members \
+					"$group_members"
+			   ;;
+			esac
+		done
+	else
+		# Form the command
+		local cmd="pw groupadd -n '$group_name'"
+		[ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+		[ "$group_members" ] && cmd="$cmd -M '$group_members'"
+
+		# Execute the command
+		local retval err
+		if [ "$group_password_disable" ]; then
+			f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+		elif [ "$group_password" ]; then
+			echo "$group_password" | f_eval_catch -k err \
+				$funcname pw '%s -h 0' "$cmd"
+		else
+			f_eval_catch -k err $funcname pw '%s' "$cmd"
+		fi
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_err "%s" "$err"
+			return $retval
+		fi
+	fi
+
+	f_dialog_title "$title"
+	$alert "$msg_group_added"
+	f_dialog_title_restore
+	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 2
+
+	return $SUCCESS
+}
+
+# f_group_delete [$group]
+#
+# Delete a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# 	VAR_GROUP [Optional if running interactively]
+# 		The group to delete. Ignored if given non-NULL first-argument.
+#
+# Returns success if the group was successfully deleted.
+#
+f_group_delete()
+{
+	local funcname=f_group_delete
+	local title # Calculated below
+	local alert=f_show_msg no_confirm=
+
+	f_getvar $VAR_NO_CONFIRM no_confirm
+	[ "$no_confirm" ] && alert=f_show_info
+
+	local input
+	f_getvar 3:-\$$VAR_GROUP input "$1"
+
+	local group_name group_password group_gid group_members
+	if [ "$input" ] && ! f_input_group "$input"; then
+		f_show_err "$msg_group_not_found" "$input"
+		return $FAILURE
+	fi
+
+	#
+	# Loop until the user decides to Exit, Cancel, or presses ESC
+	#
+	title="$msg_delete $msg_group: $group_name"
+	if f_interactive; then
+		local mtag retval defaultitem=
+		while :; do
+        		f_dialog_title "$title"
+			f_dialog_menu_group_delete "$group_name" "$defaultitem"
+			retval=$?
+			f_dialog_title_restore
+			f_dialog_menutag_fetch mtag
+			f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+			defaultitem="$mtag"
+
+			# Return if user either pressed ESC or chose Cancel/No
+			[ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+			case "$mtag" in
+			X) # Delete/Exit
+			   f_eval_catch $funcname pw 'pw groupdel "%s"' \
+					"$group_name" && break
+			   ;;
+			1) # Group Name (select different group from list)
+			   f_dialog_menu_group_list "$group_name" || continue
+			   f_dialog_menutag_fetch mtag
+
+			   [ "$mtag" = "X $msg_exit" ] && continue
+
+			   if ! f_input_group "$mtag"; then
+				f_show_err "$msg_group_not_found" "$mtag"
+				# Attempt to fall back to previous selection
+				f_input_group "$input" || return $FAILURE
+			   else
+				input="$mtag"
+			   fi
+			   ;;
+			esac
+		done
+	else
+		local retval err
+		f_eval_catch -k err $funcname pw \
+			'pw groupdel "%s"' "$group_name"
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_err "%s" "$err"
+			return $retval
+		fi
+	fi
+
+        f_dialog_title "$title"
+	$alert "$msg_group_deleted"
+	f_dialog_title_restore
+	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 2
+
+	return $SUCCESS
+}
+
+# f_group_edit [$group]
+#
+# Modify a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# 	VAR_GROUP [Optional if running interactively]
+# 		The group to modify. Ignored if given non-NULL first-argument.
+#	VAR_GROUP_GID [Optional]
+# 		Numerical group ID to set. If NULL or unset, the group ID is
+# 		unchanged.
+# 	VAR_GROUP_MEMBERS [Optional]
+# 		Comma separated list of users that are a member of this group.
+# 		If NULL or unset, group membership is unmodified.
+# 	VAR_GROUP_PASSWORD [Optional]
+# 		newgrp(1) password to set for the group. If unset, the password
+# 		is unmodified. If NULL, the newgrp(1) password is disabled.
+#
+# Returns success if the group was successfully modified.
+#
+f_group_edit()
+{
+	local funcname=f_group_edit
+	local title # Calculated below
+	local alert=f_show_msg no_confirm=
+
+	f_getvar $VAR_NO_CONFIRM no_confirm
+	[ "$no_confirm" ] && alert=f_show_info
+
+	local input
+	f_getvar 3:-\$$VAR_GROUP input "$1"
+
+	#
+	# NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+	# instead of name. Work-around is to also pass `-g GID' at the same
+	# time (any GID will do; but `-1' is appropriate for this context).
+	#
+	if [ "$input" ] && ! f_quietly pw groupshow -n "$input" -g -1; then
+		f_show_err "$msg_group_not_found" "$input"
+		return $FAILURE
+	fi
+
+	if f_interactive && [ ! "$input" ]; then
+		f_dialog_menu_group_list || return $SUCCESS
+		f_dialog_menutag_fetch input
+		[ "$input" = "X $msg_exit" ] && return $SUCCESS
+	elif [ ! "$input" ]; then
+		f_show_err "$msg_no_group_specified"
+		return $FAILURE
+	fi
+
+	local group_name group_password group_gid group_members
+	if ! f_input_group "$input"; then
+		f_show_err "$msg_group_not_found" "$input"
+		return $FAILURE
+	fi
+
+	f_isset $VAR_GROUP_GID && f_getvar $VAR_GROUP_GID group_gid
+	local null_members=
+	if f_isset $VAR_GROUP_MEMBERS; then
+		f_getvar $VAR_GROUP_MEMBERS group_members
+		[ "$group_members" ] || null_members=1
+	fi
+	local group_password_disable=
+	if f_isset $VAR_GROUP_PASSWORD; then
+		f_getvar $VAR_GROUP_PASSWORD group_password
+		[ "$group_password" ] || group_password_disable=1
+	fi
+
+	#
+	# Loop until the user decides to Exit, Cancel, or presses ESC
+	#
+	title="$msg_edit_view $msg_group: $group_name"
+	if f_interactive; then
+		local mtag retval defaultitem=
+		while :; do
+			f_dialog_title "$title"
+			f_dialog_menu_group_edit "$defaultitem"
+			retval=$?
+			f_dialog_title_restore
+			f_dialog_menutag_fetch mtag
+			f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+			defaultitem="$mtag"
+
+			# Return if user either pressed ESC or chose Cancel/No
+			[ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+			case "$mtag" in
+			X) # Save/Exit
+			   local cmd="pw groupmod -n '$group_name'"
+			   [ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+			   [ "$group_members" -o "$null_members" ] &&
+			   	cmd="$cmd -M '$group_members'"
+
+			   # Execute the command (break on success)
+			   if [ "$group_password_disable" ]; then
+			   	f_eval_catch $funcname pw '%s -h -' "$cmd"
+			   elif [ "$group_password" ]; then
+			   	echo "$group_password" |
+			   		f_eval_catch $funcname \
+			   			pw '%s -h 0' "$cmd"
+			   else
+			   	f_eval_catch $funcname pw '%s' "$cmd"
+			   fi && break
+			   ;;
+			1) # Group Name (select different group from list)
+			   f_dialog_menu_group_list "$group_name" || continue
+			   f_dialog_menutag_fetch mtag
+
+			   [ "$mtag" = "X $msg_exit" ] && continue
+
+			   if ! f_input_group "$mtag"; then
+			   	f_show_err "$msg_group_not_found" "$mtag"
+			   	# Attempt to fall back to prevoius selection
+			   	f_input_group "$input" || return $FAILURE
+			   else
+			   	input="$mtag"
+			   fi
+			   title="$msg_edit_view $msg_group: $group_name"
+			   ;;
+			2) # Password
+			   f_dialog_input_group_password group_password \
+			   	group_password_disable
+			   ;;
+			3) # Group ID
+			   f_dialog_input_group_gid group_gid "$group_gid"
+			   ;;
+			4) # Group Members
+			   f_dialog_input_group_members group_members \
+			   	"$group_members" && [ ! "$group_members" ] &&
+			   	null_members=1
+			   ;;
+			esac
+		done
+	else
+		# Form the command
+		local cmd="pw groupmod -n '$group_name'"
+		[ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+		[ "$group_members" -o "$null_members" ] &&
+			cmd="$cmd -M '$group_members'"
+
+		# Execute the command
+		local retval err
+		if [ "$group_password_disable" ]; then
+			f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+		elif [ "$group_password" -o "$null_password" ]; then
+			echo "$group_password" | f_eval_catch -k err \
+				$funcname pw '%s -h 0' "$cmd"
+		else
+			f_eval_catch -k err $funcname pw '%s' "$cmd"
+		fi
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_err "%s" "$err"
+			return $retval
+		fi
+	fi
+
+	f_dialog_title "$title"
+	$alert "$msg_group_updated"
+	f_dialog_title_restore
+	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 2
+
+	return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/group.subr
+
+fi # ! $_USERMGMT_GROUP_SUBR

Modified: head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr	Fri Mar  7 20:32:45 2014	(r262903)
+++ head/usr.sbin/bsdconfig/usermgmt/share/group_input.subr	Fri Mar  7 20:44:19 2014	(r262904)
@@ -1,7 +1,7 @@
 if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
 #
 # Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -48,14 +48,20 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/inc
 #
 f_input_group()
 {
-	eval $( pw groupshow "$1" | awk -F: '
+	local funcname=f_input_group
+	local group="$1"
+
+	f_dprintf "$funcname: Getting info for group \`%s'" "$group"
+	eval "$( pw groupshow "$group" 2> /dev/null | awk -F: '
 	{
+		found = $1 != ""
 		printf "group_name='\'%s\''\n", $1
 		printf "group_password=\n"
 		printf "group_gid='\'%s\''\n", $3
 		printf "group_members='\'%s\''\n", $4
 		exit
-	}' )
+	}
+	END { if (!found) print "false" }' )"
 }
 
 # f_dialog_menu_group_list [$default]
@@ -105,300 +111,457 @@ f_dialog_menu_group_list()
 	return $retval
 }
 
-# f_dialog_input_group_name [$group_name]
+# f_dialog_input_group_name $var_to_set [$group_name]
 #
-# Allows the user to enter a new groupname for a given group. If the user does
-# not cancel or press ESC, the $group_name variable will hold the
-# newly-configured value upon return.
-#
-# If $cur_group_name is defined, the user can enter that and by-pass error-
-# checking (allowing the user to "revert" to an old value without, for example,
-# being told that the groupname already exists).
+# Allows the user to enter a name for a new group. If the user does not cancel
+# or press ESC, the $var_to_set variable will hold the newly-configured value
+# upon return.
 #
 f_dialog_input_group_name()
 {
+	local __var_to_set="$1" __name="$2"
+
 	#
 	# Loop until the user provides taint-free/valid input
 	#
-	local _name="$1" _input="$1"
+	local __input="$__name"
 	while :; do
-
 		# Return if user has either pressed ESC or chosen Cancel/No
-		f_dialog_input _input "$msg_group" "$_input" \
+		f_dialog_input __input "$msg_group" "$__input" \
 		               "$hline_alnum_tab_enter" || return $?
 
 		# Check for no-change
-		[ "$_input" = "$_name" ] && return $DIALOG_OK
-
-		# Check for reversion
-		if [ "$_input" = "$cur_group_name" ]; then
-			group_name="$cur_group_name"
+		if [ "$__input" = "$__name" ]; then
+			setvar "$__var_to_set" "$__input"
 			return $DIALOG_OK
 		fi
 
 		# Check for NULL entry
-		if [ ! "$_input" ]; then
+		if [ ! "$__input" ]; then
 			f_show_msg "$msg_group_is_empty"
 			continue
 		fi
 
 		# Check for invalid entry
-		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
+		case "$__input" in [!a-zA-Z]*)
 			f_show_msg "$msg_group_must_start_with_letter"
 			continue
-		fi
+		esac
 
 		# Check for duplicate entry
-		if f_quietly pw groupshow -n "$_input"; then
-			f_show_msg "$msg_group_already_used" "$_input"
+		if f_quietly pw groupshow -n "$__input"; then
+			f_show_msg "$msg_group_already_used" "$__input"
 			continue
 		fi
 
-		group_name="$_input"
+		setvar "$__var_to_set" "$__input"
 		break
 	done
 	save_flag=1
 
-	f_dprintf "group_name: [%s]->[%s]" "$cur_group_name" "$group_name"
-
 	return $DIALOG_OK
 }
 
-# f_dialog_input_group_password
+# f_dialog_input_group_password $var_to_set $dvar_to_set
 #
-# Prompt the user to enter a password (twice).
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
+# user cancels or enters a NULL password (twice), they are given the choice to
+# disable password authentication for the given group, wherein $dvar_to_set has
+# a value of 1 to indicate password authentication should be disabled.
 #
 f_dialog_input_group_password()
 {
-	local prompt1="$msg_group_password"
-	local prompt2="$msg_reenter_group_password"
-	local hline="$hline_alnum_punc_tab_enter"
+	local __var_to_set="$1" __dvar_to_set="$2"
+	local __prompt1="$msg_group_password"
+	local __prompt2="$msg_reenter_group_password"
+	local __hline="$hline_alnum_punc_tab_enter"
 
-	local height1 width1
-	f_dialog_inputbox_size height1 width1 \
+	local __height1 __width1
+	f_dialog_inputbox_size __height1 __width1 \
 	        	"$DIALOG_TITLE"     \
 	        	"$DIALOG_BACKTITLE" \
-	        	"$prompt1"          \
+	        	"$__prompt1"        \
 	        	""                  \
-	        	"$hline"
+	        	"$__hline"
 
-	local height2 width2
-	f_dialog_inputbox_size height2 width2 \
+	local __height2 __width2
+	f_dialog_inputbox_size __height2 __width2 \
 	        	"$DIALOG_TITLE"     \
 	        	"$DIALOG_BACKTITLE" \
-	        	"$prompt2"          \
+	        	"$__prompt2"        \
 	        	""                  \
-	        	"$hline"
+	        	"$__hline"
 
 	#
 	# Loop until the user provides taint-free/valid input
 	#
-	local retval _password1 _password2
+	local __retval __password1 __password2
 	while :; do
-		_password1=$( $DIALOG \
+		__password1=$( $DIALOG \
 			--title "$DIALOG_TITLE"         \
 			--backtitle "$DIALOG_BACKTITLE" \
-			--hline "$hline"                \
+			--hline "$__hline"              \
 			--ok-label "$msg_ok"            \
 			--cancel-label "$msg_cancel"    \
 			--insecure                      \
-			--passwordbox "$prompt1"        \
-			$height1 $width1                \
+			--passwordbox "$__prompt1"      \
+			$__height1 $__width1            \
 			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
 		)
-		retval=$?
-		debug= f_dialog_line_sanitize _password1
+		__retval=$?
+		debug= f_dialog_line_sanitize __password1
 
 		# Return if user has either pressed ESC or chosen Cancel/No
-		[ $retval -eq $DIALOG_OK ] || return $retval
+		[ $__retval -eq $DIALOG_OK ] || return $__retval
 
-		_password2=$( $DIALOG \
+		__password2=$( $DIALOG \
 			--title "$DIALOG_TITLE"         \
 			--backtitle "$DIALOG_BACKTITLE" \
-			--hline "$hline"                \
+			--hline "$__hline"              \
 			--ok-label "$msg_ok"            \
 			--cancel-label "$msg_cancel"    \
 			--insecure                      \
-			--passwordbox "$prompt2"        \
-			$height2 $width2                \
+			--passwordbox "$__prompt2"      \
+			$__height2 $__width2            \
 			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
 		)
-		retval=$?
-		debug= f_dialog_line_sanitize _password2
+		__retval=$?
+		debug= f_dialog_line_sanitize __password2
 
 		# Return if user has either pressed ESC or chosen Cancel/No
-		[ $retval -eq $DIALOG_OK ] || return $retval
+		[ $__retval -eq $DIALOG_OK ] || return $__retval
 
 		# Check for password mismatch
-		if [ "$_password1" != "$_password2" ]; then
+		if [ "$__password1" != "$__password2" ]; then
 			f_show_msg "$msg_group_passwords_do_not_match"
 			continue
 		fi
 
 		# Check for NULL entry
-		if [ ! "$_password1" ]; then
+		if [ ! "$__password1" ]; then
 			f_dialog_yesno "$msg_disable_password_auth_for_group"
-			local retval=$?
-			if [ $retval -eq $DIALOG_ESC ]; then
-				return $retval
-			elif [ $retval -eq $DIALOG_OK ]; then
-				pw_group_password_disable=1
+			__retval=$?
+			if [ $__retval -eq $DIALOG_ESC ]; then
+				return $__retval
+			elif [ $__retval -eq $DIALOG_OK ]; then
+				setvar "$__dvar_to_set" 1
 			else
 				continue # back to password prompt
 			fi
 		else
-			pw_group_password_disable=
+			setvar "$__dvar_to_set" ""
 		fi
 
-		group_password="$_password1"
+		setvar "$__var_to_set" "$__password1"
 		break
 	done
 	save_flag=1
 
-	f_dprintf "group_password: [%s]->[%s]" \
-	          "$cur_group_password" "$group_password"
-
 	return $DIALOG_OK
 }
 
-# f_dialog_input_group_gid [$group_gid]
+# f_dialog_input_group_gid $var_to_set [$group_gid]
 #
 # Allow the user to enter a new GID for a given group. If the user does not
-# cancel or press ESC, the $group_gid variable will hold the newly-configured
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
 # value upon return.
 #
 f_dialog_input_group_gid()
 {
-	local _input="$1"
+	local __var_to_set="$1" __input="$2"
 
 	# Return if user has either pressed ESC or chosen Cancel/No
-	f_dialog_input _input "$msg_group_id_leave_empty_for_default" \
-	               "$_input" "$hline_num_tab_enter" || return $?
+	f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
+	               "$__input" "$hline_num_tab_enter" || return $?
 
-	group_gid="$_input"
+	setvar "$__var_to_set" "$__input"
 	save_flag=1
 
-	f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid"
-
 	return $DIALOG_OK
 }
 
-# f_dialog_input_group_members [$group_members]
+# f_dialog_input_group_members $var_to_set [$group_members]
 #
 # Allow the user to modify a list of members for a given group. If the user
-# does not cancel or press ESC, the $group_members variable will hold the
-# newly-configured value upon return.
+# does not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
 #

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403072044.s27KiKCb039707>