Page MenuHomeFreeBSD

D43671.diff
No OneTemporary

D43671.diff

diff --git a/libexec/rc/Makefile b/libexec/rc/Makefile
--- a/libexec/rc/Makefile
+++ b/libexec/rc/Makefile
@@ -18,6 +18,12 @@
CONFETCDEFAULTS= rc.conf
CONFETCDEFAULTSPACKAGE= rc
+FILESGROUPS= LIBEXEC_SCRIPTS
+LIBEXEC_SCRIPTS= debug.sh safe_eval.sh
+LIBEXEC_SCRIPTSDIR= /libexec
+LIBEXEC_SCRIPTSMODE= 755
+LIBEXEC_SCRIPTSPACKAGE= rc
+
SUBDIR+= rc.d
HAS_TESTS=
diff --git a/libexec/rc/debug.sh b/libexec/rc/debug.sh
new file mode 100755
--- /dev/null
+++ b/libexec/rc/debug.sh
@@ -0,0 +1,278 @@
+:
+# SPDX-License-Identifier: BSD-2-Clause
+
+# NAME:
+# debug.sh - selectively debug scripts
+#
+# SYNOPSIS:
+# $_DEBUG_SH . debug.sh
+# DebugOn [-eo] "tag" ...
+# DebugOff [-eo] [rc="rc"] "tag" ...
+# Debugging
+# DebugEcho ...
+# DebugLog ...
+# DebugShell "tag" ...
+# DebugTrace ...
+# Debug "tag" ...
+#
+# $DEBUG_SKIP echo skipped when Debug "tag" is true.
+# $DEBUG_DO echo only done when Debug "tag" is true.
+#
+# DESCRIPTION:
+# debug.sh provides the following functions to facilitate
+# flexible run-time tracing of complicated shell scripts.
+#
+# DebugOn turns tracing on if any "tag" is found in "DEBUG_SH".
+# It turns tracing off if "!tag" is found in "DEBUG_SH".
+# It also sets "DEBUG_ON" to the "tag" that caused tracing to be
+# enabled, or "DEBUG_OFF" if we matched "!tag".
+# If '-e' option given returns 1 if no "tag" matched.
+# If the '-o' flag is given, tracing is turned off unless there
+# was a matched "tag", useful for functions too noisy to tace.
+#
+# DebugOff turns tracing on if any "tag" matches "DEBUG_OFF" or
+# off if any "tag" matches "DEBUG_ON". This allows nested
+# functions to not interfere with each other.
+#
+# DebugOff accepts but ignores the '-e' and '-o' options.
+# The optional "rc" value will be returned rather than the
+# default of 0. Thus if DebugOff is the last operation in a
+# function, "rc" will be the return code of that function.
+#
+# DebugEcho is just shorthand for:
+#.nf
+# $DEBUG_DO echo "$@"
+#.fi
+#
+# Debugging returns true if tracing is enabled.
+# It is useful for bounding complex debug actions, rather than
+# using lots of "DEBUG_DO" lines.
+#
+# DebugShell runs an interactive shell if any "tag" is found in
+# "DEBUG_INTERACTIVE", and there is a tty available.
+# The shell used is defined by "DEBUG_SHELL" or "SHELL" and
+# defaults to '/bin/sh'.
+#
+# Debug calls DebugOn and if that does not turn tracing on, it
+# calls DebugOff to turn it off.
+#
+# The variables "DEBUG_SKIP" and "DEBUG_DO" are set so as to
+# enable/disable code that should be skipped/run when debugging
+# is turned on. "DEBUGGING" is the same as "DEBUG_SKIP" for
+# backwards compatability.
+#
+# The use of $_DEBUG_SH is to prevent multiple inclusion, though
+# it does no harm in this case.
+#
+# BUGS:
+# Does not work with some versions of ksh.
+# If a function turns tracing on, ksh turns it off when the
+# function returns - useless.
+# PD ksh works ok ;-)
+#
+# AUTHOR:
+# Simon J. Gerraty <sjg@crufty.net>
+
+# RCSid:
+# $Id: debug.sh,v 1.35 2024/02/03 19:04:47 sjg Exp $
+#
+# @(#) Copyright (c) 1994-2024 Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+_DEBUG_SH=:
+
+Myname=${Myname:-`basename $0 .sh`}
+
+DEBUGGING=
+DEBUG_DO=:
+DEBUG_SKIP=
+export DEBUGGING DEBUG_DO DEBUG_SKIP
+
+_debugOn() {
+ DEBUG_OFF=
+ DEBUG_DO=
+ DEBUG_SKIP=:
+ DEBUG_X=-x
+ set -x
+ DEBUG_ON=$1
+}
+
+_debugOff() {
+ DEBUG_OFF=$1
+ set +x
+ DEBUG_ON=$2
+ DEBUG_DO=:
+ DEBUG_SKIP=
+ DEBUG_X=
+}
+
+DebugEcho() {
+ $DEBUG_DO echo "$@"
+}
+
+Debugging() {
+ test "$DEBUG_SKIP"
+}
+
+DebugLog() {
+ $DEBUG_SKIP return 0
+ echo `date '+@ %s [%Y-%m-%d %H:%M:%S %Z]'` "$@"
+}
+
+# something hard to miss when wading through huge -x output
+DebugTrace() {
+ $DEBUG_SKIP return 0
+ set +x
+ echo "@ ==================== [ $DEBUG_ON ] ===================="
+ DebugLog "$@"
+ echo "@ ==================== [ $DEBUG_ON ] ===================="
+ set -x
+}
+
+# Turn on debugging if appropriate
+DebugOn() {
+ _rc=0 # avoid problems with set -e
+ _off=:
+ while :
+ do
+ case "$1" in
+ -e) _rc=1; shift;; # caller ok with return 1
+ -o) _off=; shift;; # off unless we have a match
+ *) break;;
+ esac
+ done
+ case ",${DEBUG_SH:-$DEBUG}," in
+ ,,) return $_rc;;
+ *,[Dd]ebug,*) ;;
+ *) $DEBUG_DO set +x;; # reduce the noise
+ esac
+ _match=
+ # if debugging is off because of a !e
+ # don't add 'all' to the On list.
+ case "$_off$DEBUG_OFF" in
+ :) _e=all;;
+ *) _e=;;
+ esac
+ for _e in ${*:-$Myname} $_e
+ do
+ : $_e in ,${DEBUG_SH:-$DEBUG},
+ case ",${DEBUG_SH:-$DEBUG}," in
+ *,!$_e,*|*,!$Myname:$_e,*)
+ # only turn it off if it was on
+ _rc=0
+ $DEBUG_DO _debugOff $_e $DEBUG_ON
+ break
+ ;;
+ *,$_e,*|*,$Myname:$_e,*)
+ # only turn it on if it was off
+ _rc=0
+ _match=$_e
+ $DEBUG_SKIP _debugOn $_e
+ break
+ ;;
+ esac
+ done
+ if test -z "$_off$_match"; then
+ # off unless explicit match, but
+ # only turn it off if it was on
+ $DEBUG_DO _debugOff $_e $DEBUG_ON
+ fi
+ DEBUGGING=$DEBUG_SKIP # backwards compatability
+ $DEBUG_DO set -x # back on if needed
+ $DEBUG_DO set -x # make sure we see it in trace
+ return $_rc
+}
+
+# Only turn debugging off if one of our args was the reason it
+# was turned on.
+# We normally return 0, but caller can pass rc=$? as first arg
+# so that we preserve the status of last statement.
+DebugOff() {
+ case ",${DEBUG_SH:-$DEBUG}," in
+ *,[Dd]ebug,*) ;;
+ *) $DEBUG_DO set +x;; # reduce the noise
+ esac
+ _rc=0 # always happy
+ while :
+ do
+ case "$1" in
+ -[eo]) shift;; # ignore it
+ rc=*) eval "_$1"; shift;;
+ *) break;;
+ esac
+ done
+ for _e in $*
+ do
+ : $_e==$DEBUG_OFF DEBUG_OFF
+ case "$DEBUG_OFF" in
+ "") break;;
+ $_e) _debugOn $DEBUG_ON; return $_rc;;
+ esac
+ done
+ for _e in $*
+ do
+ : $_e==$DEBUG_ON DEBUG_ON
+ case "$DEBUG_ON" in
+ "") break;;
+ $_e) _debugOff; return $_rc;;
+ esac
+ done
+ DEBUGGING=$DEBUG_SKIP # backwards compatability
+ $DEBUG_DO set -x # back on if needed
+ $DEBUG_DO set -x # make sure we see it in trace
+ return $_rc
+}
+
+_TTY=${_TTY:-`test -t 0 && tty`}; export _TTY
+
+# override this if you like
+_debugShell() {
+ {
+ echo DebugShell "$@"
+ echo "Type 'exit' to continue..."
+ } > $_TTY
+ ${DEBUG_SHELL:-${SHELL:-/bin/sh}} < $_TTY > $_TTY 2>&1
+}
+
+# Run an interactive shell if appropriate
+# Note: you can use $DEBUG_SKIP DebugShell ... to skip unless debugOn
+DebugShell() {
+ case "$_TTY%${DEBUG_INTERACTIVE}" in
+ *%|%*) return 0;; # no tty or no spec
+ esac
+ for _e in ${*:-$Myname} all
+ do
+ case ",${DEBUG_INTERACTIVE}," in
+ *,!$_e,*|*,!$Myname:$_e,*)
+ return 0
+ ;;
+ *,$_e,*|*,$Myname:$_e,*)
+ # Provide clues as to why/where
+ _debugShell "$_e: $@"
+ return $?
+ ;;
+ esac
+ done
+ return 0
+}
+
+# For backwards compatability
+Debug() {
+ case "${DEBUG_SH:-$DEBUG}" in
+ "") ;;
+ *) DEBUG_ON=${DEBUG_ON:-_Debug}
+ DebugOn -e $* || DebugOff $DEBUG_LAST
+ DEBUGGING=$DEBUG_SKIP
+ ;;
+ esac
+}
diff --git a/libexec/rc/rc b/libexec/rc/rc
--- a/libexec/rc/rc
+++ b/libexec/rc/rc
@@ -66,8 +66,11 @@
# to minimize the number of files that are needed on a diskless system,
# and to make the configuration file variables available to rc itself.
#
+# -o verify has no effect if mac_veriexec is not active
+set -o verify
. /etc/rc.subr
-load_rc_config
+set +o verify
+load_rc_config $rc_config_xtra
# If we receive a SIGALRM, re-source /etc/rc.conf; this allows rc.d
# scripts to perform "boot-time configuration" including enabling and
@@ -93,16 +96,7 @@
unset system_rc
find_system_scripts
files=`rcorder ${skip} ${skip_firstboot} ${system_rc} 2>/dev/null`
-
-_rc_elem_done=' '
-for _rc_elem in ${files}; do
- run_rc_script ${_rc_elem} ${_boot}
- _rc_elem_done="${_rc_elem_done}${_rc_elem} "
-
- case "$_rc_elem" in
- */${early_late_divider}) break ;;
- esac
-done
+run_rc_scripts --break ${early_late_divider} ${rc_early_flags} $files
unset files local_rc system_rc
@@ -122,13 +116,13 @@
find_system_scripts
files=`rcorder ${skip} ${skip_firstboot} ${system_rc} ${local_rc} 2>/dev/null`
-for _rc_elem in ${files}; do
- case "$_rc_elem_done" in
- *" $_rc_elem "*) continue ;;
- esac
+run_rc_scripts ${rc_late_flags} $files
+unset files local_rc system_rc
- run_rc_script ${_rc_elem} ${_boot}
-done
+# allow for more complicated setups
+if have run_rc_scripts_final; then
+ run_rc_scripts_final
+fi
# Remove the firstboot sentinel, and reboot if it was requested.
# Be a bit paranoid about removing it to handle the common failure
diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -66,6 +66,122 @@
# functions
# ---------
+# is_verified file
+# if VERIEXEC is active check that $file is verified
+#
+VERIEXEC="/sbin/veriexec"
+if test -x $VERIEXEC && $VERIEXEC -i active > /dev/null 2>&1; then
+ is_verified() { $VERIEXEC -x $1; }
+else
+ is_verified() { return 0; }
+fi
+
+# indicate that we have vdot
+_VDOT_SH=:
+
+# current state of O_VERIFY
+o_verify()
+{
+ set -o | sed -n '/^verify/s,.*[[:space:]],,p'
+}
+
+##
+# o_verify_set want [save]
+#
+# record current state of verify in $save
+# and set it to $want if different
+#
+o_verify_set() {
+ local x=$(o_verify)
+
+ [ -z "$x" ] && return 0
+ [ -z "$2" ] || eval $2=$x
+ [ "$x" = "$1" ] && return 0
+ case "$1" in
+ on)
+ set -o verify
+ ;;
+ off)
+ set +o verify
+ ;;
+ esac
+}
+
+# for unverified files
+dotted=
+dot()
+{
+ local f verify
+
+ o_verify_set off verify
+ for f in "$@"; do
+ if [ -f $f -a -s $f ]; then
+ dotted="$dotted $f"
+ . $f
+ fi
+ done
+ o_verify_set $verify
+}
+
+# try for verified, fallback to safe
+sdot()
+{
+ local f
+
+ for f in "$@"; do
+ [ -f $f -a -s $f ] || continue
+ vdot $f || safe_dot $f
+ done
+}
+
+# convenience function - skip if not verified
+vdot()
+{
+ local f rc=0 verify
+
+ o_verify_set on verify
+ for f in "$@"; do
+ [ -f $f -a -s $f ] || continue
+ if is_verified $f 2> /dev/null; then
+ dotted="$dotted $f"
+ . $f
+ else
+ rc=80 # EAUTH
+ fi
+ done
+ o_verify_set $verify
+ return $rc
+}
+
+# do we have $1 (could be a function)
+have()
+{
+ type "$1" > /dev/null 2>&1
+}
+
+# provide consistent means of logging progress
+rc_log()
+{
+ date "+@ %s [%Y-%m-%d %H:%M:%S %Z] $*"
+}
+
+# only rc_log if tracing enabled
+# and $level >= $RC_LEVEL
+rc_trace()
+{
+ local level=$1; shift
+ local cf=/etc/rc.conf.d/rc_trace
+
+ if [ -z "$RC_LEVEL" ]; then
+ [ -f $cf ] || return
+ [ -s $cf ] && \
+ RC_LEVEL=$(sed -n '/^RC_LEVEL=/ { s/.*=//p;q; }' $cf)
+ RC_LEVEL=${RC_LEVEL:-0}
+ fi
+ [ ${RC_LEVEL:-0} -ge ${level:-0} ] || return
+ rc_log "$@"
+}
+
# list_vars pattern
# List variables matching glob pattern.
#
@@ -924,6 +1040,8 @@
err 3 'run_rc_command: $name is not set.'
fi
+ DebugOn rc:$name rc:$name:$rc_arg $name:$rc_arg
+
# Don't repeat the first argument when passing additional command-
# line arguments to the command subroutines.
#
@@ -1077,6 +1195,7 @@
_postcmd=\$${rc_arg}_postcmd
if [ -n "$_cmd" ]; then
+ rc_trace 1 "$_cmd"
if [ -n "$_env" ]; then
eval "export -- $_env"
fi
@@ -1449,6 +1568,10 @@
required_vars
eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
+ rc_trace 0 "$_file $_arg"
+ # don't use it if we don't trust it
+ is_verified $_file || return
+
rc_service="$_file"
case "$_file" in
/etc/rc.d/*.sh) # no longer allowed in the base
@@ -1459,6 +1582,8 @@
;;
*) # run in subshell
if [ -x $_file ]; then
+ DebugOn $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg
+
if [ -n "$rc_boottrace" ]; then
boottrace_fn "$_file" "$_arg"
elif [ -n "$rc_fast_and_loose" ]; then
@@ -1469,11 +1594,65 @@
trap "echo Script $_file running >&2" 29
set $_arg; . $_file )
fi
+ DebugOff $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg
fi
;;
esac
}
+#
+# run_rc_scripts [options] file [...]
+#
+# Call `run_rc_script' for each "file" unless already listed in
+# $_rc_elem_done.
+#
+# Options:
+#
+# --arg "arg"
+# Pass "arg" to `run_rc_script' default is $_boot.
+#
+# --break "marker"
+# If any "file" matches "marker" stop processing.
+#
+_rc_elem_done=
+run_rc_scripts()
+{
+ local _arg=${_boot}
+ local _rc_elem
+ local _rc_breaks=
+
+ while :; do
+ case "$1" in
+ --arg)
+ _arg="$2"
+ shift 2
+ ;;
+ --break)
+ _rc_breaks="$_rc_breaks $2"
+ shift 2
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ for _rc_elem in "$@"; do
+ : _rc_elem=$_rc_elem
+ case " $_rc_elem_done " in
+ *" $_rc_elem "*)
+ continue
+ ;;
+ esac
+ run_rc_script ${_rc_elem} ${_arg}
+ _rc_elem_done="$_rc_elem_done $_rc_elem"
+ case " $_rc_breaks " in
+ *" ${_rc_elem##*/} "*)
+ break
+ ;;
+ esac
+ done
+}
+
boottrace_fn()
{
local _file _arg
@@ -1502,19 +1681,42 @@
#
load_rc_config()
{
- local _name _rcvar_val _var _defval _v _msg _new _d
+ local _name _rcvar_val _var _defval _v _msg _new _d _dot
_name=$1
+ _dot=${load_rc_config_reader:-dot}
+
+ case "$_dot" in
+ dot|[sv]dot)
+ ;;
+ *) warn "Ignoring invalid load_rc_config_reader"
+ _dot=dot
+ ;;
+ esac
+ case "$1" in
+ -s|--safe)
+ _dot=sdot
+ _name=$2
+ shift
+ ;;
+ -v|--verify)
+ _dot=vdot
+ _name=$2
+ shift
+ ;;
+ esac
+
+ DebugOn rc:$_name $_name
if ${_rc_conf_loaded:-false}; then
:
else
if [ -r /etc/defaults/rc.conf ]; then
debug "Sourcing /etc/defaults/rc.conf"
- . /etc/defaults/rc.conf
+ $_dot /etc/defaults/rc.conf
source_rc_confs
elif [ -r /etc/rc.conf ]; then
debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
- . /etc/rc.conf
+ $_dot /etc/rc.conf
fi
_rc_conf_loaded=true
fi
@@ -1526,13 +1728,13 @@
_d=${_d%/rc.d}
if [ -f ${_d}/rc.conf.d/"$_name" ]; then
debug "Sourcing ${_d}/rc.conf.d/$_name"
- . ${_d}/rc.conf.d/"$_name"
+ $_dot ${_d}/rc.conf.d/"$_name"
elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then
local _rc
for _rc in ${_d}/rc.conf.d/"$_name"/* ; do
if [ -f "$_rc" ] ; then
debug "Sourcing $_rc"
- . "$_rc"
+ $_dot "$_rc"
fi
done
fi
@@ -2286,3 +2488,24 @@
if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then
rc_boottrace=YES
fi
+
+# Allow for local additions and overrides.
+# Use vdot to ensure the file has not been tampered with.
+vdot /etc/local.rc.subr
+
+# safe_eval.sh provides safe_dot - for untrusted files
+$_SAFE_EVAL_SH vdot /libexec/safe_eval.sh
+$_DEBUG_SH vdot /libexec/debug.sh
+
+# Ensure we can still operate if debug.sh and
+# safe_eval.sh are not found.
+if have DebugOn; then
+ # allow DEBUG_SH to be set from loader prompt
+ DEBUG_SH=${DEBUG_SH:-$(kenv -q DEBUG_SH)}
+else
+ DebugOn() { return 0; }
+ DebugOff() { return 0; }
+fi
+if ! have save_dot; then
+ safe_dot() { dot "$@"; }
+fi
diff --git a/libexec/rc/safe_eval.sh b/libexec/rc/safe_eval.sh
new file mode 100644
--- /dev/null
+++ b/libexec/rc/safe_eval.sh
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+# RCSid:
+# $Id: safe_eval.sh,v 1.12 2023/10/12 18:46:53 sjg Exp $
+#
+# @(#) Copyright (c) 2023 Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+
+_SAFE_EVAL_SH=:
+
+##
+# safe_set
+#
+# return a safe variable setting
+# any non-alphanumeric chars are replaced with '_'
+#
+safe_set() {
+ sed 's/[ ]*#.*//;/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. "$,/=-];_;g'
+}
+
+##
+# safe_eval [file]
+#
+# eval variable assignments only from file
+# taking care to eliminate any shell meta chars
+#
+safe_eval() {
+ eval `cat "$@" | safe_set`
+}
+
+##
+# safe_dot file [...]
+#
+# feed all "file" that exist to safe_eval
+#
+safe_dot() {
+ local ef= f
+
+ for f in "$@"
+ do
+ test -s $f || continue
+ ef="${ef:+$ef }$f"
+ dotted="$dotted $f"
+ done
+ test -z "$ef" && return 1
+ safe_eval $ef
+ return 0
+}
+
+case /$0 in
+*/safe_eval*)
+ case "$1" in
+ dot|eval|set) op=safe_$1; shift; $op "$@";;
+ *) safe_dot "$@";;
+ esac
+ ;;
+esac
diff --git a/share/man/man8/Makefile b/share/man/man8/Makefile
--- a/share/man/man8/Makefile
+++ b/share/man/man8/Makefile
@@ -4,6 +4,7 @@
MAN= \
beinstall.8 \
crash.8 \
+ debug.sh.8 \
diskless.8 \
intro.8 \
nanobsd.8 \
diff --git a/share/man/man8/debug.sh.8 b/share/man/man8/debug.sh.8
new file mode 100644
--- /dev/null
+++ b/share/man/man8/debug.sh.8
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1994-2021 Simon J. Gerraty
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" This file is provided in the hope that it will
+.\" be of use. There is absolutely NO WARRANTY.
+.\" Permission to copy, redistribute or otherwise
+.\" use this file is hereby granted provided that
+.\" the above copyright notice and this notice are
+.\" left intact.
+.\"
+.\" Please send copies of changes and bug-fixes to:
+.\" sjg@crufty.net
+.\"
+.Dd January 31, 2024
+.Dt DEBUG.SH 8
+.Os
+.Sh NAME
+.Nm debug.sh
+.Nd selectively debug scripts
+.Sh SYNOPSIS
+.Bl -item -compact
+.It
+.Ic $_DEBUG_SH .\& Pa debug.sh
+.Pp
+.It
+.Ic DebugOn Oo Fl eo Oc Ar tag ...
+.It
+.Ic DebugOff Oo Fl eo Oc Oo Cm rc= Ns Ar rc Oc Ar tag ...
+.It
+.Ic Debugging
+.It
+.Ic DebugEcho Op Ar message
+.It
+.Ic DebugLog Op Ar message
+.It
+.Ic DebugShell Ar tag ...
+.It
+.Ic DebugTrace Ar message
+.It
+.Ic Debug Ar tag ...
+.El
+.Sh DESCRIPTION
+.Nm
+provides the following functions to facilitate flexible
+run-time tracing of complicated shell scripts.
+.Bl -tag -width 4n
+.It Ic DebugOn Oo Fl eo Oc Ar tag ...
+turns tracing on if any
+.Ar tag
+is found in
+.Va DEBUG_SH
+(a comma separated list of tags).
+.Pp
+It turns tracing off if
+.Ar !tag
+is found in
+.Va DEBUG_SH .
+.Pp
+It sets
+.Va DEBUG_ON
+to the
+.Ar tag
+that caused tracing to be enabled, or
+.Va DEBUG_OFF
+if we matched
+.Ar !tag .
+.Pp
+If
+.Fl e
+option is present, returns 1 if no
+.Ar tag
+matched.
+.Pp
+If
+.Fl o
+option is present, tracing is turned off unless there
+was a matched
+.Ar tag ,
+useful for functions too noisy to tace.
+.It Ic DebugOff Oo Fl eo Oc Oo Cm rc= Ns Ar rc Oc Ar tag ...
+turns tracing on if any
+.Ar tag
+matches
+.Va DEBUG_OFF
+or off if any
+.Ar tag
+matches
+.Va DEBUG_ON .
+This allows nested functions to not interfere with each other.
+.Pp
+The flags
+.Fl e
+and
+.Fl o
+are ignored, they just allow for symmetry with calls to
+.Fn DebugOn .
+.Pp
+The optional
+.Ar rc
+value will be returned rather than the default of 0.
+Thus if
+.Fn DebugOff
+is the last operation in a function,
+.Ar rc
+will be the return code of the function.
+.It Ic Debugging
+returns true if tracing is enabled.
+It is useful for bounding complex debug actions, rather than
+using lots of
+.Ic $DEBUG_DO
+lines.
+.It Ic DebugEcho
+is just shorthand for:
+.Bd -literal -offset indent
+$DEBUG_DO echo "$@"
+.Ed
+.It Ic DebugLog Op Ar message
+If debugging is enabled, output
+.Ar message
+prefixed with a time-stamp.
+.It Ic DebugShell Ar tag ...
+runs an interactive shell if any
+.Ar tag
+is found in
+.Va DEBUG_INTERACTIVE ,
+and there is a tty available.
+The shell used is defined by
+.Va DEBUG_SHELL
+or
+.Va SHELL
+and defaults to
+.Pa /bin/sh .
+.It Ic DebugTrace Ar message
+Debug output can be very noisy, and it can be tricky
+to align with the script.
+This function outputs a very noticable banner indicating the value of
+.Va DEBUG_ON ,
+and
+.Ar message
+is passed to
+.Fn DebugLog ,
+finally the banner is repeated.
+.It Ic Debug Ar tag ...
+For backwards compatibility, calls
+.Fn DebugOn
+and if that does not turn tracing on,
+it calls
+.Fn DebugOff
+to turn it off.
+.El
+.Pp
+The variables
+.Va DEBUG_SKIP
+and
+.Va DEBUG_DO
+are set so as to enable/disable code that should be
+skipped/run when debugging is turned on.
+.Va DEBUGGING
+is the same as
+.Va DEBUG_SKIP
+for backwards compatability and is only set by
+.Fn Debug .
+.Pp
+The use of
+.Ic $_DEBUG_SH
+is to prevent multiple inclusion,
+though it does no harm in this case.
+.Sh BUGS
+Does not work with some versions of
+.Xr ksh 1 .
+If a function turns tracing on, ksh turns it off when the
+function returns - useless.
+.Pp
+PD ksh works ok ;-)
+.Sh AUTHOR
+.An -nosplit
+.Nm
+was written by
+.An Simon J Gerraty Aq Mt sjg@crufty.net .
+
+
diff --git a/share/man/man8/rc.8 b/share/man/man8/rc.8
--- a/share/man/man8/rc.8
+++ b/share/man/man8/rc.8
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 27,2023
+.Dd January 31, 2024
.Dt RC 8
.Os
.Sh NAME
@@ -148,9 +148,13 @@
.Fl s
flag).
.It
-Call each script in turn using
+Call
+.Fn run_rc_scripts
+with the list of scripts to be run.
+.Pp
+For each script that will call
.Fn run_rc_script
-(from
+(both functions are from
.Xr rc.subr 8 ) ,
which sets
.Va $1
@@ -171,9 +175,11 @@
this time including the scripts in the
.Va $local_startup
directories.
-Ignore everything up to the
-.Va $early_late_divider ,
-then start executing the scripts as described above.
+Call
+.Fn run_rc_scripts
+again with the new list of scripts.
+It will skip any that have already been run and
+execute the rest as described above.
.It
If the file
.Va ${firstboot_sentinel}
diff --git a/share/man/man8/rc.subr.8 b/share/man/man8/rc.subr.8
--- a/share/man/man8/rc.subr.8
+++ b/share/man/man8/rc.subr.8
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd August 16, 2022
+.Dd January 31, 2024
.Dt RC.SUBR 8
.Os
.Sh NAME
@@ -47,22 +47,34 @@
.It
.Ic check_process Ar procname Op Ar interpreter
.It
+.Ic DebugOn Ar tag ...
+.It
+.Ic DebugOff Ar tag ...
+.It
.Ic debug Ar message
.It
+.Ic dot Ar file ...
+.It
.Ic err Ar exitval Ar message
.It
.Ic force_depend Ar name
.It
.Ic info Ar message
.It
+.Ic is_verified Ar file
+.It
.Ic load_kld Oo Fl e Ar regex Oc Oo Fl m Ar module Oc Ar file
.It
-.Ic load_rc_config Op Ar service
+.Ic load_rc_config Oo Ar flag Oc Op Ar service
.It
.Ic load_rc_config_var Ar name Ar var
.It
.Ic mount_critical_filesystems Ar type
.It
+.Ic rc_log Ar message
+.It
+.It rc_trace Ar level Ar message
+.It
.Ic rc_usage Ar command ...
.It
.Ic reverse_list Ar item ...
@@ -71,8 +83,16 @@
.It
.Ic run_rc_script Ar file Ar argument
.It
+.Ic run_rc_scripts Oo options Oc Ar file ...
+.It
+.Ic safe_dot Ar file ...
+.It
+.Ic sdot Ar file ...
+.It
.Ic startmsg Oo Fl n Oc Ar message
.It
+.Ic vdot Ar file ...
+.It
.Ic wait_for_pids Op Ar pid ...
.It
.Ic warn Ar message
@@ -191,6 +211,43 @@
.Ar interpreter
is handled as per
.Ic check_pidfile .
+.It Ic DebugOn Ar tag ...
+Enable tracing if not already enabled,
+and any
+.Ar tag
+is found in
+.Va DEBUG_SH
+(a comma separated list of tags).
+.Pp
+Record the
+.Ar tag
+that caused it to be enabled in
+.Va DEBUG_ON ,
+set
+.Va DEBUG_DO
+empty and
+.Va DEBUG_SKIP
+to
+.Ql \&: .
+.Pp
+See
+.Xr debug.sh 8
+for more details.
+.It Ic DebugOff Ar tag ...
+Disable tracing if enabled and any
+.Ar tag
+matches
+.Va DEBUG_ON ,
+which means it was the reason tracing was enabled.
+.Pp
+Set
+.Va DEBUG_DO
+to
+.Ql \&: ,
+and
+.Va DEBUG_ON ,
+.Va DEBUG_SKIP
+empty.
.It Ic debug Ar message
Display a debugging message to
.Va stderr ,
@@ -212,6 +269,23 @@
.Xr rc.conf 5
variable
.Va rc_debug .
+.It Ic dot Ar file ...
+For reading in unverified files.
+.Pp
+Ensure shell
+.Li verify
+option is off.
+This option is only meaningful when
+.Xr mac_veriexec 4
+is active.
+.Pp
+Read each
+.Ar file
+if it exists.
+.Pp
+Restore previous state of the
+.Li verify
+option.
.It Ic err Ar exitval message
Display an error message to
.Va stderr ,
@@ -248,6 +322,18 @@
and return with a return value of 1.
If it was successful
it will return 0.
+.It Ic is_verified Ar file
+If
+.Xr veriexec 8
+does not exist, or
+.Xr mac_veriexec 4
+is not active, just return success.
+Otherwise use
+.Xr veriexec 8
+to check if
+.Ar file
+is verified.
+If not verified the return code will be 80 (EAUTH).
.It Ic info Ar message
Display an informational message to
.Va stdout ,
@@ -279,7 +365,7 @@
By default, the module is assumed to have the same name as
.Ar file ,
which is not always the case.
-.It Ic load_rc_config Op Ar service
+.It Ic load_rc_config Oo Ar flag Oc Op Ar service
Source in the configuration file(s) for
.Ar service .
If no
@@ -298,6 +384,26 @@
mechanism for an administrator to override the behaviour of a given
.Xr rc.d 8
script without requiring the editing of that script.
+.Pp
+The function
+.Ic dot
+is used to read configuration unless
+.Ar flag
+is:
+.Bl -tag -width Ds
+.It Fl s
+use
+.Ic sdot
+to read configuration,
+because we want verified configuration or
+to use
+.Ic safe_dot
+to read an unverified configuration.
+.It Fl v
+use
+.Ic vdot
+to read in configuration only if it is verified.
+.El
.It Ic load_rc_config_var Ar name Ar var
Read the
.Xr rc.conf 5
@@ -317,6 +423,34 @@
.Va critical_filesystems_ Ns Ar type ,
mounting each one that
is not currently mounted.
+.It Ic rc_log Ar message
+Output
+.Ar message
+with a timestamp, which is both human readable and
+easily parsed for post processing, using:
+.Bd -literal -offset indent
+date "+@ %s [%Y-%m-%d %H:%M:%S %Z] $*"
+.Ed
+.It Ic rc_trace Ar level Ar message
+If the file
+.Pa /etc/rc.conf.d/rc_trace
+exists and is not empty attempt to set
+.Va RC_LEVEL
+based on its content.
+If the file is empty or does not contain
+a value for
+.Va RC_LEVEL ,
+set it to
+Li 0 .
+.Pp
+If
+.Ar level
+is greater than or equal to
+.Va RC_LEVEL
+pass
+.Ar message
+to
+.Ic rc_log .
.It Ic rc_usage Ar command ...
Print a usage message for
.Va $0 ,
@@ -849,6 +983,16 @@
.Ar argument Ns Va _postcmd .
.Ed
.Pp
+Call
+.Ic rc_trace
+to indicate that
+.Ar file
+is to be run.
+.Pp
+However, if
+.Ic is_verified Ar file
+fails, just return.
+.Pp
The startup behaviour of
.Ar file
depends upon the following checks:
@@ -885,6 +1029,54 @@
.Ar file
into the current shell.
.El
+.It Ic run_rc_scripts Oo options Oc file ...
+Call
+.Ic run_rc_script
+for each
+.Ar file ,
+unless it is already recorded as having been run.
+.Pp
+The
+.Ar options
+are:
+.Bl -tag -width "--break break"
+.It Ic --arg Ar arg
+Pass
+.Ar arg
+to
+.Ic run_rc_script ,
+default is
+.Ar _boot
+set by
+.Xr rc 8 .
+.It Ic --break Ar break
+Stop processing if any
+.Ar file
+matches any
+.Ar break
+.El
+.It Ic safe_dot Ar file ...
+Used by
+.Ic sdot
+when
+.Xr mac_veriexec 4
+is active and
+.Ar file
+is not verified.
+.Pp
+This function limits the input from
+.Ar file
+to simple variable assignments with any
+non-alphanumeric characters replaced with
+.Ql _ .
+.It Ic sdot Ar file ...
+For reading in configuration files.
+Skip files that do not exist or are empty.
+Try using
+.Ic vdot
+and if that fails (the file is unverified)
+fall back to using
+.Ic safe_dot .
.It Ic startmsg Oo Fl n Oc Ar message
Display a start message to
.Va stdout .
@@ -914,6 +1106,27 @@
process, which is assumed to be
.Xr rc 8 .
Otherwise, the shell exits with a non-zero status.
+.It Ic vdot Ar file ...
+For reading in only verified files.
+.Pp
+Ensure shell
+.Li verify
+option is on.
+This option is only meaningful when
+.Xr mac_veriexec 4
+is active,
+otherwise this function is effectively the same as
+.Ic dot .
+.Pp
+Read in each
+.Ar file
+if it exists and
+.Ic is_verfied Ar file
+is successful, otherwise set return code to 80 (EAUTH).
+.Pp
+Restore previous state of the
+.Li verify
+option.
.It Ic wait_for_pids Op Ar pid ...
Wait until all of the provided
.Ar pids
@@ -943,6 +1156,7 @@
.Pa /etc .
.El
.Sh SEE ALSO
+.Xr debug.sh 8 ,
.Xr rc.conf 5 ,
.Xr rc 8
.Sh HISTORY

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 1:04 AM (21 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16069676
Default Alt Text
D43671.diff (27 KB)

Event Timeline