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 [email protected] .
+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 .