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.
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to