Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Apr 2014 22:40:29 +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: r264243 - in head/etc: . rc.d
Message-ID:  <201404072240.s37MeTqo085123@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dteske
Date: Mon Apr  7 22:40:29 2014
New Revision: 264243
URL: http://svnweb.freebsd.org/changeset/base/264243

Log:
  Loosen the processing of *_IF_aliasN vars to be less strict. Previously,
  the first alias had to be _alias0 and processing stopped at the first non-
  defined variable (preventing gaps). Allowing gaps gives the administrator
  the ability to group aliases in an adhoc manner and also lifts the
  requirement to renumber aliases simply to comment-out an existing one.
  Aliases are processed in numerical ascending order.
  
  Discussed on:	-rc
  MFC after:	1 week

Modified:
  head/etc/network.subr
  head/etc/rc.d/mdconfig
  head/etc/rc.d/mdconfig2
  head/etc/rc.subr

Modified: head/etc/network.subr
==============================================================================
--- head/etc/network.subr	Mon Apr  7 22:37:13 2014	(r264242)
+++ head/etc/network.subr	Mon Apr  7 22:40:29 2014	(r264243)
@@ -283,10 +283,8 @@ get_if_var()
 	fi
 
 	_if=$1
-	_punct=". - / +"
-	for _punct_c in $_punct; do
-		_if=`ltr ${_if} ${_punct_c} '_'`
-	done
+	_punct=".-/+"
+	ltr ${_if} "${_punct}" '_' _if
 	_var=$2
 	_default=$3
 
@@ -1076,6 +1074,7 @@ ifalias_af_common_handler()
 ifalias_af_common()
 {
 	local _ret _if _af _action alias ifconfig_args _aliasn _c _tmpargs _iaf
+	local _punct=".-/+"
 
 	_ret=1
 	_aliasn=
@@ -1083,10 +1082,14 @@ ifalias_af_common()
 	_af=$2
 	_action=$3
 
+	# Normalize $_if before using it in a pattern to list_vars()
+	ltr "$_if" "$_punct" "_" _if
+
 	# ifconfig_IF_aliasN which starts with $_af
-	alias=0
-	while : ; do
-		ifconfig_args=`get_if_var $_if ifconfig_IF_alias${alias}`
+	for alias in `list_vars ifconfig_${_if}_alias[0-9]\* |
+		sort_lite -nk1.$((9+${#_if}+7))`
+	do
+		eval ifconfig_args=\"\$$alias\"
 		_iaf=
 		case $ifconfig_args in
 		inet\ *)	_iaf=inet ;;
@@ -1107,15 +1110,15 @@ ifalias_af_common()
 			warn "\$ifconfig_${_if}_alias${alias} needs " \
 			    "\"inet\" keyword for an IPv4 address."
 		esac
-		alias=$(($alias + 1))
 	done
 
 	# backward compatibility: ipv6_ifconfig_IF_aliasN.
 	case $_af in
 	inet6)
-		alias=0
-		while : ; do
-			ifconfig_args=`get_if_var $_if ipv6_ifconfig_IF_alias${alias}`
+		for alias in `list_vars ipv6_ifconfig_${_if}_alias[0-9]\* |
+			sort_lite -nk1.$((14+${#_if}+7))`
+		do
+			eval ifconfig_args=\"\$$alias\"
 			case ${_action}:"${ifconfig_args}" in
 			*:"")
 				break
@@ -1127,7 +1130,6 @@ ifalias_af_common()
 				    "instead."
 			;;
 			esac
-			alias=$(($alias + 1))
 		done
 	esac
 

Modified: head/etc/rc.d/mdconfig
==============================================================================
--- head/etc/rc.d/mdconfig	Mon Apr  7 22:37:13 2014	(r264242)
+++ head/etc/rc.d/mdconfig	Mon Apr  7 22:40:29 2014	(r264243)
@@ -181,17 +181,14 @@ fi
 
 load_rc_config $name
 
-_mdconfig_unit=0
 if [ -z "${_mdconfig_list}" ]; then
-	while :; do
-		eval _mdconfig_config=\$mdconfig_md${_mdconfig_unit}
-		if [ -z "${_mdconfig_config}" ]; then
-			break
-		else
-			_mdconfig_list="${_mdconfig_list}${_mdconfig_list:+ }md${_mdconfig_unit}"
-			_mdconfig_unit=$((${_mdconfig_unit} + 1))
-		fi
+	for _mdconfig_config in `list_vars mdconfig_md[0-9]\* |
+		sort_lite -nk1.12`
+	do
+		_mdconfig_unit=${_mdconfig_config#mdconfig_md}
+		_mdconfig_list="$_mdconfig_list md$_mdconfig_unit"
 	done
+	_mdconfig_list="${_mdconfig_list# }"
 fi
 
 run_rc_command "${_mdconfig_cmd}"

Modified: head/etc/rc.d/mdconfig2
==============================================================================
--- head/etc/rc.d/mdconfig2	Mon Apr  7 22:37:13 2014	(r264242)
+++ head/etc/rc.d/mdconfig2	Mon Apr  7 22:40:29 2014	(r264243)
@@ -211,17 +211,14 @@ fi
 
 load_rc_config $name
 
-_mdconfig2_unit=0
 if [ -z "${_mdconfig2_list}" ]; then
-	while :; do
-		eval _mdconfig2_config=\$mdconfig_md${_mdconfig2_unit}
-		if [ -z "${_mdconfig2_config}" ]; then
-			break
-		else
-			_mdconfig2_list="${_mdconfig2_list}${_mdconfig2_list:+ }md${_mdconfig2_unit}"
-			_mdconfig2_unit=$((${_mdconfig2_unit} + 1))
-		fi
+	for _mdconfig2_config in `list_vars mdconfig_md[0-9]\* |
+		sort_lite -nk1.12`
+	do
+		_mdconfig2_unit=${_mdconfig2_config#mdconfig_md}
+		_mdconfig2_list="$_mdconfig2_list md$_mdconfig2_unit"
 	done
+	_mdconfig2_list="${_mdconfig2_list# }"
 fi
 
 run_rc_command "${_mdconfig2_cmd}"

Modified: head/etc/rc.subr
==============================================================================
--- head/etc/rc.subr	Mon Apr  7 22:37:13 2014	(r264242)
+++ head/etc/rc.subr	Mon Apr  7 22:40:29 2014	(r264243)
@@ -54,6 +54,20 @@ JID=`$PS -p $$ -o jid=`
 #	functions
 #	---------
 
+# list_vars pattern
+#	List vars matching pattern.
+# 
+list_vars()
+{
+	set | { while read LINE; do
+		var="${LINE%%=*}"
+		case "$var" in
+		"$LINE"|*[!a-zA-Z0-9_]*) continue ;;
+		$1) echo $var
+		esac
+	done; }
+}
+
 # set_rcvar_obsolete oldvar [newvar] [msg]
 #	Define obsolete variable.
 #	Global variable $rcvars_obsolete is used.
@@ -314,6 +328,246 @@ _find_processes()
 	eval $_proccheck
 }
 
+# sort_lite [-b] [-n] [-k POS] [-t SEP]
+#	A lite version of sort(1) (supporting a few options) that can be used
+#	before the real sort(1) is available (e.g., in scripts that run prior
+#	to mountcritremote). Requires only shell built-in functionality.
+#
+sort_lite()
+{
+	local funcname=sort_lite
+	local sort_sep="$IFS" sort_ignore_leading_space=
+	local sort_field=0 sort_strict_fields= sort_numeric=
+	local nitems=0 skip_leading=0 trim=
+
+	local OPTIND flag
+	while getopts bnk:t: flag; do
+		case "$flag" in
+		b) sort_ignore_leading_space=1 ;;
+		n) sort_numeric=1 sort_ignore_leading_space=1 ;;
+		k) sort_field="${OPTARG%%,*}" ;; # only up to first comma
+			# NB: Unlike sort(1) only one POS allowed
+		t) sort_sep="$OPTARG"
+		   if [ ${#sort_sep} -gt 1 ]; then
+		   	echo "$funcname: multi-character tab \`$sort_sep'" >&2
+		   	return 1
+		   fi
+		   sort_strict_fields=1
+		   ;;
+		\?) return 1 ;;
+		esac
+	done
+	shift $(( $OPTIND - 1 ))
+
+	# Create transformation pattern to trim leading text if desired
+	case "$sort_field" in
+	""|[!0-9]*|*[!0-9.]*)
+		echo "$funcname: invalid sort field \`$sort_field'" >&2
+		return 1
+		;;
+	*.*)
+		skip_leading=${sort_field#*.} sort_field=${sort_field%%.*}
+		while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do
+			trim="$trim?" skip_leading=$(( $skip_leading - 1 ))
+		done
+	esac
+
+	# Copy input to series of local numbered variables
+	# NB: IFS of NULL preserves leading whitespace
+	local LINE
+	while IFS= read -r LINE || [ "$LINE" ]; do
+		nitems=$(( $nitems + 1 ))
+		local src_$nitems="$LINE"
+	done
+
+	#
+	# Sort numbered locals using insertion sort
+	#
+	local curitem curitem_orig curitem_mod curitem_haskey
+	local dest dest_orig dest_mod dest_haskey
+	local d gt n
+	local i=1 
+	while [ $i -le $nitems ]; do
+		curitem_haskey=1 # Assume sort field (-k POS) exists
+		eval curitem=\"\$src_$i\"
+		curitem_mod="$curitem" # for modified comparison
+		curitem_orig="$curitem" # for original comparison
+
+		# Trim leading whitespace if desired
+		if [ "$sort_ignore_leading_space" ]; then
+			while case "$curitem_orig" in
+				[$IFS]*) : ;; *) false; esac
+			do
+				curitem_orig="${curitem_orig#?}"
+			done
+			curitem_mod="$curitem_orig"
+		fi
+
+		# Shift modified comparison value if sort field (-k POS) is > 1
+		n=$sort_field
+		while [ $n -gt 1 ]; do
+			case "$curitem_mod" in
+			*[$sort_sep]*)
+				# Cut text up-to (and incl.) first separator
+				curitem_mod="${curitem_mod#*[$sort_sep]}"
+
+				# Skip NULLs unless strict field splitting
+				[ "$sort_strict_fields" ] ||
+					[ "${curitem_mod%%[$sort_sep]*}" ] ||
+					[ $n -eq 2 ] ||
+					continue
+				;;
+			*)
+				# Asked for a field that doesn't exist
+				curitem_haskey= break
+			esac
+			n=$(( $n - 1 ))
+		done
+
+		# Trim trailing words if sort field >= 1
+		[ $sort_field -ge 1 -a "$sort_numeric" ] &&
+			curitem_mod="${curitem_mod%%[$sort_sep]*}"
+
+		# Apply optional trim (-k POS.TRIM) to cut leading characters
+		curitem_mod="${curitem_mod#$trim}"
+
+		# Determine the type of modified comparison to use initially
+		# NB: Prefer numerical if requested but fallback to standard
+		case "$curitem_mod" in
+		""|[!0-9]*) # NULL or begins with non-number
+			gt=">"
+			[ "$sort_numeric" ] && curitem_mod=0
+			;;
+		*)
+			if [ "$sort_numeric" ]; then
+				gt="-gt"
+				curitem_mod="${curitem_mod%%[!0-9]*}"
+					# NB: trailing non-digits removed
+					# otherwise numeric comparison fails
+			else
+				gt=">"
+			fi
+		esac
+
+		# If first time through, short-circuit below position-search
+		if [ $i -le 1 ]; then
+			d=0
+		else
+			d=1
+		fi
+
+		#
+		# Find appropriate element position
+		#
+		while [ $d -gt 0 ]
+		do
+			dest_haskey=$curitem_haskey
+			eval dest=\"\$dest_$d\"
+			dest_mod="$dest" # for modified comparison
+			dest_orig="$dest" # for original comparison
+
+			# Trim leading whitespace if desired
+			if [ "$sort_ignore_leading_space" ]; then
+				while case "$dest_orig" in
+					[$IFS]*) : ;; *) false; esac
+				do
+					dest_orig="${dest_orig#?}"
+				done
+				dest_mod="$dest_orig"
+			fi
+
+			# Shift modified value if sort field (-k POS) is > 1
+			n=$sort_field
+			while [ $n -gt 1 ]; do
+				case "$dest_mod" in
+				*[$sort_sep]*)
+					# Cut text up-to (and incl.) 1st sep
+					dest_mod="${dest_mod#*[$sort_sep]}"
+
+					# Skip NULLs unless strict fields
+					[ "$sort_strict_fields" ] ||
+					    [ "${dest_mod%%[$sort_sep]*}" ] ||
+					    [ $n -eq 2 ] ||
+					    continue
+					;;
+				*)
+					# Asked for a field that doesn't exist
+					dest_haskey= break
+				esac
+				n=$(( $n - 1 ))
+			done
+
+			# Trim trailing words if sort field >= 1
+			[ $sort_field -ge 1 -a "$sort_numeric" ] &&
+				dest_mod="${dest_mod%%[$sort_sep]*}"
+
+			# Apply optional trim (-k POS.TRIM), cut leading chars
+			dest_mod="${dest_mod#$trim}"
+
+			# Determine type of modified comparison to use
+			# NB: Prefer numerical if requested, fallback to std
+			case "$dest_mod" in
+			""|[!0-9]*) # NULL or begins with non-number
+				gt=">"
+				[ "$sort_numeric" ] && dest_mod=0
+				;;
+			*)
+				if [ "$sort_numeric" ]; then
+					gt="-gt"
+					dest_mod="${dest_mod%%[!0-9]*}"
+						# NB: kill trailing non-digits
+						# for numeric comparison safety
+				else
+					gt=">"
+				fi
+			esac
+
+			# Break if we've found the proper element position
+			if [ "$curitem_haskey" -a "$dest_haskey" ]; then
+				if [ "$dest_mod" = "$curitem_mod" ]; then
+					[ "$dest_orig" ">" "$curitem_orig" ] &&
+						break
+				elif [ "$dest_mod" $gt "$curitem_mod" ] \
+					2> /dev/null
+				then
+					break
+				fi
+			else
+				[ "$dest_orig" ">" "$curitem_orig" ] && break
+			fi
+
+			# Break if we've hit the end
+			[ $d -ge $i ] && break
+
+			d=$(( $d + 1 ))
+		done
+
+		# Shift remaining positions forward, making room for new item
+		n=$i
+		while [ $n -ge $d ]; do
+			# Shift destination item forward one placement
+			eval dest_$(( $n + 1 ))=\"\$dest_$n\"
+			n=$(( $n - 1 ))
+		done
+
+		# Place the element
+		if [ $i -eq 1 ]; then
+			local dest_1="$curitem"
+		else
+			local dest_$d="$curitem"
+		fi
+
+		i=$(( $i + 1 ))
+	done
+
+	# Print sorted results
+	d=1
+	while [ $d -le $nitems ]; do
+		eval echo \"\$dest_$d\"
+		d=$(( $d + 1 ))
+	done
+}
+
 #
 # wait_for_pids pid [pid ...]
 #	spins until none of the pids exist
@@ -1524,19 +1778,20 @@ load_kld()
 	return 0
 }
 
-# ltr str src dst
+# ltr str src dst [var]
 #	Change every $src in $str to $dst.
 #	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
-#	awk(1).
+#	awk(1). If var is non-NULL, set it to the result.
 ltr()
 {
-	local _str _src _dst _out _com
-	_str=$1
-	_src=$2
-	_dst=$3
+	local _str _src _dst _out _com _var
+	_str="$1"
+	_src="$2"
+	_dst="$3"
+	_var="$4"
 	_out=""
 
-	IFS=${_src}
+	local IFS="${_src}"
 	for _com in ${_str}; do
 		if [ -z "${_out}" ]; then
 			_out="${_com}"
@@ -1544,7 +1799,11 @@ ltr()
 			_out="${_out}${_dst}${_com}"
 		fi
 	done
-	echo "${_out}"
+	if [ -n "${_var}" ]; then
+		setvar "${_var}" "${_out}"
+	else
+		echo "${_out}"
+	fi
 }
 
 # Creates a list of providers for GELI encryption.



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