Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108242756
D43671.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
D43671.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D43671: /etc/rc add trace debug and verify
Attached
Detach File
Event Timeline
Log In to Comment