From owner-freebsd-rc@FreeBSD.ORG Tue Nov 9 07:23:31 2010 Return-Path: Delivered-To: freebsd-rc@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 88B06106566B for ; Tue, 9 Nov 2010 07:23:31 +0000 (UTC) (envelope-from dteske@vicor.com) Received: from postoffice.vicor.com (postoffice.vicor.com [69.26.56.53]) by mx1.freebsd.org (Postfix) with ESMTP id 2D0138FC0A for ; Tue, 9 Nov 2010 07:23:30 +0000 (UTC) Received: from [173.241.24.124] (port=49583 helo=[10.0.0.109]) by postoffice.vicor.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.71) (envelope-from ) id 1PFiY9-0007BQ-BD; Mon, 08 Nov 2010 23:23:30 -0800 Mime-Version: 1.0 (Apple Message framework v1081) From: Devin Teske In-Reply-To: <1288919368.7362.35.camel@localhost.localdomain> Date: Mon, 8 Nov 2010 23:23:23 -0800 Message-Id: <11FDD7C3-4451-47BD-AE01-58952ACFF586@vicor.com> References: <1286925182.32724.18.camel@localhost.localdomain> <1286996709.32724.60.camel@localhost.localdomain> <1287448781.5713.3.camel@localhost.localdomain> <1287510629.25599.2.camel@localhost.localdomain> <1288746388.7362.4.camel@localhost.localdomain> <17B64023-A64A-40DA-9CBC-A601710AB5BB@vicor.com> <1288919368.7362.35.camel@localhost.localdomain> To: Devin Teske X-Mailer: Apple Mail (2.1081) X-Scan-Signature: 0a4055a72ae5c7848cb83e0bf4da5446 X-Scan-Host: postoffice.vicor.com Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: freebsd-rc@freebsd.org Subject: Re: sysrc(8) -- a sysctl(8)-like utility for managing rc.conf(5) X-BeenThere: freebsd-rc@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Discussion related to /etc/rc.d design and implementation." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Nov 2010 07:23:31 -0000 On Nov 4, 2010, at 6:09 PM, Devin Teske wrote: > And now... for the piece de resistance! >=20 >> ... >=20 > Woohoo... version 3.0! 3.1 now. > This version completely does-away with sed(1), replacing entire swaths > of code with embedded awk(1) scripts. >=20 > This gives the script a much-needed performance boost (quantifiably > about 623-648% increase in performance given `-Ad' flags on a standard > system). And now, 161% increase beyond _that_ (`-Ad' now completes in 2.3 seconds = on my system). ^_^ >>>>>>> Direct links: >>>>>>> http://druidbsd.sf.net/download/sysrc.gz (download gzipped) >>>>>>> http://druidbsd.sf.net/download/sysrc.txt (view as text) > And here's that good-ol' unified patch to show what's changed... --- sysrc.3_0 2010-11-04 17:48:17.000000000 -0700 +++ sysrc 2010-11-08 22:56:20.000000000 -0800 @@ -2,8 +2,8 @@ # -*- tab-width: 4 -*- ;; Emacs # vi: set tabstop=3D4 :: Vi/ViM # -# Revision: 3.0 -# Last Modified: November 4th, 2010 +# Revision: 3.1 +# Last Modified: November 8th, 2010 ############################################################ COPYRIGHT # # (c)2010. Devin Teske. All Rights Reserved. @@ -30,6 +30,7 @@ # SUCH DAMAGE. # # AUTHOR DATE DESCRIPTION +# dteske 2010.11.08 Further significant performance enhancements. # dteske 2010.11.04 Add taint checking. # dteske 2010.11.04 Comments. # dteske 2010.11.04 Significant performance enhancements. @@ -83,6 +84,13 @@ # # *optional # +# Special Thanks to (in order of appearance): +# Brandon Gooch - name suggestion +# Garrett Cooper - structure/mktemp = suggestions +# Julian Elischer - jail suggestions +# Pawel Jakub Dawidek - security suggestions +# Cyrille Lefevre - awk = suggestions +# ############################################################ = CONFIGURATION =20 # @@ -418,6 +426,68 @@ sysrc_find() # does not appear in the source file, it is appended to the end of the = primary # system configuration file `/etc/rc.conf'. # +# 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. +# +sysrc_set_awk=3D' +# Variables that should be defined on the invocation line: +# -v varname=3D"varname" +# -v new_value=3D"new_value" +# +BEGIN { + regex =3D "^[[:space:]]*"varname"=3D" + retval =3D found =3D 0 +} +{ + # If already found... just spew + if ( found ) { print; next } + + # Does this line match an assignment to our variable? + if ( ! match($0, regex) ) { print; next } + + # Save important match information + found =3D 1 + matchlen =3D RSTART + RLENGTH - 1 + + # Store the value text for later munging + value =3D substr($0, matchlen + 1, length($0) - matchlen) + + # Store the first character of the value + t1 =3D t2 =3D substr(value, 0, 1) + + # Assignment w/ back-ticks, expression, or misc. + # We ignore these since we did not generate them + # + if ( t1 ~ /[\`$\\]/ ) { retval =3D 1; print; next } + + # Assignment w/ single-quoted value + else if ( t1 =3D=3D "'\''" ) { + sub(/^'\''[^'\'']*/, "", value) + if ( length(value) =3D=3D 0 ) t2 =3D "" + sub(/^'\''/, "", value) + } + + # Assignment w/ double-quoted value + else if ( t1 =3D=3D "\"" ) { + sub(/^"(.*\\\\+")*[^"]*/, "", value) + if ( length(value) =3D=3D 0 ) t2 =3D "" + sub(/^"/, "", value) + } + + # Assignment w/ non-quoted value + else if ( t1 ~ /[^[:space:];#]/ ) { + t1 =3D t2 =3D "\"" + sub(/^[^[:space:]]*/, "", value) + } + + # Null-assignment + else if ( t1 ~ /[[:space:]];#]/ ) { t1 =3D t2 =3D "\"" } + + printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ + t1, new_value, t2, value +} +END { exit retval } +' sysrc_set() { local varname=3D"$1" new_value=3D"$2" @@ -495,77 +565,12 @@ sysrc_set() | awk '{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); print }' = )" =20 # - # Generate an awk(1) script to find/replace the appropriate = line. - # If a line suitable-of-replacement is not found, awk will = return - # error-status, indicating that we should append the new value. - # - - local awkscript apos=3D"'" quot=3D'"' bquot=3D'\"' bbtick=3D'\`' - local regex=3D"^[[:space:]]*$varname=3D" - #NOTE: This should be the same regex as used by = sysrc_find() - - awkscript=3D$( cat << EOF - BEGIN { retval =3D 0; found =3D 0 } - { - # If already found... just spew - if ( found ) { print; next } - - # Does this line match an assignment to our variable? - if ( ! match(\$0, /$regex/) ) { print; next } - - # Save important match information - found =3D 1 - matchlen =3D RSTART + RLENGTH - 1 - - # Store the value text for later munging - value =3D substr(\$0, matchlen + 1, length(\$0) - = matchlen) - - # Store the first character of the value - t1 =3D t2 =3D substr(value, 0, 1) - - # Assignment w/ back-ticks, expression, or misc. - # We ignore these since we did not generate them - # - if ( t1 ~ /[$bbtick\\\$\\\\]/ ) - { retval =3D 1; print; next } - - # Assignment w/ single-quoted value - else if ( t1 =3D=3D "$apos" ) { - sub(/^$apos[^$apos]*/, "", value) - if ( length(value) =3D=3D 0 ) t2 =3D "" - sub(/^$apos/, "", value) - } - - # Assignment w/ double-quoted value - else if ( t1 =3D=3D "$bquot" ) { - sub(/^$quot(.*\\\\+$quot)*[^$quot]*/, "", value) - if ( length(value) =3D=3D 0 ) t2 =3D "" - sub(/^$quot/, "", value) - } - - # Assignment w/ non-quoted value - else if ( t1 ~ /[^[:space:];#]/ ) { - t1 =3D t2 =3D "$bquot" - sub(/^[^[:space:]]*/, "", value) - } - - # Null-assignment - else if ( t1 ~ /[[:space:]];#]/ ) - { t1 =3D t2 =3D "$bquot" } - - printf "%s%c%s%c%s\n", substr(\$0, 0, matchlen), \ - t1, "$awk_new_value", t2, value - } - END { exit retval } -EOF - ) - - # # Operate on the matching file, replacing only the last = occurrence. # local new_contents retval new_contents=3D$( tail -r $file 2> /dev/null ) - new_contents=3D$( echo "$new_contents" | awk "$awkscript" ) + new_contents=3D$( echo "$new_contents" | awk -v = varname=3D"$varname" \ + -v new_value=3D"$new_value" "$sysrc_set_awk" ) retval=3D$? =20 # @@ -600,47 +605,49 @@ EOF # Multi-line comments are joined together. Results are NULL if no = description # could be found. # -sysrc_desc() +# 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. +# +sysrc_desc_awk=3D' +# Variables that should be defined on the invocation line: +# -v varname=3D"varname" +# +BEGIN { + regex =3D "^[[:space:]]*"varname"=3D" + found =3D 0 + buffer =3D "" +} { - local varname=3D"$1" - local regex=3D"^[[:space:]]*$varname=3D" - local vregex=3D"[[:space:]]*[[:alpha:]_][[:alnum:]_]*" - local awkscript - - awkscript=3D$( cat << EOF - BEGIN { found =3D 0; buffer =3D "" } + if ( ! found ) { - if ( ! found ) - { - if ( ! match(\$0, /$regex/) ) next - - found =3D 1 - sub(/^[^#]*(#[[:space:]]*)?/, "") - buffer =3D \$0 - next - } - - if ( !/^[[:space:]]*#/ || - /^[[:space:]]*$vregex=3D/ || - /^[[:space:]]*#$vregex=3D/ || - /^[[:space:]]*$/ ) exit + if ( ! match($0, regex) ) next =20 - sub(/(.*#)*[[:space:]]*/, "") - buffer =3D buffer" "\$0 + found =3D 1 + sub(/^[^#]*(#[[:space:]]*)?/, "") + buffer =3D $0 + next } - END \ - { - # Clean up the buffer - sub(/^[[:space:]]*/, "", buffer) - sub(/[[:space:]]*$/, "", buffer) =20 - print buffer - exit ! found - } -EOF - ) + if ( !/^[[:space:]]*#/ || + /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=3D/ || + /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=3D/ || + /^[[:space:]]*$/ ) exit + + sub(/(.*#)*[[:space:]]*/, "") + buffer =3D buffer" "$0 +} +END { + # Clean up the buffer + sub(/^[[:space:]]*/, "", buffer) + sub(/[[:space:]]*$/, "", buffer) =20 - awk "$awkscript" < "$RC_DEFAULTS" + print buffer + exit ! found +} +' +sysrc_desc() +{ + awk -v varname=3D"$1" "$sysrc_desc_awk" < "$RC_DEFAULTS" } =20 ############################################################ MAIN = SOURCE @@ -815,7 +822,7 @@ if [ "$SHOW_ALL" ]; then IFS=3D"$IFS|" EXCEPT=3D"IFS|EXCEPT|PATH|RC_DEFAULTS|OPTIND|DESCRIBE|SEP"= = EXCEPT=3D"$EXCEPT|SHOW_ALL|SHOW_EQUALS|SHOW_NAME|SHOW_VALUE" - EXCEPT=3D"$EXCEPT|SYSRC_VERBOSE|RC_CONFS" + EXCEPT=3D"$EXCEPT|SYSRC_VERBOSE|RC_CONFS|sysrc_desc_awk" =20 # # Clean the environment (except for our required = variables) -- Cheers, Devin Teske -> CONTACT INFORMATION <- Business Solutions Consultant II FIS - fisglobal.com 510-735-5650 Mobile 510-621-2038 Office 510-621-2020 Office Fax 909-477-4578 Home/Fax devin.teske@fisglobal.com -> LEGAL DISCLAIMER <- This message contains confidential and proprietary information of the sender, and is intended only for the person(s) to whom it is addressed. Any use, distribution, copying or disclosure by any other person is strictly prohibited. If you have received this message in error, please notify the e-mail sender immediately, and delete the original message without making a copy. -> FUN STUFF <- -----BEGIN GEEK CODE BLOCK----- Version 3.1 GAT/CS d(+) s: a- C++(++++) UB++++$ P++(++++) L++(++++) !E--- W++ N? o? = K- w O M+ V- PS+ PE Y+ PGP- t(+) 5? X+(++) R>++ tv(+) b+(++) DI+(++) D(+) G+>++ = e>+ h r>++ y+=20 ------END GEEK CODE BLOCK------ http://www.geekcode.com/ -> END TRANSMISSION <-