git: eaeb5f29bc6f - main - sysrc: make independant from bsdconfig(8)

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Mon, 14 Sep 2026 13:42:42 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=eaeb5f29bc6f4ff31026b12bd2329699a066c68b

commit eaeb5f29bc6f4ff31026b12bd2329699a066c68b
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2026-04-15 09:41:09 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2026-09-14 13:42:27 +0000

    sysrc: make independant from bsdconfig(8)
    
    MFC After:      1 week
    Approved by:    dteske
    Reviewed by:    dteske
    Differential Revision:  https://reviews.freebsd.org/D59658
---
 MAINTAINERS                         |   2 +-
 UPDATING                            |   5 +
 packages/bsdconfig/bsdconfig.ucl    |   3 -
 usr.sbin/bsdconfig/share/sysrc.subr | 719 +----------------------------
 usr.sbin/sysrc/Makefile             |   5 +-
 usr.sbin/sysrc/sysrc                |  12 +-
 usr.sbin/sysrc/sysrc.subr           | 898 ++++++++++++++++++++++++++++++++++++
 7 files changed, 916 insertions(+), 728 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index fd514a085ae1..a695641a0dac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -129,7 +129,7 @@ top(1)		eadler	Pre-commit review requested.
 ufshci(4)	jaeyoon	Pre-commit review requested.
 usr.sbin/bsdconfig	dteske	Pre-commit phabricator review requested.
 usr.sbin/pkg	pkg@	Please coordinate behavior or flag changes with pkg team.
-usr.sbin/sysrc	dteske	Pre-commit phabricator review requested. Keep in sync with bsdconfig(8) sysrc.subr.
+usr.sbin/sysrc	dteske	Pre-commit phabricator review requested.
 vmm(4)		#bhyve	Pre-commit review requested via #bhyve phabricator group.
 libvmmapi	#bhyve	Pre-commit review requested via #bhyve phabricator group.
 usr.sbin/bhyve*	#bhyve	Pre-commit review requested via #bhyve phabricator group.
diff --git a/UPDATING b/UPDATING
index de5b9024832f..99c10a9adda1 100644
--- a/UPDATING
+++ b/UPDATING
@@ -27,6 +27,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW:
 	world, or to merely disable the most expensive debugging functionality
 	at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
 
+20260414:
+	sysrc(8) has been moved from the "bsdconfig" package to the "rc"
+	package and no longer depends on bsdconfig at runtime.  For pkgbase
+	users, sysrc is now part of set-minimal instead of set-optional.
+
 20260902:
 	struct if_rxd_info now carries a receive timestamp.  iflib drivers
 	must be rebuilt.  __FreeBSD_version has been bumped to 1600022.
diff --git a/packages/bsdconfig/bsdconfig.ucl b/packages/bsdconfig/bsdconfig.ucl
index ba34e5b96fe9..d712742108e5 100644
--- a/packages/bsdconfig/bsdconfig.ucl
+++ b/packages/bsdconfig/bsdconfig.ucl
@@ -21,7 +21,4 @@ comment = "System configuration utility"
 desc = <<EOD
 bsdconfig(8) provides a simple full-screen interface to manage system
 configuration, including services, networking and disks.
-
-This package also provides sysrc(8), a command-line utility for managing
-the rc.conf(5) configuration.
 EOD
diff --git a/usr.sbin/bsdconfig/share/sysrc.subr b/usr.sbin/bsdconfig/share/sysrc.subr
index 5d2a3cd97f7c..eee489f4cc50 100644
--- a/usr.sbin/bsdconfig/share/sysrc.subr
+++ b/usr.sbin/bsdconfig/share/sysrc.subr
@@ -25,731 +25,22 @@ if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1
 # SUCH DAMAGE.
 #
 #
+# Compatibility shim: sources the canonical sysrc.subr from /usr/share/sysrc/
+# and loads bsdconfig-specific i18n messages afterward.
+#
 ############################################################ INCLUDES
 
 BSDCFG_SHARE="/usr/share/bsdconfig"
 [ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1
 
+f_include /usr/share/sysrc/sysrc.subr
+
 BSDCFG_LIBE="/usr/libexec/bsdconfig"
 if [ ! "$_SYSRC_JAILED" ]; then
 	f_dprintf "%s: loading includes..." sysrc.subr
 	f_include_lang $BSDCFG_LIBE/include/messages.subr
 fi
 
-############################################################ CONFIGURATION
-
-#
-# Standard pathnames (inherit values from shell if available)
-#
-: ${RC_DEFAULTS:="/etc/defaults/rc.conf"}
-
-############################################################ GLOBALS
-
-#
-# Global exit status variables
-#
-SUCCESS=0
-FAILURE=1
-
-#
-# 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
-# these can include accent characters (which are not valid in a variable name).
-# For example, A-Z matches any character that sorts after A but before Z,
-# including A and Z. Although ASCII order would make more sense, that is not
-# how it works.
-#
-VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
-
-############################################################ FUNCTIONS
-
-# f_clean_env [ --except $varname ... ]
-#
-# Unset all environment variables in the current scope. An optional list of
-# arguments can be passed, indicating which variables to avoid unsetting; the
-# `--except' is required to enable the exclusion-list as the remainder of
-# positional arguments.
-#
-# Be careful not to call this in a shell that you still expect to perform
-# $PATH expansion in, because this will blow $PATH away. This is best used
-# within a sub-shell block "(...)" or "$(...)" or "`...`".
-#
-f_clean_env()
-{
-	local var arg except=
-
-	#
-	# Should we process an exclusion-list?
-	#
-	if [ "$1" = "--except" ]; then
-		except=1
-		shift 1
-	fi
-
-	#
-	# Loop over a list of variable names from set(1) built-in.
-	#
-	for var in $( set | awk -F= \
-		'/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \
-		| grep -v '^except$'
-	); do
-		#
-		# In POSIX bourne-shell, attempting to unset(1) OPTIND results
-		# in "unset: Illegal number:" and causes abrupt termination.
-		#
-		[ "$var" = OPTIND ] && continue
-
-		#
-		# Process the exclusion-list?
-		#
-		if [ "$except" ]; then
-			for arg in "$@" ""; do
-				[ "$var" = "$arg" ] && break
-			done
-			[ "$arg" ] && continue
-		fi
-
-		unset "$var"
-	done
-}
-
-# f_sysrc_get $varname
-#
-# Get a system configuration setting from the collection of system-
-# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and
-# /etc/rc.conf.local)
-#
-# NOTE: Additional shell parameter-expansion formats are supported. For
-# example, passing an argument of "hostname%%.*" (properly quoted) will
-# return the hostname up to (but not including) the first `.' (see sh(1),
-# "Parameter Expansion" for more information on additional formats).
-#
-f_sysrc_get()
-{
-	# Sanity check
-	[ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE
-
-	# Taint-check variable name
-	case "$1" in
-	[0-9]*)
-		# Don't expand possible positional parameters
-		return $FAILURE ;;
-	*)
-		[ "$1" ] || return $FAILURE
-	esac
-
-	( # Execute within sub-shell to protect parent environment
-
-		#
-		# Clear the environment of all variables, preventing the
-		# expansion of normals such as `PS1', `TERM', etc.
-		#
-		f_clean_env --except IFS RC_CONFS RC_DEFAULTS
-
-		. "$RC_DEFAULTS" > /dev/null 2>&1
-
-		unset RC_DEFAULTS
-			# no longer needed
-
-		#
-		# If the query is for `rc_conf_files' then store the value that
-		# we inherited from sourcing RC_DEFAULTS (above) so that we may
-		# conditionally restore this value after source_rc_confs in the
-		# event that RC_CONFS does not customize the value.
-		#
-		if [ "$1" = "rc_conf_files" ]; then
-			_rc_conf_files="$rc_conf_files"
-		fi
-
-		#
-		# If RC_CONFS is defined, set $rc_conf_files to an explicit
-		# value, modifying the default behavior of source_rc_confs().
-		#
-		if [ "${RC_CONFS+set}" ]; then
-			rc_conf_files="$RC_CONFS"
-			_rc_confs_set=1
-		fi
-
-		source_rc_confs > /dev/null 2>&1
-
-		#
-		# If the query was for `rc_conf_files' AND after calling
-		# source_rc_confs the value has not changed, then we should
-		# restore the value to the one inherited from RC_DEFAULTS
-		# before performing the final query (preventing us from
-		# returning what was set via RC_CONFS when the intent was
-		# instead to query the value from the file(s) specified).
-		#
-		if [ "$1" = "rc_conf_files" -a \
-		     "$_rc_confs_set" -a \
-		     "$rc_conf_files" = "$RC_CONFS" \
-		]; then
-			rc_conf_files="$_rc_conf_files"
-			unset _rc_conf_files
-			unset _rc_confs_set
-		fi
-
-		unset RC_CONFS
-			# no longer needed
-
-		#
-		# This must be the last functional line for both the sub-shell
-		# and the function to preserve the return status from formats
-		# such as "${varname?}" and "${varname:?}" (see "Parameter
-		# Expansion" in sh(1) for more information).
-		#
-		eval printf "'%s\\n'" '"${'"$1"'}"' 2> /dev/null
-	)
-}
-
-# f_sysrc_service_configs [-a|-p] $name [$var_to_set]
-#
-# Get a list of optional `rc.conf.d' entries sourced by system `rc.d' script
-# $name (see rc.subr(8) for additional information on `rc.conf.d'). If $name
-# exists in `/etc/rc.d' or $local_startup directories and is an rc(8) script
-# the result is a space separated list of `rc.conf.d' entries sourced by the
-# $name `rc.d' script. Otherwise, if $name exists as a binary `rc.d' script,
-# the result is ``/etc/rc.conf.d/$name /usr/local/etc/rc.conf.d/$name''. The
-# result is NULL if $name does not exist.
-#
-# If $var_to_set is missing or NULL, output is to standard out. Returns success
-# if $name was found, failure otherwise.
-#
-# If `-a' flag is given and $var_to_set is non-NULL, append result to value of
-# $var_to_set rather than overwriting current contents.
-#
-# If `-p' flag is given and $var_to_set is non-NULL, prepend result to value of
-# $var_to_set rather than overwriting current contents.
-#
-# NB: The `-a' and `-p' option flags are mutually exclusive.
-#
-f_sysrc_service_configs()
-{
-	local OPTIND=1 OPTARG __flag __append= __prepend=
-	local __local_startup __dir __spath __stype __names=
-
-	while getopts ap __flag; do
-		case "$__flag" in
-		a) __append=1 __prepend= ;;
-		p) __prepend=1 __append= ;;
-		esac
-	done
-	shift $(( $OPTIND - 1 ))
-
-	[ $# -gt 0 ] || return $FAILURE
-	local __sname="$1" __var_to_set="$2"
-
-	__local_startup=$( f_sysrc_get local_startup )
-	for __dir in /etc/rc.d $__local_startup; do
-		__spath="$__dir/$__sname"
-		[ -f "$__spath" -a -x "$__spath" ] || __spath= continue
-		break
-	done
-	[ "$__spath" ] || return $FAILURE
-
-	__stype=$( file -b "$__spath" 2> /dev/null )
-	case "$__stype" in
-	*"shell script"*)
-		__names=$( exec 9<&1 1>&- 2>&-
-			last_name=
-			print_name() {
-				local name="$1"
-				case "$name" in
-				""|.|..|*/*|"$last_name") return ;;
-				esac
-				echo "$name" >&9
-				last_name="$name"
-			}
-			eval "$( awk '{
-				gsub(/load_rc_config /, "print_name ")
-				gsub(/run_rc_command /, ": ")
-				print
-			}' "$__spath" )"
-		) ;;
-	*)
-		__names="$__sname"
-	esac
-
-	local __name __test_path __configs=
-	for __name in $__names; do
-		for __dir in /etc/rc.d $__local_startup; do
-			__test_path="${__dir%/rc.d}/rc.conf.d/$__name"
-			[ -d "$__test_path" ] ||
-				__configs="$__configs $__test_path" continue
-			for __test_path in "$__test_path"/*; do
-				[ -f "$__test_path" ] || continue
-				__configs="$__configs $__test_path"
-			done	
-		done
-	done
-	__configs="${__configs# }"
-
-	if [ "$__var_to_set" ]; then
-		local __cur=
-		[ "$__append" -o "$__prepend" ] &&
-			f_getvar "$__var_to_set" __cur
-		[ "$__append"  ] && __configs="$__cur{$__cur:+ }$__configs"
-		[ "$__prepend" ] && __configs="$__configs${__cur:+ }$__cur"
-		setvar "$__var_to_set" "$__configs"
-	else
-		echo "$__configs"
-	fi
-
-	return $SUCCESS
-}
-
-# f_sysrc_get_default $varname
-#
-# Get a system configuration default setting from the default rc.conf(5) file
-# (or whatever RC_DEFAULTS points at).
-#
-f_sysrc_get_default()
-{
-	# Sanity check
-	[ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE
-
-	# Taint-check variable name
-	case "$1" in
-	[0-9]*)
-		# Don't expand possible positional parameters
-		return $FAILURE ;;
-	*)
-		[ "$1" ] || return $FAILURE
-	esac
-
-	( # Execute within sub-shell to protect parent environment
-
-		#
-		# Clear the environment of all variables, preventing the
-		# expansion of normals such as `PS1', `TERM', etc.
-		#
-		f_clean_env --except RC_DEFAULTS
-
-		. "$RC_DEFAULTS" > /dev/null 2>&1
-
-		unset RC_DEFAULTS
-			# no longer needed
-
-		#
-		# This must be the last functional line for both the sub-shell
-		# and the function to preserve the return status from formats
-		# such as "${varname?}" and "${varname:?}" (see "Parameter
-		# Expansion" in sh(1) for more information).
-		#
-		eval printf "'%s\\n'" '"${'"$1"'}"' 2> /dev/null
-	)
-}
-
-# f_sysrc_find $varname
-#
-# Find which file holds the effective last-assignment to a given variable
-# within the rc.conf(5) file(s).
-#
-# If the variable is found in any of the rc.conf(5) files, the function prints
-# the filename it was found in and then returns success. Otherwise output is
-# NULL and the function returns with error status.
-#
-f_sysrc_find()
-{
-	local varname="${1%%[!$VALID_VARNAME_CHARS]*}"
-	local regex="^[[:space:]]*$varname="
-	local rc_conf_files="$( f_sysrc_get rc_conf_files )"
-	local conf_files=
-	local file
-
-	# Check parameters
-	case "$varname" in
-	""|[0-9]*) return $FAILURE
-	esac
-
-	#
-	# If RC_CONFS is defined, set $rc_conf_files to an explicit
-	# value, modifying the default behavior of source_rc_confs().
-	#
-	[ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS"
-
-	#
-	# Reverse the order of files in rc_conf_files (the boot process sources
-	# these in order, so we will search them in reverse-order to find the
-	# last-assignment -- the one that ultimately effects the environment).
-	#
-	for file in $rc_conf_files; do
-		conf_files="$file${conf_files:+ }$conf_files"
-	done
-
-	#
-	# Append the defaults file (since directives in the defaults file
-	# indeed affect the boot process, we'll want to know when a directive
-	# is found there).
-	#
-	conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS"
-
-	#
-	# Find which file matches assignment to the given variable name.
-	#
-	for file in $conf_files; do
-		[ -f "$file" -a -r "$file" ] || continue
-		if grep -Eq "$regex" $file; then
-			echo $file
-			return $SUCCESS
-		fi
-	done
-
-	return $FAILURE # Not found
-}
-
-# f_sysrc_desc $varname
-#
-# Attempts to return the comments associated with varname from the rc.conf(5)
-# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to).
-#
-# Multi-line comments are joined together. Results are NULL if no description
-# could be found.
-#
-# 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.
-#
-f_sysrc_desc_awk='
-# Variables that should be defined on the invocation line:
-# 	-v varname="varname"
-#
-BEGIN {
-	regex = "^[[:space:]]*"varname"="
-	found = 0
-	buffer = ""
-}
-{
-	if ( ! found )
-	{
-		if ( ! match($0, regex) ) next
-
-		found = 1
-		sub(/^[^#]*(#[[:space:]]*)?/, "")
-		buffer = $0
-		next
-	}
-
-	if ( !/^[[:space:]]*#/ ||
-	      /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ ||
-	      /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ ||
-	      /^[[:space:]]*$/ ) exit
-
-	sub(/(.*#)*[[:space:]]*/, "")
-	buffer = buffer" "$0
-}
-END {
-	# Clean up the buffer
-	sub(/^[[:space:]]*/, "", buffer)
-	sub(/[[:space:]]*$/, "", buffer)
-
-	print buffer
-	exit ! found
-}
-'
-f_sysrc_desc()
-{
-	awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS"
-}
-
-# f_sysrc_set $varname $new_value
-#
-# Change a setting in the system configuration files (edits the files in-place
-# to change the value in the last assignment to the variable). If the variable
-# 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.
-#
-f_sysrc_set_awk='
-# Variables that should be defined on the invocation line:
-# 	-v varname="varname"
-# 	-v new_value="new_value"
-#
-BEGIN {
-	regex = "^[[:space:]]*"varname"="
-	found = retval = 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 = 1
-	matchlen = RSTART + RLENGTH - 1
-
-	# Store the value text for later munging
-	value = substr($0, matchlen + 1, length($0) - matchlen)
-
-	# Store the first character of the value
-	t1 = t2 = substr(value, 0, 1)
-
-	# Assignment w/ back-ticks, expression, or misc.
-	# We ignore these since we did not generate them
-	#
-	if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next }
-
-	# Assignment w/ single-quoted value
-	else if ( t1 == "'\''" ) {
-		sub(/^'\''[^'\'']*/, "", value)
-		if ( length(value) == 0 ) t2 = ""
-		sub(/^'\''/, "", value)
-	}
-
-	# Assignment w/ double-quoted value
-	else if ( t1 == "\"" ) {
-		sub(/^"(.*\\\\+")*[^"]*/, "", value)
-		if ( length(value) == 0 ) t2 = ""
-		sub(/^"/, "", value)
-	}
-
-	# Assignment w/ non-quoted value
-	else if ( t1 ~ /[^[:space:];]/ ) {
-		t1 = t2 = "\""
-		sub(/^[^[:space:]]*/, "", value)
-	}
-
-	# Null-assignment
-	else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" }
-
-	printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \
-		t1, new_value, t2, value
-}
-END { exit retval }
-'
-f_sysrc_set()
-{
-	local funcname=f_sysrc_set
-	local varname="$1" new_value="$2"
-
-	# Check arguments
-	[ "$varname" ] || return $FAILURE
-
-	#
-	# Find which rc.conf(5) file contains the last-assignment
-	#
-	local not_found=
-	local file="$( f_sysrc_find "$varname" )"
-	if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then
-		#
-		# We either got a null response (not found) or the variable
-		# was only found in the rc.conf(5) defaults. In either case,
-		# let's instead modify the first file from $rc_conf_files.
-		#
-
-		not_found=1
-
-		#
-		# If RC_CONFS is defined, use $RC_CONFS
-		# rather than $rc_conf_files.
-		#
-		if [ "${RC_CONFS+set}" ]; then
-			file="${RC_CONFS%%[$IFS]*}"
-		else
-			file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' )
-		fi
-	fi
-
-	#
-	# If not found, append new value to first file and return.
-	#
-	if [ "$not_found" ]; then
-		# Add a newline if missing before appending to the file
-		[ ! -e "$file" ] || awk 'BEGIN { wc = 0 } NR == 1 {
-			(cmd = "wc -l " FILENAME) | getline
-			close(cmd)
-			wc = $1
-		} END { exit wc != NR }' "$file" ||
-			echo >> "$file" || return $?
-		echo "$varname=\"$new_value\"" >> "$file"
-		return $?
-	fi
-
-	#
-	# Perform sanity checks.
-	#
-	if [ ! -w "$file" ]; then
-		f_err "$msg_cannot_create_permission_denied\n" \
-		      "$pgm" "$file"
-		return $FAILURE
-	fi
-
-	#
-	# Create a new temporary file to write to.
-	#
-	local tmpfile
-	if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm"
-	then
-		echo "$tmpfile" >&2
-		return $FAILURE
-	fi
-
-	#
-	# Fixup permissions (else we're in for a surprise, as mktemp(1) creates
-	# the temporary file with 0600 permissions, and if we simply mv(1) the
-	# temporary file over the destination, the destination will inherit the
-	# permissions from the temporary file).
-	#
-	local mode
-	f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" ||
-		mode=0644
-	f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile"
-
-	#
-	# Fixup ownership. The destination file _is_ writable (we tested
-	# earlier above). However, this will fail if we don't have sufficient
-	# permissions (so we throw stderr into the bit-bucket).
-	#
-	local owner
-	f_eval_catch -dk owner $funcname stat \
-		'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
-	f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile"
-
-	#
-	# Operate on the matching file, replacing only the last occurrence.
-	#
-	# Use awk to ensure LF at end of each line, else files without ending
-	# LF will trigger a bug in `tail -r' where last two lines are joined.
-	#
-	local new_contents retval
-	new_contents=$( awk 1 "$file" 2> /dev/null | tail -r )
-	new_contents=$( echo "$new_contents" | awk -v varname="$varname" \
-		-v new_value="$new_value" "$f_sysrc_set_awk" )
-	retval=$?
-
-	#
-	# Write the temporary file contents.
-	#
-	echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE
-	if [ $retval -ne $SUCCESS ]; then
-		echo "$varname=\"$new_value\"" >> "$tmpfile"
-	fi
-
-	#
-	# Taint-check our results.
-	#
-	if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then
-		f_err "$msg_previous_syntax_errors\n" "$pgm" "$file"
-		rm -f "$tmpfile"
-		return $FAILURE
-	fi
-
-	#
-	# Finally, move the temporary file into place.
-	#
-	f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file"
-}
-
-# f_sysrc_delete $varname
-#
-# Remove a setting from the system configuration files (edits files in-place).
-# Deletes all assignments to the given variable in all config files. If the
-# `-f file' option is passed, the removal is restricted to only those files
-# specified, otherwise the system collection of rc_conf_files is used.
-#
-# 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.
-#
-f_sysrc_delete_awk='
-# Variables that should be defined on the invocation line:
-# 	-v varname="varname"
-#
-BEGIN {
-	regex = "^[[:space:]]*"varname"="
-	found = 0
-}
-{
-	if ( $0 ~ regex )
-		found = 1
-	else
-		print
-}
-END { exit ! found }
-'
-f_sysrc_delete()
-{
-	local funcname=f_sysrc_delete
-	local varname="$1"
-	local file
-
-	# Check arguments
-	[ "$varname" ] || return $FAILURE
-
-	#
-	# Operate on each of the specified files
-	#
-	local tmpfile
-	for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do
-		[ -e "$file" ] || continue
-
-		#
-		# Create a new temporary file to write to.
-		#
-		if ! f_eval_catch -dk tmpfile $funcname mktemp \
-			'mktemp -t "%s"' "$pgm"
-		then
-			echo "$tmpfile" >&2
-			return $FAILURE
-		fi
-
-		#
-		# Fixup permissions and ownership (mktemp(1) defaults to 0600
-		# permissions) to instead match the destination file.
-		#
-		local mode owner
-		f_eval_catch -dk mode $funcname stat \
-			'stat -f "%%#Lp" "%s"' "$file" || mode=0644
-		f_eval_catch -dk owner $funcname stat \
-			'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
-		f_eval_catch -d $funcname chmod \
-			'chmod "%s" "%s"' "$mode" "$tmpfile"
-		f_eval_catch -d $funcname chown \
-			'chown "%s" "%s"' "$owner" "$tmpfile"
-
-		#
-		# Operate on the file, removing all occurrences, saving the
-		# output in our temporary file.
-		#
-		awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \
-			> "$tmpfile"
-		if [ $? -ne $SUCCESS ]; then
-			# The file didn't contain any assignments
-			rm -f "$tmpfile"
-			continue
-		fi
-
-		#
-		# Taint-check our results.
-		#
-		if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"
-		then
-			f_err "$msg_previous_syntax_errors\n" \
-			      "$pgm" "$file"
-			rm -f "$tmpfile"
-			return $FAILURE
-		fi
-
-		#
-		# Perform sanity checks
-		#
-		if [ ! -w "$file" ]; then
-			f_err "$msg_permission_denied\n" "$pgm" "$file"
-			rm -f "$tmpfile"
-			return $FAILURE
-		fi
-
-		#
-		# Finally, move the temporary file into place.
-		#
-		f_eval_catch -de $funcname mv \
-			'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE
-	done
-}
-
 ############################################################ MAIN
 
 f_dprintf "%s: Successfully loaded." sysrc.subr
diff --git a/usr.sbin/sysrc/Makefile b/usr.sbin/sysrc/Makefile
index bad50caf2ffc..b0ddedab8fad 100644
--- a/usr.sbin/sysrc/Makefile
+++ b/usr.sbin/sysrc/Makefile
@@ -1,8 +1,11 @@
 .include <src.opts.mk>
 
-PACKAGE= bsdconfig
+PACKAGE= rc
 SCRIPTS= sysrc
 
+FILESDIR= ${SHAREDIR}/sysrc
+FILES= sysrc.subr
+
 MAN= sysrc.8
 
 HAS_TESTS=
diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc
index 625ff5ca4efd..bd3faeac8ed3 100644
--- a/usr.sbin/sysrc/sysrc
+++ b/usr.sbin/sysrc/sysrc
@@ -27,12 +27,8 @@
 #
 ############################################################ INCLUDES
 
-# Prevent `-d' from being interpreted as a debug flag by common.subr
-DEBUG_SELF_INITIALIZE=
-
-BSDCFG_SHARE="/usr/share/bsdconfig"
-[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1
-[ "$_SYSRC_SUBR"  ] || f_include $BSDCFG_SHARE/sysrc.subr
+SYSRC_SHARE="/usr/share/sysrc"
+[ "$_SYSRC_SUBR" ] || . $SYSRC_SHARE/sysrc.subr || exit 1
 
 ############################################################ GLOBALS
 
@@ -207,9 +203,7 @@ jail_depend()
 	#
 	# Print include dependencies
 	#
-	echo DEBUG_SELF_INITIALIZE=
-	cat $BSDCFG_SHARE/common.subr
-	cat $BSDCFG_SHARE/sysrc.subr
+	cat $SYSRC_SHARE/sysrc.subr
 }
 
 # escape $string [$var_to_set]
diff --git a/usr.sbin/sysrc/sysrc.subr b/usr.sbin/sysrc/sysrc.subr
new file mode 100644
index 000000000000..63c92843c672
--- /dev/null
+++ b/usr.sbin/sysrc/sysrc.subr
@@ -0,0 +1,898 @@
+if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1
+#
+# Copyright (c) 2006-2015 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+# This file was split-out of bsdconfig(8) and is now self-contained, and is
+# no longer dependent on bsdconfig(8) or any of its libraries.
+#
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames (inherit values from shell if available)
+#
+: ${RC_DEFAULTS:="/etc/defaults/rc.conf"}
+
+############################################################ GLOBALS
+
+#
+# Global exit status variables
+#
+SUCCESS=0
+FAILURE=1
+
+#
+# Program name (derived from the running script)
+#
+pgm="${0##*/}"
+
+#
+# Error messages.
+#
+msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied"
+msg_permission_denied="%s: %s: Permission denied"
+msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors"
+
+#
+# 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
+# these can include accent characters (which are not valid in a variable name).
+# For example, A-Z matches any character that sorts after A but before Z,
+# including A and Z. Although ASCII order would make more sense, that is not
+# how it works.
+#
+VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
+
+############################################################ FUNCTIONS
+
+# f_err $format [$arguments ...]
+#
+# Print a message to stderr (fd=2).
+#
+f_err()
+{
+	printf "$@" >&2
+}
+
+# f_have $anything ...
+#
+# A wrapper to the `type' built-in. Returns true if argument is a valid shell
+# built-in, keyword, or externally-tracked binary, otherwise false.
+#
+f_have()
+{
+	type "$@" > /dev/null 2>&1
+}
+
+# setvar $var_to_set [$value]
+#
+# Implement setvar for shells unlike FreeBSD sh(1).
+#
+if ! f_have setvar; then
+setvar()
+{
+	[ $# -gt 0 ] || return $SUCCESS
+	local __setvar_var_to_set="$1" __setvar_right="$2" __setvar_left=
+	case $# in
+	1) unset "$__setvar_var_to_set"
+	   return $? ;;
+	2) : fall through ;;
+	*) f_err "setvar: too many arguments\n"
+	   return $FAILURE
+	esac
+	case "$__setvar_var_to_set" in *[!0-9A-Za-z_]*)
+		f_err "setvar: %s: bad variable name\n" "$__setvar_var_to_set"
+		return 2
+	esac
+	while case "$__setvar_r" in *\'*) : ;; *) false ; esac
+	do
+		__setvar_left="$__setvar_left${__setvar_right%%\'*}'\\''"
+		__setvar_right="${__setvar_right#*\'}"
+	done
+	__setvar_left="$__setvar_left${__setvar_right#*\'}"
+	eval "$__setvar_var_to_set='$__setvar_left'"
+}
+fi
+
+# f_getvar $var_to_get [$var_to_set]
+#
+# Utility function designed to go along with the already-builtin setvar.
+# Allows clean variable name indirection without forking or sub-shells.
+#
+# Returns error status if the requested variable ($var_to_get) is not set.
+#
*** 772 LINES SKIPPED ***