Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Nov 2010 23:23:23 -0800
From:      Devin Teske <dteske@vicor.com>
To:        Devin Teske <dteske@vicor.com>
Cc:        freebsd-rc@freebsd.org
Subject:   Re: sysrc(8) -- a sysctl(8)-like utility for managing rc.conf(5)
Message-ID:  <11FDD7C3-4451-47BD-AE01-58952ACFF586@vicor.com>
In-Reply-To: <1288919368.7362.35.camel@localhost.localdomain>
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> <D763F474-8F19-4C65-B23F-78C9B137A8FE@vicor.com> <1288746388.7362.4.camel@localhost.localdomain> <17B64023-A64A-40DA-9CBC-A601710AB5BB@vicor.com> <1288919368.7362.35.camel@localhost.localdomain>

next in thread | previous in thread | raw e-mail | index | archive | help

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 <jamesbrandongooch@gmail.com> - name suggestion
+# 	Garrett Cooper <gcooper@freebsd.org> - structure/mktemp =
suggestions
+# 	Julian Elischer <julian@freebsd.org> - jail suggestions
+# 	Pawel Jakub Dawidek <pjd@freebsd.org> - security suggestions
+# 	Cyrille Lefevre <cyrille.lefevre-lists@laposte.net> - 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 <-




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?11FDD7C3-4451-47BD-AE01-58952ACFF586>