svn commit: r263980 - in stable/10: . usr.sbin/bsdconfig usr.sbin/bsdconfig/share usr.sbin/bsdconfig/timezone/share usr.sbin/bsdconfig/usermgmt usr.sbin/bsdconfig/usermgmt/include usr.sbin/bsdconfi...

Devin Teske dteske at FreeBSD.org
Tue Apr 1 00:19:17 UTC 2014


Author: dteske
Date: Tue Apr  1 00:19:13 2014
New Revision: 263980
URL: http://svnweb.freebsd.org/changeset/base/263980

Log:
  MFC revisions 260894,260899,262895-262902,262904,262908-262910,262982,
  262984,263133-263137,263139,263141,263144-263150, and (partially) 263249
  (31 revisions; summarized below)...
  r260894: Optimize f_expand_number(), improving performance
  r260899: s/__number/__num/ in f_expand_number()
  r262895: Allow dispatched reswords to carry arguments
  r262896: Add missing local declaration
  r262897: Fix a typo in a comment
  r262898: Fix incorrect return status if var_to_set and var_to_get are same
  r262899: Make f_show_err non-fatal
  r262900: Centralize function name; Update a comment while here
  r262901: s/__num/__number/ in f_expand_number()
  r262902: Comment to go with NL global introduced by previous commit
  r262904: Rewrite groupmgmt -- hooking it into the scripting system
  r262908: Change dispatch words from group* to *Group for backward compat
  r262909: Fix copy/paste error in a comment
  r262910: Take a group name on the command-line if available
  r262982: Whitespace
  r262984: Remove vestigial global, no longer used since r262904
  r263133: Remove indexfile from debug statement (already logged)
  r263134: Add debug statement just before attempting to exec a module
  r263135: Comments
  r263136: Update copyright
  r263137: Fix future namespace issues for functions taking $var_to_set
  r263139: Remove useless NULL string in compound strings
  r263141: Pointy hat! Fix a broken f_isinteger()
  r263144: Fix a code-typo that prevented auto-sizing of a dialog
  r263145: Fix comments and whitespace
  r263146: Reduce the sleep cycle when using dialog(1) [infobox] to 1-second
  r263147: Fix a bug preventing errors from pw(8) from appearing
  r263148: For non-interactive scripts, forgot to check argument
  r263149: Add protection against input containing single-quotes
  r263150: Rewrite usermgmt
  r263249: (partial) Add more obsolete files

Added:
  stable/10/usr.sbin/bsdconfig/usermgmt/share/group.subr
     - copied, changed from r262904, head/usr.sbin/bsdconfig/usermgmt/share/group.subr
  stable/10/usr.sbin/bsdconfig/usermgmt/share/user.subr
     - copied unchanged from r263150, head/usr.sbin/bsdconfig/usermgmt/share/user.subr
Deleted:
  stable/10/usr.sbin/bsdconfig/usermgmt/groupinput
  stable/10/usr.sbin/bsdconfig/usermgmt/userinput
Modified:
  stable/10/ObsoleteFiles.inc
  stable/10/usr.sbin/bsdconfig/bsdconfig
  stable/10/usr.sbin/bsdconfig/share/common.subr
  stable/10/usr.sbin/bsdconfig/share/device.subr
  stable/10/usr.sbin/bsdconfig/share/dialog.subr
  stable/10/usr.sbin/bsdconfig/share/keymap.subr
  stable/10/usr.sbin/bsdconfig/share/script.subr
  stable/10/usr.sbin/bsdconfig/share/strings.subr
  stable/10/usr.sbin/bsdconfig/share/variable.subr
  stable/10/usr.sbin/bsdconfig/timezone/share/menus.subr
  stable/10/usr.sbin/bsdconfig/usermgmt/Makefile
  stable/10/usr.sbin/bsdconfig/usermgmt/groupadd
  stable/10/usr.sbin/bsdconfig/usermgmt/groupdel
  stable/10/usr.sbin/bsdconfig/usermgmt/groupedit
  stable/10/usr.sbin/bsdconfig/usermgmt/include/messages.subr
  stable/10/usr.sbin/bsdconfig/usermgmt/share/Makefile
  stable/10/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
  stable/10/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
  stable/10/usr.sbin/bsdconfig/usermgmt/useradd
  stable/10/usr.sbin/bsdconfig/usermgmt/userdel
  stable/10/usr.sbin/bsdconfig/usermgmt/useredit
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/ObsoleteFiles.inc
==============================================================================
--- stable/10/ObsoleteFiles.inc	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/ObsoleteFiles.inc	Tue Apr  1 00:19:13 2014	(r263980)
@@ -75,6 +75,10 @@ OLD_FILES+=usr/include/clang/3.3/xopintr
 OLD_FILES+=usr/share/man/man1/llvm-prof.1.gz
 OLD_FILES+=usr/share/man/man1/llvm-ranlib.1.gz
 OLD_DIRS+=usr/include/clang/3.3
+# 20140314: bsdconfig usermgmt rewrite
+OLD_FILES+=usr/libexec/bsdconfig/070.usermgmt/userinput
+# 20140307: bsdconfig groupmgmt rewrite
+OLD_FILES+=usr/libexec/bsdconfig/070.usermgmt/groupinput
 # 20131109: extattr(2) mlinks fixed
 OLD_FILES+=usr/share/man/man2/extattr_delete_list.2.gz
 OLD_FILES+=usr/share/man/man2/extattr_get_list.2.gz

Modified: stable/10/usr.sbin/bsdconfig/bsdconfig
==============================================================================
--- stable/10/usr.sbin/bsdconfig/bsdconfig	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/bsdconfig	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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
@@ -315,8 +315,7 @@ if [ "$pgm" != "bsdconfig" ]; then
 	if indexfile=$( f_index_file "$pgm" ) &&
 	   cmd=$( f_index_menusel_command "$indexfile" "$pgm" )
 	then
-		f_dprintf "pgm=[%s] indexfile=[%s] cmd=[%s]" \
-		          "$pgm" "$indexfile" "$cmd"
+		f_dprintf "pgm=[%s] cmd=[%s] *=[%s]" "$pgm" "$cmd" "$*"
 		exec "$cmd" "$@" || exit 1
 	else
 		f_include $BSDCFG_SHARE/script.subr
@@ -324,7 +323,7 @@ if [ "$pgm" != "bsdconfig" ]; then
 			[ "$pgm" = "$resword" ] || continue
 			# Found a match
 			f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
-			f_dispatch $resword
+			f_dispatch $resword $resword "$@"
 			exit $?
 		done
 	fi
@@ -382,6 +381,7 @@ if [ "$1" ]; then
 		# Not reached
 	fi
 
+	f_dprintf "cmd=[%s] *=[%s]" "$cmd" "$*"
 	shift
 	exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
 	# Not reached

Modified: stable/10/usr.sbin/bsdconfig/share/common.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/common.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/common.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -1,7 +1,7 @@
 if [ ! "$_COMMON_SUBR" ]; then _COMMON_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
@@ -153,7 +153,7 @@ f_debug_init()
 	# Process stored command-line arguments
 	#
 	set -- $ARGV
-	local OPTIND
+	local OPTIND flag
 	f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
 	          "$ARGV" "$GETOPTS_STDARGS"
 	while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \
@@ -270,9 +270,9 @@ f_getvar()
 {
 	local __var_to_get="$1" __var_to_set="$2"
 	[ "$__var_to_set" ] || local value
-	eval ${__var_to_set:-value}=\"\${$__var_to_get}\"
 	eval [ \"\${$__var_to_get+set}\" ]
 	local __retval=$?
+	eval ${__var_to_set:-value}=\"\${$__var_to_get}\"
 	eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \
 		\"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval
 	[ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; }
@@ -368,13 +368,10 @@ f_show_msg()
 # f_show_err $format [$arguments ...]
 #
 # Display a message in a dialog box with ``Error'' i18n title (overridden by
-# setting msg_error) using printf(1) syntax. If running non-interactively,
-# the process will terminate (using [above] f_die()).
+# setting msg_error) using printf(1) syntax.
 #
 f_show_err()
 {
-	[ "$nonInteractive" ] && f_die
-
 	local msg
 	msg=$( printf "$@" )
 
@@ -523,7 +520,7 @@ f_include_lang()
 # 	f_usage $file "FOO" "BAR"
 #
 # Will cause instances of "@FOO@" appearing in $file to be replaced with the
-# text "BAR" before bering printed to the screen.
+# text "BAR" before being printed to the screen.
 #
 # This function is a two-parter. Below is the awk(1) portion of the function,
 # afterward is the sh(1) function which utilizes the below awk script.

Modified: stable/10/usr.sbin/bsdconfig/share/device.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/device.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/device.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -1,6 +1,6 @@
 if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_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
@@ -170,11 +170,10 @@ f_device_reset()
 	for dev in $DEVICES; do
 		f_device_shutdown $dev
 
-		#
-		# XXX this potentially leaks $dev->private if it's being
+		# XXX This potentially leaks $dev->private if it's being
 		# used to point to something dynamic, but you're not supposed
 		# to call this routine at such times that some open instance
-		# has its private member pointing somewhere anyway. XXX
+		# has its private member pointing somewhere anyway.
 		#
 		f_struct_free device_$dev
 	done
@@ -325,8 +324,7 @@ f_device_get_all()
 
 		case "$diskname" in
 		cd*)
-			# XXX
-			#  Due to unknown reasons, kern.disks returns SCSI
+			# XXX Due to unknown reasons, kern.disks returns SCSI
 			# CDROM as a valid disk. This will prevent bsdconfig
 			# from presenting SCSI CDROMs as available disks in
 			# various menus. Why GEOM treats SCSI CDROM as a disk

Modified: stable/10/usr.sbin/bsdconfig/share/dialog.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/dialog.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/dialog.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -1,6 +1,6 @@
 if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1
 #
-# Copyright (c) 2006-2013 Devin Teske
+# Copyright (c) 2006-2014 Devin Teske
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -469,16 +469,17 @@ f_dialog_menu_constrain()
 	# Print debug warnings if any given (non-NULL) argument are invalid
 	# NOTE: Don't change the name of $__{var,min,}{height,width,rows}
 	#
-	local __height __width __rows
+	local __height_menu_constrain __width_menu_constrain
+	local __rows_menu_constrain
 	local __arg __cp __fname=f_dialog_menu_constrain 
 	for __arg in height width rows; do
 		debug= f_getvar __var_$__arg __cp
 		[ "$__cp" ] || continue
-		if ! debug= f_getvar "$__cp" __$__arg; then
+		if ! debug= f_getvar "$__cp" __${__arg}_menu_constrain; then
 			f_dprintf "%s: var_%s variable \`%s' not set" \
 			          $__fname $__arg "$__cp"
 			__retval=$FAILURE
-		elif ! eval f_isinteger \$__$__arg; then
+		elif ! eval f_isinteger \$__${__arg}_menu_constrain; then
 			f_dprintf "%s: var_%s variable value not a number" \
 			          $__fname $__arg
 			__retval=$FAILURE
@@ -502,9 +503,11 @@ f_dialog_menu_constrain()
 
 	# Adjust height if desired
 	if [ "$__var_height" ]; then
-		if [ $__height -lt ${__min_height:-0} ]; then
+		if [ $__height_menu_constrain -lt ${__min_height:-0} ]; then
 			setvar "$__var_height" $__min_height
-		elif [ $__height -gt $__max_height_menu_constrain ]; then
+		elif [ $__height_menu_constrain -gt \
+		       $__max_height_menu_constrain ]
+		then
 			setvar "$__var_height" $__max_height_menu_constrain
 		fi
 	fi
@@ -516,9 +519,11 @@ f_dialog_menu_constrain()
 		else
 			: ${__min_width:=${DIALOG_MIN_WIDTH:-24}}
 		fi
-		if [ $__width -lt $__min_width ]; then
+		if [ $__width_menu_constrain -lt $__min_width ]; then
 			setvar "$__var_width" $__min_width
-		elif [ $__width -gt $__max_width_menu_constrain ]; then
+		elif [ $__width_menu_constrain -gt \
+		       $__max_width_menu_constrain ]
+		then
 			setvar "$__var_width" $__max_width_menu_constrain
 		fi
 	fi
@@ -531,16 +536,20 @@ f_dialog_menu_constrain()
 			: ${__min_rows:=0}
 		fi
 
-		local __max_rows=$(( $__max_height_menu_constrain - 7 ))
+		local __max_rows_menu_constrain=$((
+			$__max_height_menu_constrain - 7
+		))
 		# If prompt_len is zero (no prompt), bump the max-rows by 1
 		# Default assumption is (if no argument) that there's no prompt
-		[ ${__prompt_len:-0} -gt 0 ] ||
-			__max_rows=$(( $__max_rows + 1 ))
+		[ ${__prompt_len:-0} -gt 0 ] || __max_rows_menu_constrain=$((
+			$__max_rows_menu_constrain + 1
+		))
 
-		if [ $__rows -lt $__min_rows ]; then
+		if [ $__rows_menu_constrain -lt $__min_rows ]; then
 			setvar "$__var_rows" $__min_rows
-		elif [ $__rows -gt $__max_rows ]; then
-			setvar "$__var_rows" $__max_rows
+		elif [ $__rows_menu_constrain -gt $__max_rows_menu_constrain ]
+		then
+			setvar "$__var_rows" $__max_rows_menu_constrain
 		fi
 	fi
 
@@ -1100,19 +1109,20 @@ f_dialog_radiolist_size()
 	# longest item-length (both used to bump the width), and the number of
 	# rows (used to bump the height).
 	#
-	local __longest_tag=0 __longest_item=0 __rows=0
+	local __longest_tag=0 __longest_item=0 __rows_rlist_size=0
 	while [ $# -ge 3 ]; do
 		local __tag="$1" __item="$2"
 		shift 3 # tag/item/status
 		[ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
 		[ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
-		__rows=$(( $__rows + 1 ))
+		__rows_rlist_size=$(( $__rows_rlist_size + 1 ))
 	done
 
 	# Adjust rows early (for up-coming height calculation)
 	if [ "$__var_height" -o "$__var_rows" ]; then
 		# Add a row for visual aid if using Xdialog(1)
-		[ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+		[ "$USE_XDIALOG" ] &&
+			__rows_rlist_size=$(( $__rows_rlist_size + 1 ))
 	fi
 
 	# Adjust height if desired
@@ -1120,10 +1130,12 @@ f_dialog_radiolist_size()
 		# Add rows to height
 		if [ "$USE_XDIALOG" ]; then
 			__height_rlist_size=$((
-				$__height_rlist_size + $__rows + 7 ))
+				$__height_rlist_size + $__rows_rlist_size + 7
+			))
 		else
 			__height_rlist_size=$((
-				$__height_rlist_size + $__rows + 4 ))
+				$__height_rlist_size + $__rows_rlist_size + 4
+			))
 		fi
 		setvar "$__var_height" $__height_rlist_size
 	fi
@@ -1140,7 +1152,7 @@ f_dialog_radiolist_size()
 	fi
 
 	# Store adjusted rows if desired
-	[ "$__var_rows" ] && setvar "$__var_rows" $__rows
+	[ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_size
 
 	# Constrain height, width, and rows to sensible minimum/maximum values
 	# Return success if no-constrain, else return status from constrain
@@ -1220,20 +1232,26 @@ f_dialog_radiolist_with_help_size()
 	# all used to bump the width -- and the number of rows (used to bump
 	# the height).
 	#
-	local __longest_tag=0 __longest_item=0 __longest_help=0 __rows=0
+	local __longest_tag=0 __longest_item=0 __longest_help=0
+	local __rows_rlist_with_help_size=0
 	while [ $# -ge 4 ]; do
 		local __tag="$1" __item="$2" __status="$3" __help="$4"
 		shift 4 # tag/item/status/help
 		[ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
 		[ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
 		[ ${#__help} -gt $__longest_help ] && __longest_help=${#__help}
-		__rows=$(( $__rows + 1 ))
+		__rows_rlist_with_help_size=$((
+			$__rows_rlist_with_help_size + 1
+		))
 	done
 
 	# Adjust rows early (for up-coming height calculation)
 	if [ "$__var_height" -o "$__var_rows" ]; then
 		# Add a row for visual aid if using Xdialog(1)
-		[ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+		[ "$USE_XDIALOG" ] &&
+			__rows_rlist_with_help_size=$((
+				$__rows_rlist_with_help_size + 1
+			))
 	fi
 
 	# Adjust height if desired
@@ -1241,10 +1259,14 @@ f_dialog_radiolist_with_help_size()
 		# Add rows to height
 		if [ "$USE_XDIALOG" ]; then
 			__height_rlist_with_help_size=$((
-				$__height_rlist_with_help_size + $__rows + 7 ))
+				$__height_rlist_with_help_size +
+				$__rows_rlist_with_help_size + 7
+			))
 		else
 			__height_rlist_with_help_size=$((
-				$__height_rlist_with_help_size + $__rows + 4 ))
+				$__height_rlist_with_help_size +
+				$__rows_rlist_with_help_size + 4
+			))
 		fi
 		setvar "$__var_height" $__height
 	fi
@@ -1270,7 +1292,7 @@ f_dialog_radiolist_with_help_size()
 	fi
 
 	# Store adjusted rows if desired
-	[ "$__var_rows" ] && setvar "$__var_rows" $__rows
+	[ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_with_help_size
 
 	# Constrain height, width, and rows to sensible minimum/maximum values
 	# Return success if no-constrain, else return status from constrain

Modified: stable/10/usr.sbin/bsdconfig/share/keymap.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/keymap.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/keymap.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -165,7 +165,7 @@ f_keymap_get_all()
 			marks[keym] = mark
 			name = keym
 			gsub(/[^[:alnum:]_]/, "_", name)
-			gsub(/'\''/, "'\''\\'\'''\''", desc);
+			gsub(/'\''/, "'\''\\'\'\''", desc);
 			printf "f_keymap_checkfile %s && " \
 			       "f_keymap_register %s '\'%s\'' %s %u\n",
 			       keym, name, desc, keym, mark

Modified: stable/10/usr.sbin/bsdconfig/share/script.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/script.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/script.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -1,6 +1,6 @@
 if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_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
@@ -37,6 +37,8 @@ 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/usermgmt/user.subr
 f_include $BSDCFG_SHARE/variable.subr
 
 ############################################################ GLOBALS
@@ -50,25 +52,23 @@ RESWORDS=
 # Create a new `reserved' word for scripting purposes. Reswords call pre-
 # defined functions but differ from those functions in the following ways:
 #
-# 	+ Reswords do not take arguments but instead get all their data from
-# 	  the environment variable namespace.
 # 	+ Unless noError is set (must be non-NULL), if calling the resword
 # 	  results in failure, the application will terminate prematurely.
 # 	+ noError is unset after each/every resword is called.
 #
 # Reswords should not be used in bsdconfig itself (hence the name `reserved
-# word') but instead only in scripts loaded through f_script_load()).
+# word') but instead only in scripts loaded through f_script_load().
 #
 f_resword_new()
 {
 	local resword="$1" func="$2"
 	[ "$resword" ] || return $FAILURE
 	f_dprintf "script.subr: New resWord %s -> %s" "$resword" "$func"
-	eval $resword\(\){ f_dispatch $func $resword\; }
+	eval $resword\(\){ f_dispatch $func $resword \"\$@\"\; }
 	RESWORDS="$RESWORDS${RESWORDS:+ }$resword"
 }
 
-# f_dispatch $func [$resword]
+# f_dispatch $func $resword
 #
 # Wrapper function used by `reserved words' (reswords) to call other functions.
 # If $noError is set and non-NULL, a failure result from $func is ignored,
@@ -78,9 +78,10 @@ f_resword_new()
 #
 f_dispatch()
 {
-	local func="$1" resword="${2:-$1}"
+	local func="$1" resword="$2"
+	shift 2 # func resword
 	f_dprintf "f_dispatch: calling resword \`%s'" "$resword"
-	eval $func
+	eval $func "$@"
 	local retval=$?
 	if [ $retval -ne $SUCCESS ]; then
 		local _ignore_this_error
@@ -96,7 +97,7 @@ f_dispatch()
 # Load a script (usually filled with reswords). If $file is missing or NULL,
 # use one of the following instead (in order):
 #
-# 	$configFile
+# 	$configFile (global)
 # 	install.cfg
 # 	/stand/install.fg
 # 	/tmp/install.cfg
@@ -108,9 +109,10 @@ f_dispatch()
 #
 f_script_load()
 {
+	local funcname=f_script_load
 	local script="$1" config_file retval=$SUCCESS
 
-	f_dprintf "f_script_load: script=[%s]" "$script"
+	f_dprintf "$funcname: script=[%s]" "$script"
 	if [ ! "$script" ]; then
 		f_getvar $VAR_CONFIG_FILE config_file
 		for script in \
@@ -130,11 +132,11 @@ f_script_load()
 	setvar $VAR_NONINTERACTIVE yes
 
 	if [ "$script" = "-" ]; then
-		f_dprintf "f_script_load: Loading script from stdin"
+		f_dprintf "$funcname: Loading script from stdin"
 		eval "$( cat )"
 		retval=$?
 	else
-		f_dprintf "f_script_load: Loading script \`%s'" "$script"
+		f_dprintf "$funcname: Loading script \`%s'" "$script"
 		if [ ! -e "$script" ]; then
 			f_show_msg "$msg_unable_to_open" "$script"
 			return $FAILURE
@@ -198,6 +200,16 @@ 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 addGroup		f_group_add
+f_resword_new deleteGroup	f_group_delete
+f_resword_new editGroup		f_group_edit
+
+# usermgmt/user.subr
+f_resword_new addUser		f_user_add
+f_resword_new deleteUser	f_user_delete
+f_resword_new editUser		f_user_edit
+
 # variable.subr
 f_resword_new installVarDefaults	f_variable_set_defaults
 f_resword_new dumpVariables		f_dump_variables

Modified: stable/10/usr.sbin/bsdconfig/share/strings.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/strings.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/strings.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -34,6 +34,12 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
 ############################################################ GLOBALS
 
 #
+# A Literal newline (for use with f_replace_all(), or IFS, or whatever)
+#
+NL="
+" # END-QUOTE
+
+#
 # Valid characters that can appear in an sh(1) variable name
 #
 # Please note that the character ranges A-Z and a-z should be avoided because
@@ -189,7 +195,7 @@ f_number_of_lines()
 f_isinteger()
 {
 	local arg="${1#-}"
-	[ "${arg:-x}" = "${arg#[!0-9]*}" ]
+	[ "${arg:-x}" = "${arg%[!0-9]*}" ]
 }
 
 # f_uriencode [$text]
@@ -265,6 +271,9 @@ f_uridecode()
 # capturing in a sub-shell (which is less recommended due to performance
 # degradation).
 #
+# To replace newlines or a sequence containing the newline character, use $NL
+# as `\n' is not supported.
+#
 f_replaceall()
 {
 	local __left="" __right="$1"
@@ -372,14 +381,13 @@ f_expand_number()
 	local __cp __num __bshift __maxinput
 
 	# Remove any leading non-digits
-	while :; do
-		__cp="$__string"
-		__string="${__cp#[!0-9]}"
-		[ "$__string" = "$__cp" ] && break
-	done
+	__string="${__string#${__string%%[0-9]*}}"
+
+	# Store the numbers (no trailing suffix)
+	__num="${__string%%[!0-9]*}"
 
 	# Produce `-1' if string didn't contain any digits
-	if [ ! "$__string" ]; then
+	if [ ! "$__num" ]; then
 		if [ "$__var_to_set" ]; then
 			setvar "$__var_to_set" -1
 		else
@@ -388,25 +396,8 @@ f_expand_number()
 		return 1 # 1 = "Given $string contains no digits"
 	fi
 
-	# Store the numbers
-	__num="${__string%%[!0-9]*}"
-
-	# Shortcut
-	if [ $__num -eq 0 ]; then
-		if [ "$__var_to_set" ]; then
-			setvar "$__var_to_set" 0
-		else
-			echo 0
-		fi
-		return $SUCCESS
-	fi
-
 	# Remove all the leading numbers from the string to get at the prefix
-	while :; do
-		__cp="$__string"
-		__string="${__cp#[0-9]}"
-		[ "$__string" = "$__cp" ] && break
-	done
+	__string="${__string#"$__num"}"
 
 	#
 	# Test for invalid prefix (and determine bitshift length)

Modified: stable/10/usr.sbin/bsdconfig/share/variable.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/share/variable.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/share/variable.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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
@@ -279,6 +283,21 @@ f_variable_new VAR_SLOW_ETHER		slowEther
 f_variable_new VAR_TRY_DHCP		tryDHCP
 f_variable_new VAR_TRY_RTSOL		tryRTSOL
 f_variable_new VAR_UFS_PATH		ufs
+f_variable_new VAR_USER			user
+f_variable_new VAR_USER_ACCOUNT_EXPIRE	userAccountExpire
+f_variable_new VAR_USER_DOTFILES_CREATE	userDotfilesCreate
+f_variable_new VAR_USER_GECOS		userGecos
+f_variable_new VAR_USER_GID		userGid
+f_variable_new VAR_USER_GROUPS		userGroups
+f_variable_new VAR_USER_GROUP_DELETE	userGroupDelete
+f_variable_new VAR_USER_HOME		userHome
+f_variable_new VAR_USER_HOME_CREATE	userHomeCreate
+f_variable_new VAR_USER_HOME_DELETE	userHomeDelete
+f_variable_new VAR_USER_LOGIN_CLASS	userLoginClass
+f_variable_new VAR_USER_PASSWORD	userPassword
+f_variable_new VAR_USER_PASSWORD_EXPIRE	userPasswordExpire
+f_variable_new VAR_USER_SHELL		userShell
+f_variable_new VAR_USER_UID		userUid
 f_variable_new VAR_ZFSINTERACTIVE	zfsInteractive
 
 #

Modified: stable/10/usr.sbin/bsdconfig/timezone/share/menus.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/timezone/share/menus.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/timezone/share/menus.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -104,7 +104,7 @@ f_make_menus_awk='
 function add_zone_n_to_country_menu(tlc, n)
 {
 	zone_title = ENVIRON["country_" tlc "_descr_" n]
-	gsub(/'\''/, "'\''\\'\'''\''", zone_title)
+	gsub(/'\''/, "'\''\\'\'\''", zone_title)
 	country_menu_list[tlc] = country_menu_list[tlc] \
 		( length(country_menu_list[tlc]) > 0 ? "\n" : "" ) \
 		n " '\''" zone_title "'\''"
@@ -121,7 +121,7 @@ BEGIN {
 	{
 		tlc = countries[cp]
 		title = ENVIRON["country_" tlc "_name"]
-		gsub(/'\''/, "'\''\\'\'''\''", title)
+		gsub(/'\''/, "'\''\\'\'\''", title)
 		nzones = ENVIRON["country_" tlc "_nzones"]
 		if (!nzones)
 		{

Modified: stable/10/usr.sbin/bsdconfig/usermgmt/Makefile
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/Makefile	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/Makefile	Tue Apr  1 00:19:13 2014	(r263980)
@@ -8,8 +8,7 @@ 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 usermgmt
 
 beforeinstall:
 	mkdir -p ${DESTDIR}${FILESDIR}

Modified: stable/10/usr.sbin/bsdconfig/usermgmt/groupadd
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/groupadd	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/groupadd	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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 group
+#
+# 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: stable/10/usr.sbin/bsdconfig/usermgmt/groupdel
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/groupdel	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/groupdel	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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
 
 #
+# If given a group name, operate on it and exit
+#
+if [ "$1" ]; then
+	f_group_delete "$1"
+	exit $SUCCESS
+fi
+
+#
 # Loop until the user Exits, Cancels or presses ESC
 #
-defaultitem=""
+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="Delete" group="$mtag"
+	f_group_delete "$mtag"
 done
 
 exit $SUCCESS

Modified: stable/10/usr.sbin/bsdconfig/usermgmt/groupedit
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/groupedit	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/groupedit	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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: stable/10/usr.sbin/bsdconfig/usermgmt/include/messages.subr
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/include/messages.subr	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/include/messages.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -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
@@ -33,7 +33,7 @@ hline_arrows_tab_enter="Press arrows, TA
 hline_num_arrows_tab_enter="Use numbers, arrows, TAB or ENTER"
 hline_num_tab_enter="Use numbers, TAB or ENTER"
 msg_account_does_not_expire="Account does not expire"
-msg_account_expires_in_how_many_days="Account expires in how many days?"
+msg_account_expire_manual_edit="Enter account expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
 msg_account_expires_on="Account Expires on"
 msg_add="Add"
 msg_add_group="Add Group"
@@ -56,6 +56,7 @@ msg_edit_group="Edit/View Group"
 msg_edit_login="Edit/View Login"
 msg_edit_view="Edit/View"
 msg_enter_group_members_manually="Enter Group Members manually"
+msg_enter_groups_manually="Enter Groups manually"
 msg_enter_number_of_days_into_the_future="Enter number of days into the future"
 msg_enter_value_manually="Edit value manually"
 msg_error="ERROR!"
@@ -74,9 +75,8 @@ msg_group_not_found="%s: Group not found
 msg_group_password="Group Password"
 msg_group_passwords_do_not_match="Group Passwords do not match."
 msg_group_updated="Group Updated"
+msg_groups="Groups"
 msg_home_directory="Home Directory"
-msg_invalid_number_of_days="Invalid number of days."
-msg_invalid_number_of_seconds="Invalid number of seconds."
 msg_login="Login"
 msg_login_added="Login Added"
 msg_login_already_used="%s: Login is already used."
@@ -85,23 +85,28 @@ msg_login_deleted="Login Deleted"
 msg_login_is_empty="Login is empty."
 msg_login_management="Login/Group Management"
 msg_login_must_start_with_letter="Login must start with a letter."
-msg_login_not_found="Login not found."
+msg_login_not_found="%s: Login not found."
 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_no_user_specified="No user 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"
 msg_password_does_not_expire="Password does not expire"
-msg_password_expires_in_how_many_days="Password expires in how many days?"
+msg_password_expire_manual_edit="Enter password expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
 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_please_enter_a_user_name="Please enter a user name!"
 msg_reenter_group_password="Re-enter Group Password"
 msg_reenter_password="Re-enter Password"
 msg_save="Save"
 msg_save_exit_or_cancel="Choose Save/Exit when finished or Cancel."
 msg_select_group_members_from_list="Select Group Members from a list"
+msg_select_groups_from_list="Select Groups from a list"
 msg_select_login_shell="Select Login Shell"
 msg_separated_by_commas="Separated by commas"
 msg_shell="Shell"

Modified: stable/10/usr.sbin/bsdconfig/usermgmt/share/Makefile
==============================================================================
--- stable/10/usr.sbin/bsdconfig/usermgmt/share/Makefile	Mon Mar 31 21:04:15 2014	(r263979)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/share/Makefile	Tue Apr  1 00:19:13 2014	(r263980)
@@ -3,7 +3,7 @@
 NO_OBJ=
 
 FILESDIR=	${SHAREDIR}/bsdconfig/usermgmt
-FILES=		group_input.subr user_input.subr
+FILES=		group.subr group_input.subr user.subr user_input.subr
 
 beforeinstall:
 	mkdir -p ${DESTDIR}${FILESDIR}

Copied and modified: stable/10/usr.sbin/bsdconfig/usermgmt/share/group.subr (from r262904, head/usr.sbin/bsdconfig/usermgmt/share/group.subr)
==============================================================================
--- head/usr.sbin/bsdconfig/usermgmt/share/group.subr	Fri Mar  7 20:44:19 2014	(r262904, copy source)
+++ stable/10/usr.sbin/bsdconfig/usermgmt/share/group.subr	Tue Apr  1 00:19:13 2014	(r263980)
@@ -96,6 +96,10 @@ f_group_add()
 		[ "$group_name" ] ||
 			f_show_err "$msg_please_enter_a_group_name"
 	done
+	if [ ! "$group_name" ]; then
+		f_show_err "$msg_no_group_specified"
+		return $FAILURE
+	fi
 
 	local group_password group_gid group_members
 	f_getvar $VAR_GROUP_PASSWORD	group_password
@@ -152,10 +156,17 @@ f_group_add()
 
 			case "$mtag" in
 			X) # Add/Exit
-			   local cmd="pw groupadd -n '$group_name'"
-			   [ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+			   local var
+			   for var in gid members name; do
+			   	local _group_$var
+			   	eval f_shell_escape \
+			   		\"\$group_$var\" _group_$var
+			   done
+
+			   local cmd="pw groupadd -n '$_group_name'"
+			   [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
 			   [ "$group_members" ] &&
-			   	cmd="$cmd -M '$group_members'"
+			   	cmd="$cmd -M '$_group_members'"
 
 			   # Execute the command (break on success)
 			   if [ "$group_password_disable" ]; then
@@ -163,7 +174,7 @@ f_group_add()
 			   elif [ "$group_password" ]; then
 			   	echo "$group_password" |
 			   		f_eval_catch $funcname \
-			   		pw '%s -h 0' "$cmd"
+			   			pw '%s -h 0' "$cmd"
 			   else
 			   	f_eval_catch $funcname pw '%s' "$cmd"
 			   fi && break
@@ -192,18 +203,24 @@ f_group_add()
 			esac
 		done
 	else
+		local var
+		for var in gid members name; do
+			local _group_$var
+			eval f_shell_escape \"\$group_$var\" _group_$var
+		done
+
 		# Form the command
-		local cmd="pw groupadd -n '$group_name'"
-		[ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
-		[ "$group_members" ] && cmd="$cmd -M '$group_members'"
+		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"
+			err=$( echo "$group_password" | f_eval_catch -de \
+				$funcname pw '%s -h 0' "$cmd" 2>&1 )
 		else
 			f_eval_catch -k err $funcname pw '%s' "$cmd"
 		fi
@@ -217,7 +234,7 @@ f_group_add()
 	f_dialog_title "$title"
 	$alert "$msg_group_added"
 	f_dialog_title_restore
-	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 2
+	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
 
 	return $SUCCESS
 }
@@ -272,8 +289,10 @@ f_group_delete()
 
 			case "$mtag" in
 			X) # Delete/Exit
+			   local _group_name
+			   f_shell_escape "$group_name" _group_name
 			   f_eval_catch $funcname pw 'pw groupdel "%s"' \
-					"$group_name" && break
+					"$_group_name" && break
 			   ;;
 			1) # Group Name (select different group from list)
 			   f_dialog_menu_group_list "$group_name" || continue
@@ -292,9 +311,10 @@ f_group_delete()
 			esac
 		done
 	else
-		local retval err
+		local retval err _group_name
+		f_shell_escape "$group_name" _group_name
 		f_eval_catch -k err $funcname pw \
-			'pw groupdel "%s"' "$group_name"
+			"pw groupdel '%s'" "$_group_name"
 		retval=$?
 		if [ $retval -ne $SUCCESS ]; then
 			f_show_err "%s" "$err"
@@ -305,7 +325,7 @@ f_group_delete()
         f_dialog_title "$title"
 	$alert "$msg_group_deleted"
 	f_dialog_title_restore
-	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 2
+	[ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
 
 	return $SUCCESS
 }
@@ -324,7 +344,9 @@ f_group_delete()
 # 		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.
+# 		If set but NULL, group memberships are reset (no users will be
+# 		a member of this group). If 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.
@@ -400,18 +422,24 @@ f_group_edit()
 
 			case "$mtag" in
 			X) # Save/Exit
-			   local cmd="pw groupmod -n '$group_name'"
-			   [ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+			   local var
+			   for var in gid members name; do
+			   	local _group_$var
+			   	eval f_shell_escape \
+			   		\"\$group_$var\" _group_$var
+			   done
+
+			   local cmd="pw groupmod -n '$_group_name'"
+			   [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
 			   [ "$group_members" -o "$null_members" ] &&
-			   	cmd="$cmd -M '$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"
+			   	echo "$group_password" | f_eval_catch \
+			   		$funcname pw '%s -h 0' "$cmd"
 			   else
 			   	f_eval_catch $funcname pw '%s' "$cmd"
 			   fi && break
@@ -424,7 +452,7 @@ f_group_edit()
 
 			   if ! f_input_group "$mtag"; then
 			   	f_show_err "$msg_group_not_found" "$mtag"
-			   	# Attempt to fall back to prevoius selection
+			   	# Attempt to fall back to previous selection
 			   	f_input_group "$input" || return $FAILURE
 			   else
 			   	input="$mtag"
@@ -446,19 +474,25 @@ f_group_edit()
 			esac

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


More information about the svn-src-all mailing list