Module Name:    src
Committed By:   apb
Date:           Fri Sep 11 18:17:04 UTC 2009

Modified Files:
        src/doc: CHANGES
        src/etc: rc rc.subr
        src/etc/defaults: rc.conf
        src/share/man/man5: rc.conf.5
        src/share/man/man8: rc.8 rc.subr.8

Log Message:
Add a postprocessor to /etc/rc, which logs messages to /var/run/rc.log,
and which can suppress output in silent mode.  Silent mode is enabled
via the new rc_silent variable, which defaults to a value that depends
on the kern.boothowto sysctl.

Part of the /etc/rc silent changes requested in PR 41946
and proposed in tech-userlevel.


To generate a diff of this commit:
cvs rdiff -u -r1.1287 -r1.1288 src/doc/CHANGES
cvs rdiff -u -r1.163 -r1.164 src/etc/rc
cvs rdiff -u -r1.77 -r1.78 src/etc/rc.subr
cvs rdiff -u -r1.104 -r1.105 src/etc/defaults/rc.conf
cvs rdiff -u -r1.132 -r1.133 src/share/man/man5/rc.conf.5
cvs rdiff -u -r1.31 -r1.32 src/share/man/man8/rc.8
cvs rdiff -u -r1.22 -r1.23 src/share/man/man8/rc.subr.8

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/doc/CHANGES
diff -u src/doc/CHANGES:1.1287 src/doc/CHANGES:1.1288
--- src/doc/CHANGES:1.1287	Fri Sep 11 18:14:58 2009
+++ src/doc/CHANGES	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-# LIST OF CHANGES FROM LAST RELEASE:			<$Revision: 1.1287 $>
+# LIST OF CHANGES FROM LAST RELEASE:			<$Revision: 1.1288 $>
 #
 #
 # [Note: This file does not mention every change made to the NetBSD source tree.
@@ -389,3 +389,6 @@
 	build.sh: Add a modules operation which builds kernel modules and
 		installs them into DESTDIR. [jnemeth 20090907]
 	sysctl(7): Add kern.boothowto variable.  [apb 20090911]
+	rc(8): Output is now logged to /var/run/rc.log.  A new rc_silent
+		option, enabled if the kernel is booted in silent mode,
+		suppresses output to the console.  [apb 20090911]

Index: src/etc/rc
diff -u src/etc/rc:1.163 src/etc/rc:1.164
--- src/etc/rc:1.163	Fri Apr 10 16:18:04 2009
+++ src/etc/rc	Fri Sep 11 18:17:04 2009
@@ -1,9 +1,10 @@
 #!/bin/sh
 #
-# $NetBSD: rc,v 1.163 2009/04/10 16:18:04 joerg Exp $
+# $NetBSD: rc,v 1.164 2009/09/11 18:17:04 apb Exp $
 #
 # rc --
-#	Run the scripts in /etc/rc.d with rcorder.
+#	Run the scripts in /etc/rc.d with rcorder, and log output
+#	to /var/run/rc.log.
 
 #	System startup script run by init(8) on autoboot or after single-user.
 #	Output and error are redirected to console by init, and the console
@@ -13,10 +14,16 @@
 export PATH=/sbin:/bin:/usr/sbin:/usr/bin
 umask 022
 
-. /etc/rc.subr
+if [ -e ./rc.subr ] ; then
+	. ./rc.subr # for testing
+else
+	. /etc/rc.subr
+fi
 . /etc/rc.conf
 _rc_conf_loaded=true
 
+: ${RC_LOG_FILE:="/var/run/rc.log"}
+
 if ! checkyesno rc_configured; then
 	echo "/etc/rc.conf is not configured.  Multiuser boot aborted."
 	exit 1
@@ -27,24 +34,363 @@
 	rc_fast=yes	# run_rc_command(): do fast booting
 fi
 
-stty status '^T'
+#
+# Completely ignore INT and QUIT at the outer level.  The rc_real_work()
+# function should do something different.
+#
+trap '' INT QUIT
 
-#	Set shell to ignore SIGINT, but not children;
-#	shell catches SIGQUIT and returns to single user.
 #
-trap : INT
-trap "echo 'Boot interrupted.'; exit 1" QUIT
+# This string will be used to mark lines of meta-data sent over the pipe
+# from the rc_real_work() function to the rc_postprocess() function.  Lines
+# not so marked are assumed to be output from rc.d scripts.
+#
+# This string is long and unique to ensure that it does not accidentally
+# appear in output from any rc.d script.  It must not contain any
+# characters that are special to glob expansion ('*', '?', '[', or ']').
+#
+rc_metadata_prefix="$0:$$:metadata:";
 
-date
+# Child scripts may sometimes want to print directly to the original
+# stdout and stderr, bypassing the pipe to the postprocessor.  These
+# _rc_*_fd variables are private, shared with /etc/rc.subr, but not
+# intended to be used directly by child scripts.  (Child scripts
+# may use rc.subr's no_rc_postprocess function.)
+#
+_rc_original_stdout_fd=7; export _rc_original_stdout_fd
+_rc_original_stderr_fd=8; export _rc_original_stderr_fd
+eval "exec ${_rc_original_stdout_fd}>&1"
+eval "exec ${_rc_original_stderr_fd}>&2"
 
-scripts=$(for rcd in ${rc_directories:-/etc/rc.d}; do
-	test -d ${rcd} && echo ${rcd}/*;
-done)
-files=$(rcorder -s nostart ${rc_rcorder_flags} ${scripts})
+#
+# rc_real_work
+#	Do the real work.  Output from this function will be piped into
+#	rc_postprocess(), and some of the output will be marked as
+#	metadata.
+#
+# The body of this function is defined using (...), not {...}, to force
+# it to run in a subshell.
+#
+rc_real_work()
+(
+	stty status '^T'
+
+	# print_rc_metadata() wants to be able to print to the pipe
+	# that goes to our postprocessor, even if its in a context
+	# with redirected output.
+	#
+	_rc_postprocessor_fd=9 ; export _rc_postprocessor_fd
+	eval "exec ${_rc_postprocessor_fd}>&1"
+
+	# Print a metadata line when we exit
+	#
+	trap 'es=$?; print_rc_metadata "exit:$es"; trap "" 0; exit $es' 0
+
+	#	Set shell to ignore SIGINT, but children will not ignore it.
+	#	Shell catches SIGQUIT and returns to single user.
+	#
+	trap : INT
+	trap '_msg="Boot interrupted at $(date)";
+	      print_rc_metadata "interrupted:${_msg}";
+	      exit 1' QUIT
+
+	print_rc_metadata "start:$(date)"
+
+	#
+	# The stop_boot() function in rc.subr may kill $RC_PID.  We want
+	# it to kill the subshell running this rc_real_work() function,
+	# rather than killing the parent shell, because we want the
+	# rc_postprocess() function to be able to log the error
+	# without being killed itself.
+	#
+	# "$$" is the pid of the top-level shell, not the pid of the
+	# subshell that's executing this function.  The command below
+	# tentatively assumes that the parent of the "/bin/sh -c ..."
+	# process will be the current subshell, and then uses "kill -0
+	# ..." to check the result.  If the "/bin/sh -c ..." process
+	# fails, or returns the pid of an ephemeral process that exits
+	# before the "kill" command, then we fall back to using "$$".
+	#
+	RC_PID=$(/bin/sh -c 'ps -p $$ -o ppid=') || RC_PID=$$
+	kill -0 $RC_PID >/dev/null 2>&1 || RC_PID=$$
+
+	#
+	# Get a list of all rc.d scripts, and use rcorder to choose
+	# what order to execute them.
+	#
+	# For testing, allow RC_FILES_OVERRIDE from the environment to
+	# override this.
+	#
+	print_rc_metadata "cmd-name:rcorder"
+	scripts=$(for rcd in ${rc_directories:-/etc/rc.d}; do
+		test -d ${rcd} && echo ${rcd}/*;
+	done)
+	files=$(rcorder -s nostart ${rc_rcorder_flags} ${scripts})
+	print_rc_metadata "cmd-status:rcorder:$?"
+
+	if [ -n "${RC_FILES_OVERRIDE}" ]; then
+		files="${RC_FILES_OVERRIDE}"
+	fi
+
+	#
+	# Run the scripts in order.
+	#
+	for _rc_elem in $files; do
+		print_rc_metadata "cmd-name:$_rc_elem"
+		run_rc_script $_rc_elem start
+		print_rc_metadata "cmd-status:$_rc_elem:$?"
+	done
+
+	print_rc_metadata "end:$(date)"
+	exit 0
+)
 
-for _rc_elem in $files; do
-	run_rc_script $_rc_elem start
-done
+#
+# rc_postprocess
+#	Post-process the output from the rc_real_work() function.  For
+#	each line of input, we have to decide whether to print the line
+#	to the console, print a twiddle on the console, print a line to
+#	the log, or some combination of these.
+#
+#	If rc_silent is true, then suppress most output, instead running
+#	rc_silent_cmd (typically "twiddle") for each line.
+#
+# The body of this function is defined using (...), not {...}, to force
+# it to run in a subshell.
+#
+# We have to deal with the following constraints:
+#
+#  * There may be no writable file systems early in the boot, so
+#    any use of temporary files would be problematic.
+#
+#  * Scripts run during the boot may clear /tmp and/var/run, so even
+#    if they are writable, using those directories too early may be
+#    problematic.  We assume that it's safe to write to our log file
+#    after the mountcritlocal script has run.
+#
+#  * /usr/bin/tee cannot be used because the /usr file system may not
+#    be mounted early in the boot.
+#
+#  * All calls to the rc_log_message and rc_log_flush functions must be
+#    from the same subshell, otherwise the use of a shell variable to
+#    buffer log messages will fail.
+#
+rc_postprocess()
+(
+	local line
+	local before after
+	local IFS=''
+
+	# Try quite hard to flush the log to disk when we exit.
+	trap 'es=$?; rc_log_flush FORCE; trap "" 0; exit $es' 0
+
+	yesno_to_truefalse rc_silent 2>/dev/null
+
+	while read -r line ; do
+		case "$line" in
+		"${rc_metadata_prefix}"*)
+			after="${line#*"${rc_metadata_prefix}"}"
+			rc_postprocess_metadata "${after}"
+			;;
+		*"${rc_metadata_prefix}"*)
+			# magic string is present, but not at the start of
+			# the line.  Treat it like two separate lines.
+			before="${line%"${rc_metadata_prefix}"*}"
+			rc_postprocess_plain_line "${before}"
+			after="${line#*"${rc_metadata_prefix}"}"
+			rc_postprocess_metadata "${after}"
+			;;
+		*)
+			rc_postprocess_plain_line "${line}"
+			;;
+		esac
+	done
+
+	# If we get here, then the rc_real_work() function must have
+	# exited uncleanly.  A clean exit would have been accompanied by
+	# a line of metadata that would have prevented us from getting
+	# here.
+	#
+	exit 1
+)
+
+#
+# rc_postprocess_plain_line string
+#	$1 is a string representing a line of output from one of the
+#	rc.d scripts.  Append the line to the log, and also either
+#	display the line on the console, or run $rc_silent_cmd,
+#	depending on the value of $rc_silent.
+#
+rc_postprocess_plain_line()
+{
+	local line="$1"
+	rc_log_message "${line}"
+	if $rc_silent; then
+		eval "$rc_silent_cmd"
+	else
+		printf "%s\n" "${line}"
+	fi
+}
+
+#
+# rc_postprocess_metadata string
+#	$1 is a string containing metadata from the rc_real_work()
+#	function.  The rc_metadata_prefix marker should already
+#	have been removed before the string is passed to this function.
+#	Take appropriate action depending on the content of the string.
+#
+rc_postprocess_metadata()
+{
+	local metadata="$1"
+	local keyword args
+	local msg
+	local IFS=':'
+
+	# given metadata="bleep:foo bar:baz",
+	# set keyword="bleep", args="foo bar:baz",
+	# $1="foo bar", $2="baz"
+	#
+	keyword="${metadata%%:*}"
+	args="${metadata#*:}"
+	set -- $args
+
+	case "$keyword" in
+	start)
+		# $args contains a date/time
+		rc_log_message "[$0 starting at $args]"
+		if ! $rc_silent; then
+			printf "%s\n" "$args"
+		fi
+		;;
+	cmd-name)
+		rc_log_message "[running $1]"
+		;;
+	cmd-status)
+		# $1 is a command name, $2 is the command's exit status.
+		# If the command failed, report it, and add it to a list.
+		if [ "$2" != 0 ]; then
+			rc_failures="${rc_failures}${rc_failures:+ }$1"
+			msg="$1 reported failure status $2"
+			rc_log_message "$msg"
+			if ! $rc_silent; then
+				printf "%s\n" "$msg"
+			fi
+		fi
+		# After the mountcritlocal script has finished, it's
+		# OK to flush the log to disk
+		case "$1" in
+		*/mountcritlocal)
+			rc_log_flush OK
+			;;
+		esac
+		;;
+	note)
+		rc_log_message "[NOTE: $args]"
+		;;
+	end)
+		#
+		# If any scripts (or other commands) failed, report them.
+		#
+		if [ -n "$rc_failures" ]; then
+			rc_log_message "[failures]"
+			msg="The following components reported failures:"
+			msg="${msg}${nl}$( echo "    ${rc_failures}" | fmt )"
+			msg="${msg}${nl}See ${RC_LOG_FILE} for more information."
+			rc_log_message "${msg}"
+			printf "%s\n" "${msg}"
+		fi
+		#
+		# Report the end date/time, even in silent mode
+		#
+		rc_log_message "[$0 finished at $args]"
+		printf "%s\n" "$args"
+		;;
+	exit)
+		rc_log_message "[$0 exiting with status $1]"
+		exit $1
+		;;
+	interrupted)
+		# $args is a human-readable message
+		rc_log_message "$args"
+		printf "%s\n" "$args"
+		;;
+	*)
+		# an unrecognised line of metadata
+		rc_log_message "[metadata:${metadata}]"
+		;;
+	esac
+}
+
+#
+# rc_log_message string [...]
+#	write a message to the log file, or buffer it for later.
+#
+rc_log_message()
+{
+	_rc_log_buffer="${_rc_log_buffer}${*}${nl}"
+	rc_log_flush
+}
 
-date
-exit 0
+#
+# rc_log_flush [OK|FORCE]
+#	save outstanding messages from $_rc_log_buffer to $RC_LOG_FILE.
+#
+# The log file is expected to reside in the /var/run directory, which
+# may not be writable very early in the boot sequence, and which is
+# erased a little later in the boot sequence.  We therefore avoid
+# writing to the file until we believe it's safe to do so.  We also
+# assume that it's reasonable to always append to the file, never
+# truncating it.
+#
+# Optional argument $1 may be "OK" to report that writing to the log
+# file is expected to be safe from now on, or "FORCE" to force writing
+# to the log file even if it may be unsafe.
+#
+# Returns a non-zero status if messages could not be written to the
+# file.
+#
+rc_log_flush()
+{
+	#
+	# If $_rc_log_flush_ok is false, then it's probably too early to
+	# write to the log file, so don't do it, unless $1 is "FORCE".
+	#
+	: ${_rc_log_flush_ok=false}
+	case "$1:$_rc_log_flush_ok" in
+	OK:*)
+		_rc_log_flush_ok=true
+		;;
+	FORCE:*)
+		: OK just this once
+		;;
+	*:true)
+		: OK
+		;;
+	*)
+		# it's too early in the boot sequence, so don't flush
+		return 1
+		;;
+	esac
+
+	#
+	# Now append the buffer to the file.  The buffer should already
+	# contain a trailing newline, so don't add an extra newline.
+	#
+	if [ -n "$_rc_log_buffer" ]; then
+		if { printf "%s" "${_rc_log_buffer}" >>"${RC_LOG_FILE}" ; } \
+			2>/dev/null
+		then
+			_rc_log_buffer=""
+		else
+			return 1
+		fi
+	fi
+	return 0
+}
+
+#
+# Most of the action is in the rc_real_work() and rc_postprocess()
+# functions.
+#
+rc_real_work "$@" 2>&1 | rc_postprocess
+exit $?

Index: src/etc/rc.subr
diff -u src/etc/rc.subr:1.77 src/etc/rc.subr:1.78
--- src/etc/rc.subr:1.77	Sat Sep  5 16:45:33 2009
+++ src/etc/rc.subr	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-# $NetBSD: rc.subr,v 1.77 2009/09/05 16:45:33 apb Exp $
+# $NetBSD: rc.subr,v 1.78 2009/09/11 18:17:04 apb Exp $
 #
 # Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -33,6 +33,8 @@
 
 : ${rcvar_manpage:='rc.conf(5)'}
 : ${RC_PID:=$$} ; export RC_PID
+nl='
+' # a literal newline
 
 #
 #	functions
@@ -65,6 +67,23 @@
 }
 
 #
+# yesno_to_truefalse var
+#	Convert the value of a variable from any of the values
+#	understood by checkyesno() to "true" or "false".
+#
+yesno_to_truefalse()
+{
+	local var=$1
+	if checkyesno $var; then
+		eval $var=true
+		return 0
+	else
+		eval $var=false
+		return 1
+	fi
+}
+
+#
 # reverse_list list
 #	print the list in reverse order
 #
@@ -723,6 +742,13 @@
 #	a backup or scratch file, ignore it.  Otherwise if it's
 #	executable run as a child process.
 #
+#	If `file' contains "KEYWORD: interactive" and if we are
+#	running inside /etc/rc with postprocessing (as signified by
+#	_rc_postprocessor_fd being defined) then the script's stdout
+#	and stderr are redirected to $_rc_original_stdout_fd and
+#	$_rc_original_stderr_fd, so the output will be displayed on the
+#	console but not intercepted by /etc/rc's postprocessor.
+#
 run_rc_script()
 {
 	_file=$1
@@ -738,20 +764,43 @@
 		rcvar required_dirs required_files required_vars
 	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
 
+	_must_redirect=false
+	if ! [ -n "${_rc_postprocessor_fd}" ] \
+	    && _has_rcorder_keyword interactive $_file
+	then
+		_must_redirect=true
+	fi
+
 	case "$_file" in
 	*.sh)				# run in current shell
-		set $_arg ; . $_file
+		if $_must_redirect; then
+			print_rc_metadata \
+			    "note:Output from ${_file} is not logged"
+			set $_arg ; no_rc_postprocess . $_file
+		else
+			set $_arg ; . $_file
+		fi
 		;;
 	*[~#]|*.OLD|*.orig|*,v)		# scratch file; skip
 		warn "Ignoring scratch file $_file"
 		;;
 	*)				# run in subshell
-		if [ -x $_file ]; then
+		if [ -x $_file ] && $_must_redirect; then
+			print_rc_metadata \
+			    "note:Output from ${_file} is not logged"
+			if [ -n "$rc_fast_and_loose" ]; then
+				set $_arg ; no_rc_postprocess . $_file
+			else
+				( set $_arg ; no_rc_postprocess . $_file )
+			fi
+		elif [ -x $_file ]; then
 			if [ -n "$rc_fast_and_loose" ]; then
 				set $_arg ; . $_file
 			else
 				( set $_arg ; . $_file )
 			fi
+		else
+			warn "Ignoring non-executable file $_file"
 		fi
 		;;
 	esac
@@ -961,4 +1010,124 @@
 	stop_boot
 }
 
+#
+# _has_rcorder_keyword word file
+#	Check whether a file contains a "# KEYWORD:" comment with a
+#	specified keyword in the style used by rcorder(8).
+#
+_has_rcorder_keyword()
+{
+	local word="$1"
+	local file="$2"
+	local line
+
+	[ -r "$file" ] || return 1
+	while read line; do
+		case "${line} " in
+		"# KEYWORD:"*[\ \	]"${word}"[\ \	]*)
+			return 0
+			;;
+		"#"*)
+			continue
+			;;
+		*[A-Za-z0-9]*)
+			# give up at the first non-empty non-comment line
+			return 1
+			;;
+		esac
+	done <"$file"
+	return 1
+}
+
+#
+# print_rc_metadata string
+#	Print the specified string in such a way that the post-processor
+#	inside /etc/rc will treat it as meta-data.
+#
+#	If we are not running inside /etc/rc, do nothing.
+#
+#	For public use by any rc.d script, the string must begin with
+#	"note:", followed by arbitrary text.  The intent is that the text
+#	will appear in a log file but not on the console.
+#
+#	For private use within /etc/rc, the string must contain a
+#	keyword recognised by the rc_postprocess_metadata() function
+#	defined in /etc/rc, followed by a colon, followed by one or more
+#	colon-separated arguments associated with the keyword.
+#
+print_rc_metadata()
+{
+	# _rc_postprocessor fd, if defined, is the fd to which we must
+	# print, prefixing the output with $_rc_metadata_prefix.
+	#
+	if [ -n "$_rc_postprocessor_fd" ]; then
+		printf "%s%s\n" "$rc_metadata_prefix" "$1" \
+			>&${_rc_postprocessor_fd}
+	fi
+}
+
+#
+# print_rc_normal string
+#	Print the specified string in such way that it is treated as
+#	normal output, regardless of whether or not we are running
+#	inside /etc/rc with post-processing.
+#
+#	Ths intent is that a script that is run via the
+#	no_rc_postprocess() function (so its output would ordinarily be
+#	invisible to the post-processor) can nevertheless arrange for
+#	the post-processor to see things printed with print_rc_normal().
+#
+print_rc_normal()
+{
+	# If _rc_postprocessor_fd is defined, then it is the fd
+	# to shich we must print; otherwise print to stdout.
+	#
+	printf "%s\n" "$1" >&${_rc_postprocessor_fd:-1}
+}
+
+#
+# no_rc_postprocess cmd...
+#	Execute the specified command in such a way that its output
+#	bypasses the post-processor that handles the output from
+#	most commands that are run inside /etc/rc.  If we are not
+#	inside /etc/rc, then just execute the command without special
+#	treatment.
+#
+#	The intent is that interactive commands can be run via
+#	no_rc_postprocess(), and their output will apear immediately
+#	on the console instead of being hidden or delayed by the
+#	post-processor.	 An unfortunate consequence of the output
+#	bypassing the post-processor is that the output will not be
+#	logged.
+#
+no_rc_postprocess()
+{
+	if [ -n "${_rc_postprocessor_fd}" ]; then
+		"$@" >&${_rc_original_stdout_fd} 2>&${_rc_original_stderr_fd}
+	else
+		"$@"
+	fi
+}
+
+#
+# twiddle
+#	On each call, print a different one of "/", "-", "\\", "|",
+#	followed by a backspace.  The most recently printed value is
+#	saved in $_twiddle_state.
+#
+#	Output is to /dev/tty, so this function may be useful even inside
+#	a script whose output is redirected.
+#
+twiddle()
+{
+	case "$_twiddle_state" in
+	'/')	_next='-' ;;
+	'-')	_next='\' ;;
+	'\')	_next='|' ;;
+	*)	_next='/' ;;
+	esac
+	printf "%s\b" "$_next" >/dev/tty
+	_twiddle_state="$_next"
+}
+
 _rc_subr_loaded=:

Index: src/etc/defaults/rc.conf
diff -u src/etc/defaults/rc.conf:1.104 src/etc/defaults/rc.conf:1.105
--- src/etc/defaults/rc.conf:1.104	Sat Jul 25 16:20:10 2009
+++ src/etc/defaults/rc.conf	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: rc.conf,v 1.104 2009/07/25 16:20:10 mbalmer Exp $
+#	$NetBSD: rc.conf,v 1.105 2009/09/11 18:17:04 apb Exp $
 #
 # /etc/defaults/rc.conf --
 #	default configuration of /etc/rc.conf
@@ -26,6 +26,17 @@
 #
 #rc_fast_and_loose=YES
 
+# If rc_silent is true then /etc/rc will suppress most output to
+# the console.  The default is taken from the AB_SILENT flag passed
+# from the boot loader to the kernel in the boothowto(9) variable.
+#
+# rc_silent_cmd is executed once for each suppressed line of output.
+# Useful values are ":" and "twiddle".
+#
+rc_silent=$( [ "$(( $(/sbin/sysctl -n kern.boothowto 2>/dev/null || echo 0) \
+		    & 0x40000 ))" != 0 ] && echo true || echo false )
+rc_silent_cmd=twiddle
+
 # Additional flags to the rcorder(8) that's run by /etc/rc.
 #
 rc_rcorder_flags=""

Index: src/share/man/man5/rc.conf.5
diff -u src/share/man/man5/rc.conf.5:1.132 src/share/man/man5/rc.conf.5:1.133
--- src/share/man/man5/rc.conf.5:1.132	Thu Sep  3 20:06:39 2009
+++ src/share/man/man5/rc.conf.5	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: rc.conf.5,v 1.132 2009/09/03 20:06:39 apb Exp $
+.\"	$NetBSD: rc.conf.5,v 1.133 2009/09/11 18:17:04 apb Exp $
 .\"
 .\" Copyright (c) 1996 Matthew R. Green
 .\" All rights reserved.
@@ -195,6 +195,34 @@
 .Ev rc_directories
 must be located in the root filesystem, otherwise they will be silently
 skipped.
+.It Sy rc_silent
+Boolean value.
+If true then the usual output is suppresses, and
+.Xr rc 8
+invokes the command specified in the
+.Va rc_silent_cmd
+variable once for each line of suppressed output.
+The default value of
+.Va rc_silent
+is set from the
+.Dv AB_SILENT
+flag in the kernel's
+.Va boothowto
+variable (see
+.Xr boot 8 ,
+.Xr reboot 2 ) .
+.It Sy rc_silent_cmd
+A command to be executed once per line of suppressed output, when
+.Va rc_silent
+is true.
+The default value of
+.Va rc_silent_cmd
+is
+.Dq twiddle ,
+which will display a spinning symbol instead of each line of output.
+Another useful value is
+.Dq \&: ,
+which will display nothing at all.
 .El
 .Ss Basic network configuration
 .Bl -tag -width net_interfaces

Index: src/share/man/man8/rc.8
diff -u src/share/man/man8/rc.8:1.31 src/share/man/man8/rc.8:1.32
--- src/share/man/man8/rc.8:1.31	Wed Apr 30 13:10:57 2008
+++ src/share/man/man8/rc.8	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-.\" 	$NetBSD: rc.8,v 1.31 2008/04/30 13:10:57 martin Exp $
+.\" 	$NetBSD: rc.8,v 1.32 2009/09/11 18:17:04 apb Exp $
 .\"
 .\" Copyright (c) 2000-2004 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -116,6 +116,27 @@
 If the script has a
 .Sq .sh
 suffix then it is sourced directly into the current shell.
+.It
+The output from the above steps is sent to a post-processor.
+If
+.Sy rc_silent
+is false, then the post-processor displays the output.
+If
+.Sy rc_silent
+is true, then the post-processor invokes the command specified in
+.Va rc_silent_cmd
+once for each line, without otherwise displaying the output.
+Useful values for
+.Va rc_silent_cmd
+include
+.Dq \&:
+to display nothing at all, and
+.Dq twiddle
+to display a spinning symbol on the console.
+Regardless of the value of
+.Sy rc_silent ,
+the post-processor saves the output in
+.Pa /var/run/rc.log .
 .El
 .Ss Operation of rc.shutdown
 .Bl -enum
@@ -311,6 +332,9 @@
 functions used by various scripts.
 .It Pa /etc/rc.conf
 System startup configuration file.
+.It Pa /var/run/rc.log
+Log file created by
+.Nm .
 .El
 .Sh SEE ALSO
 .Xr rc.conf 5 ,
@@ -331,3 +355,9 @@
 by
 .An Luke Mewburn
 .Aq lu...@netbsd.org .
+The post-processor, support for
+.Va rc_silent ,
+and saving output to a file, was implemented in
+.Nx 6.0
+by
+.An Alan Barrett .

Index: src/share/man/man8/rc.subr.8
diff -u src/share/man/man8/rc.subr.8:1.22 src/share/man/man8/rc.subr.8:1.23
--- src/share/man/man8/rc.subr.8:1.22	Thu Apr  9 04:01:06 2009
+++ src/share/man/man8/rc.subr.8	Fri Sep 11 18:17:04 2009
@@ -1,4 +1,4 @@
-.\" 	$NetBSD: rc.subr.8,v 1.22 2009/04/09 04:01:06 joerg Exp $
+.\" 	$NetBSD: rc.subr.8,v 1.23 2009/09/11 18:17:04 apb Exp $
 .\"
 .\" Copyright (c) 2002-2004 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -54,6 +54,12 @@
 .It
 .Ic mount_critical_filesystems Ar type
 .It
+.Ic no_rc_postprocess Ar command Op Ar arguments
+.It
+.Ic print_rc_metadata Ar string
+.It
+.Ic print_rc_normal Ar string
+.It
 .Ic rc_usage Ar command Op Ar ...
 .It
 .Ic reverse_list Ar item Op Ar ...
@@ -64,9 +70,13 @@
 .It
 .Ic stop_boot
 .It
+.Ic twiddle
+.It
 .Ic wait_for_pids Op Ar pid Op Ar ...
 .It
 .Ic warn Ar message
+.It
+.Ic yesno_to_truefalse Ar var
 .El
 .Sh DESCRIPTION
 .Nm
@@ -251,6 +261,71 @@
 .Sy critical_filesystems_ Ns Ar type ,
 mounting each one that
 is not currently mounted.
+.It Ic no_rc_postprocess Ar command Op Ar arguments
+Execute the specified command with the specified arguments,
+in such a way that its output bypasses the post-processor that
+.Xr rc 8
+uses for most commands.
+This implies that the output will not appear in the
+.Pa /var/run/rc.log
+file, and will appear on the console regardless of the
+value of
+.Va rc_silent.
+This is expected to be useful for interactive commands,
+and this mechanism is automatically used by
+.Ic run_rc_command
+when a script contains the
+.Xr rcorder 8
+keyword
+.Dq interactive .
+.Pp
+If invoked from a context that does not appear to be under the control of
+.Xr rc 8 ,
+then the command is executed without special treatment.
+.It Ic print_rc_metadata Ar string
+Print the specified
+.Ar string
+in such a way that it should be handled as meta-data by the
+.Xr rc 8
+post-processor.
+If invoked from a context that does not appear to be under the control of
+.Xr rc 8 ,
+then the
+.Ar string
+is discarded.
+.Pp
+Any
+.Xr rc.d 8
+script may invoke this function with an argument that begins with
+.Dq note: ,
+followed by one line of arbitrary text;
+the text will be logged by
+.Xr rc 8
+but will not be displayed on the console.
+.Pp
+The use of arguments that do not begin with
+.Dq note:
+is reserved for internal use by
+.Xr rc 8
+and
+.Xr rc.subr 8 .
+.It Ic print_rc_normal Ar string
+Print the specified
+.Ar string
+in such a way that it should be handled as normal output by the
+.Xr rc 8
+post-processor.
+If invoked from a context that does not appear to be under the control of
+.Xr rc 8 ,
+then the
+.Ar string
+is printed to standard output.
+.Pp
+Ths intent is that a script that is run via the
+.Fn no_rc_postprocess
+function (so its output would ordinarily be invisible to the post-processor)
+can nevertheless arrange for the post-processor to see things printed with
+.Fn print_rc_normal.
 .It Ic rc_usage Ar command Op Ar ...
 Print a usage message for
 .Sy $0 ,
@@ -663,6 +738,15 @@
 otherwise source
 .Ar file
 into the current shell.
+.It
+If
+.Ar file
+contains the
+.Xr rcorder 8
+keyword
+.Dq interactive ,
+then the command is executed using
+.Ic no_rc_postprocess .
 .El
 .It Ic stop_boot
 Prevent booting to multiuser mode.
@@ -677,6 +761,16 @@
 .Xr rc 8 ) .
 Otherwise, the shell exits with status
 .Li 1 .
+.It Ic twiddle
+Display one of the characters
+.Sq \&/ , \&- , \&\e , \&| ,
+followed by a backspace.
+Repeated calls to this function will create the appearance of a spinning
+symbol, as a different character is displayed on each call.
+Output is to
+.Pa /dev/tty ,
+so this function may be useful even inside a script whose output
+has been redirected.
 .It Ic wait_for_pids Op Ar pid Op Ar ...
 Wait until all of the provided
 .Ar pids
@@ -696,6 +790,14 @@
 .Dq ": WARNING: " ,
 and then
 .Ar message .
+.It Ic yesno_to_truefalse Ar var
+Change the value of the specified variable from any of the
+forms acceptable to the
+.Is checkyesno
+function, to
+.Dq true
+or
+.Dq false .
 .El
 .Sh FILES
 .Bl -tag -width /etc/rc.subr -compact
@@ -716,3 +818,7 @@
 .Xr rc.d 8
 support functions appeared in
 .Nx 1.5 .
+Support for the
+.Xr rc 8
+post-processor appeared in
+.Nx 6.0 .

Reply via email to