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,266 @@ +: +# NAME: +# debug.sh - debug scripts +# +# SYNOPSIS: +# $_DEBUG_SH . debug.sh +# DebugOn [-e][-o] "e" ... +# DebugOff "e" ... +# DebugShell "e" ... +# DebugEcho ... +# Debugging +# DebugLog ... +# DebugTrace ... +# Debug "e" ... +# +# $DEBUG_SKIP echo skipped when Debug "e" is true. +# $DEBUG_DO echo only done when Debug "e" is true. +# +# DESCRIPTION: +# DebugOn turns tracing on if any "e" is found in "DEBUG_SH". +# It turns tracing off if "!e" is found in "DEBUG_SH". +# It also sets "DEBUG_ON" to the "e" that caused tracing to be +# enabled, or "DEBUG_OFF" if we matched "!e". +# If '-e' option given returns 1 if no "e" matched. +# If the '-o' flag is given, tracing is turned off unless there +# was a matched "e", useful for functions too noisy to tace. +# +# DebugOff turns tracing on if any "e" matches "DEBUG_OFF" or +# off if any "e" matches "DEBUG_ON". This allows nested +# functions to not interfere with each other. +# +# 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 "e" 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 and is only set by Debug. +# +# 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 + +# RCSid: +# $Id: debug.sh,v 1.33 2021/12/03 18:22:37 sjg Exp $ +# +# @(#) Copyright (c) 1994-2021 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 + $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 + $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,15 @@ required_vars eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd + rc_trace 0 "$_file $_arg" + case "$_file" in + *local*.d/*) # allow it ? + ;; + *) # don't use it if we don't trust it + is_verified $_file || return + ;; + esac + rc_service="$_file" case "$_file" in /etc/rc.d/*.sh) # no longer allowed in the base @@ -1459,6 +1587,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 +1599,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 +1686,35 @@ # 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=dot + + case "$1" in + -s) + _dot=sdot + _name=$2 + shift + ;; + -v) + _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 +1726,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 +2486,22 @@ if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then rc_boottrace=YES fi + +# allow for local additions and overrides for rc.subr +# we use vdot to ensure the file has not been tampered with +vdot /etc/rc.subr.local + +# safe_dot - for unverified files +$_SAFE_EVAL_SH vdot /libexec/safe_eval.sh +$_DEBUG_SH vdot /libexec/debug.sh + +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,64 @@ +# 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,175 @@ +.\" Copyright (c) 1994-2021 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 +.\" +.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 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 +.Ic DebugOn . +.Pp +The optional +.Ar rc +value will be returned rather than the default of 0. +.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 +.Ic DebugLog , +finally the banner is repeated. +.It Ic Debug +For backwards compatibility, calls +.Ic DebugOn +and if that does not turn tracing on, +it calls +.Ic 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 +.Ic 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