Subject: rc.subr don't check rcvar YES except at boot/shutdown
To: None <tech-userlevel@NetBSD.org>
From: Jeremy C. Reed <reed@reedmedia.net>
List: tech-userlevel
Date: 02/10/2007 11:20:10
As discussed in December and January, here are a few patches (including 
for man page) so rc.subr doesn't check rcvar for YES except at 
boot/shutdown. (This was the "admin script for ipfilter" thread. Note that 
this patch does not add any "enable" or "disable" option and this doesn't 
add a new rcadmin(8) command.)

This means the default usage of rc.subr changes. (This adds an "only" 
prefix.)

As an example, this means that running "status" of a disabled rc.d script 
will give output.

This also means that the admin can run "start" and "stop" on some 
arbritary rc.d script and it will attempt to do what they expect.

Note if you don't update your rc and rc.shutdown accordingly, it will 
really attempt to start and stop all rc.d services.

Also using "one" prefix now makes no sense.

I have only tested this a little. Your feedback is appreciated.

By the way, I have taught our rc.d usage in several FreeBSD and NetBSD 
admin classes and I use our rc.subr system in my Linux distribution. 
Having to preconfigure or use the "force" or newer "one" prefix isn't 
consistent with what many admins, including myself, expect.

Index: etc/rc
===================================================================
RCS file: /cvsroot/src/etc/rc,v
retrieving revision 1.162
diff -u -r1.162 rc
--- etc/rc	4 Jan 2003 15:27:43 -0000	1.162
+++ etc/rc	10 Feb 2007 16:34:32 -0000
@@ -40,7 +40,7 @@
 files=$(rcorder -s nostart ${rc_rcorder_flags} /etc/rc.d/*)
 
 for _rc_elem in $files; do
-	run_rc_script $_rc_elem start
+	run_rc_script $_rc_elem onlystart
 done
 
 date
Index: etc/rc.shutdown
===================================================================
RCS file: /cvsroot/src/etc/rc.shutdown,v
retrieving revision 1.8
diff -u -r1.8 rc.shutdown
--- etc/rc.shutdown	19 May 2002 01:01:33 -0000	1.8
+++ etc/rc.shutdown	10 Feb 2007 16:34:32 -0000
@@ -50,7 +50,7 @@
 files=$(rcorder -k shutdown ${rcshutdown_rcorder_flags} /etc/rc.d/*)
 
 for _rc_elem in $(reverse_list $files); do
-	run_rc_script $_rc_elem stop
+	run_rc_script $_rc_elem onlystop
 done
 
 
Index: etc/rc.subr
===================================================================
RCS file: /cvsroot/src/etc/rc.subr,v
retrieving revision 1.68
diff -u -r1.68 rc.subr
--- etc/rc.subr	27 Jan 2007 14:30:26 -0000	1.68
+++ etc/rc.subr	10 Feb 2007 16:34:32 -0000
@@ -257,8 +257,13 @@
 #		Prefix	Operation
 #		------	---------
 #		fast	Skip the pid check, and set rc_fast=yes
-#		force	Set ${rcvar} to YES, and set rc_force=yes
-#		one	Set ${rcvar} to YES
+#		force	Set rc_force=yes
+#		one	Set ${rcvar} to YES. Deprecated as this is not needed,
+#			because the ${rcvar} is only checked if "only" prefix
+#			is used. (Can't use both prefixes at same time.)
+#		only	Set rc_only=yes. (Same as original behaviour, runs
+#			command only if ${rcvar} is YES such as at boot
+#			or shutdown.)
 #
 #	The following globals are used:
 #
@@ -284,7 +289,9 @@
 #	procname	n	Process name to check for instead of $command.
 #
 #	rcvar		n	This is checked with checkyesno to determine
-#				if the action should be run.
+#				if the action should be run when the command
+#				is prefixed with 'only' such as at boot and
+#				shutdown in the /etc/rc and /etc/rc.shutdown.
 #
 #	${name}_chroot	n	Directory to chroot to before running ${command}
 #				Requires /usr to be mounted.
@@ -347,7 +354,7 @@
 #
 #	Argument	Default behaviour
 #	--------	-----------------
-#	start		if !running && checkyesno ${rcvar}
+#	start		if !running && (!rc_only || checkyesno ${rcvar})
 #				${command}
 #
 #	stop		if ${pidfile}
@@ -375,7 +382,7 @@
 #
 #	Variable	Purpose
 #	--------	-------
-#	rc_arg		Argument to command, after fast/force/one processing
+#	rc_arg		Argument to command, after fast/force/only processing
 #			performed
 #
 #	rc_flags	Flags to start the default command with.
@@ -389,6 +396,8 @@
 #
 #	rc_force	Not empty if "force" was provided (q.v.)
 #
+#	rc_only		Not empty if "only" was provided (q.v.)
+#
 #
 run_rc_command()
 {
@@ -407,17 +416,20 @@
 		rc_force=yes
 		_rc_prefix=force
 		rc_arg=${rc_arg#${_rc_prefix}}
-		if [ -n "${rcvar}" ]; then
-			eval ${rcvar}=YES
-		fi
 		;;
 	one*)				# "one" prefix; set ${rcvar}=yes
 		_rc_prefix=one
 		rc_arg=${rc_arg#${_rc_prefix}}
+		# This is now redundant.
 		if [ -n "${rcvar}" ]; then
 			eval ${rcvar}=YES
 		fi
 		;;
+	only*)				# "only" prefix; check ${rcvar}
+		rc_only=yes
+		_rc_prefix=only
+		rc_arg=${rc_arg#${_rc_prefix}}
+		;;
 	esac
 
 	_keywords="start stop restart rcvar $extra_commands"
@@ -457,12 +469,15 @@
 		fi
 	fi
 
-					# if ${rcvar} is set, and $1 is not
-					# "rcvar", then run
-					#	checkyesno ${rcvar}
-					# and return if that failed
-					#
-	if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
+	# If $rconly is set and ${rcvar} is set, and $1 is not "rcvar",
+	# then run checkyesno ${rcvar} and return if that failed.
+	# (It doesn't make sense to check $1 is not "rcvar".)
+	#
+	# For example, if "onlystart" or "onlystop" is ran and
+	# the ${rcvar} is not enabled (i.e. YES), then the service
+	# will not be started or stopped.
+	#
+	if [ -n "$rc_only" -a -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
 		if ! checkyesno ${rcvar}; then
 			return 0
 		fi

Index: share/man/man8/rc.8
===================================================================
RCS file: /cvsroot/src/share/man/man8/rc.8,v
retrieving revision 1.28
diff -u -r1.28 rc.8
--- share/man/man8/rc.8	6 Jan 2004 14:46:11 -0000	1.28
+++ share/man/man8/rc.8	10 Feb 2007 17:00:57 -0000
@@ -116,7 +116,7 @@
 which sets
 .Dv $1
 to
-.Sq start ,
+.Sq onlystart ,
 and sources the script in a subshell.
 If the script has a
 .Sq .sh
@@ -148,7 +148,7 @@
 which sets
 .Dv $1
 to
-.Sq stop ,
+.Sq onlystop ,
 and sources the script in a subshell.
 If the script has a
 .Sq .sh
@@ -241,7 +241,10 @@
 .Bl -tag -width restart -offset indent
 .It Sy start
 Start the service.
-This should check that the service is to be started as specified by
+At
+.Nm
+startup,
+should check that the service is to be started as specified by
 .Xr rc.conf 5 .
 Also checks if the service is already running and refuses to start if
 it is.
@@ -250,9 +253,12 @@
 scripts if the system is starting directly to multi-user mode, to
 speed up the boot process.
 .It Sy stop
-If the service is to be started as specified by
-.Xr rc.conf 5 ,
-stop the service.
+Stop the service.
+During the
+.Nm rc.shutdown
+shutdown, should check if the service is to be started as specified by
+.Xr rc.conf 5
+before attempting to stop the service.
 This should check that the service is running and complain if it's not.
 .It Sy restart
 Perform a
@@ -286,9 +292,7 @@
 Sets
 .Sy rc_fast=yes .
 .It Sy force
-Skips the
-.Xr rc.conf 5
-check, ignores a failure result from any of the prerequisite checks,
+Ignores a failure result from any of the prerequisite checks,
 executes the command, and always returns a zero exit status.
 Sets
 .Sy rc_force=yes .
@@ -296,6 +300,15 @@
 Skips the
 .Xr rc.conf 5
 check, but performs all other prerequisite tests.
+(This prefix is deprecated.)
+.It Sy only
+Does the
+.Xr rc.conf 5
+check. 
+The command will only run if the service is enabled,
+such as during boot up or shutdown.
+Sets
+.Sy rc_only=yes .
 .El
 .Pp
 In order to simplify scripts, the run_rc_command() function from