Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 May 2025 00:04:17 GMT
From:      Lexi Winter <ivy@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f6328f052518 - main - rc.subr: remove the dependency on bsdconfig
Message-ID:  <202505150004.54F04Hlr046961@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by ivy:

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

commit f6328f052518d56c01f10e14cd9ef1f2675c01a4
Author:     Lexi Winter <ivy@FreeBSD.org>
AuthorDate: 2025-05-14 14:33:36 +0000
Commit:     Lexi Winter <ivy@FreeBSD.org>
CommitDate: 2025-05-15 00:02:52 +0000

    rc.subr: remove the dependency on bsdconfig
    
    rc.subr uses sysrc(8) for the 'enable' and 'disable' commands, which
    means the entire rc(8) stack depends on bsdconfig.  Instead, provide a
    minimal amount of rc.conf-editing functionality in rc.subr and use it to
    implement these commands.
    
    Reviewed by:    des, bapt
    Approved by:    des (mentor)
    Differential Revision:  https://reviews.freebsd.org/D50325
---
 libexec/rc/rc.subr | 102 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 86 insertions(+), 16 deletions(-)

diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
index 2261ab0461e1..e2a30d9fc9bd 100644
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -56,6 +56,9 @@ _svcj_generic_params="path=/ mount.nodevfs host=inherit"
 JID=0
 CPUSET="/bin/cpuset"
 
+# Cache the services that we loaded with load_rc_config.
+_loaded_services=""
+
 # rc_service provides the path to the service script that we are executing.
 # This is not being set here in an execution context, necessarily, so it's
 # really just a reasonable guess, and it will get overwritten later if
@@ -1421,28 +1424,17 @@ run_rc_command()
 			;;
 
 		enable)
-			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=YES") &&
-				echo "$name enabled in ${_out%%:*}"
+			_out=$(write_rcvar "$rcvar" "YES") &&
+				echo "$name enabled in $_out"
 			;;
 
 		disable)
-			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=NO") &&
-				echo "$name disabled in ${_out%%:*}"
+			_out=$(write_rcvar "$rcvar" "NO") &&
+				echo "$name disabled in $_out"
 			;;
 
 		delete)
-			_files=
-			for _file in $(/usr/sbin/sysrc -lEs "$name"); do
-				_out=$(/usr/sbin/sysrc -Fif $_file "$rcvar") && _files="$_files $_file"
-			done
-			/usr/sbin/sysrc -x "$rcvar" && echo "$rcvar deleted in ${_files# }"
-				# delete file in rc.conf.d if desired and empty.
-			checkyesno service_delete_empty || _files=
-			for _file in $_files; do
-				[ "$_file" = "${_file#*/rc.conf.d/}" ] && continue
-				[ $(/usr/bin/stat -f%z $_file) -gt 0 ] && continue
-				/bin/rm "$_file" && echo "Empty file $_file removed"
-			done
+			delete_rcvar "$rcvar"
 			;;
 
 		status)
@@ -1982,6 +1974,7 @@ load_rc_config()
 	# If a service name was specified, attempt to load
 	# service-specific configuration
 	if [ -n "$_name" ] ; then
+		_loaded_services="${_loaded_services} ${_name}"
 		for _d in /etc ${local_startup}; do
 			_d=${_d%/rc.d}
 			if [ -f ${_d}/rc.conf.d/"$_name" ]; then
@@ -2735,6 +2728,83 @@ _echoonce()
 	esac
 }
 
+# _find_rcvar var
+#	Find the rc.conf file (other than /etc/defaults/rc.conf) that sets $var.
+_find_rcvar()
+{
+	local _var _dir _files
+
+	[ -n "$1" ] || return 1
+	_var="$1"; shift
+
+	_files="/etc/rc.conf"
+	for _dir in /etc ${local_startup}; do
+		for _name in $_loaded_services; do
+			_files="${_dir%/rc.d}/rc.conf.d/${_name} ${_files}"
+		done
+	done
+
+	/usr/bin/grep 2>/dev/null -rl "^${_var}=" $_files | /usr/bin/head -1
+}
+
+# write_rcvar var value
+#	Add or replace the rc var $var with the value $value.
+#	Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name,
+#	and if found, modify it there; otherwise, append to /etc/rc.conf.
+write_rcvar()
+{
+	local _var _value _file _dir
+
+	[ -n "$1" ] || return 1
+	_var="$1"; shift
+	[ -n "$1" ] || return 1
+	_value="$1"; shift
+
+	_file="$(_find_rcvar "$_var")"
+	if [ -n "$_file" ]; then
+		local _=$'\01'
+		/usr/bin/sed -i '' "s${_}^${_var}=.*${_}${_var}=\"$_value\"${_}" "$_file"
+		echo $_file
+		return
+	fi
+
+	for _dir in /etc ${local_startup}; do
+		_file="${_dir%/rc.d}/rc.conf.d/${name}"
+		if [ -f "$_file" ]; then
+			echo "${_var}=\"${_value}\"" >>"$_file"
+			echo "$_file"
+			return
+		fi
+	done
+
+	echo "${_var}=\"${_value}\"" >>/etc/rc.conf
+	echo "/etc/rc.conf"
+}
+
+# delete_rcvar var
+#	Remove the rc var $var.
+#	Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name,
+#	and if found, remove it.  If service_delete_empty is enabled, and the
+#	resulting file is empty, also delete the file.
+delete_rcvar()
+{
+	local _var _files
+
+	[ -n "$1" ] || return 1
+	_var="$1"; shift
+
+	_file="$(_find_rcvar "$_var")"
+	if [ -n "$_file" ]; then
+		/usr/bin/sed -i '' "/^${_var}=/d" "$_file"
+		echo "$_var deleted in $_file"
+
+		if checkyesno service_delete_empty && [ ! -s "$_file" ]; then
+			/bin/rm -f "$_file"
+			echo "Empty file $_file removed"
+		fi
+	fi
+}
+
 # If the loader env variable rc.debug is set, turn on debugging. rc.conf will
 # still override this, but /etc/defaults/rc.conf can't unconditionally set this
 # since it would undo what we've done here.



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