aboutsummaryrefslogtreecommitdiff
path: root/libexec/rc/debug.sh
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/rc/debug.sh')
-rwxr-xr-xlibexec/rc/debug.sh205
1 files changed, 189 insertions, 16 deletions
diff --git a/libexec/rc/debug.sh b/libexec/rc/debug.sh
index 7bbb500e2d22..739c81a709f6 100755
--- a/libexec/rc/debug.sh
+++ b/libexec/rc/debug.sh
@@ -1,6 +1,4 @@
:
-# SPDX-License-Identifier: BSD-2-Clause
-
# NAME:
# debug.sh - selectively debug scripts
#
@@ -9,6 +7,7 @@
# DebugOn [-eo] "tag" ...
# DebugOff [-eo] [rc="rc"] "tag" ...
# Debugging
+# DebugAdd "tag"
# DebugEcho ...
# DebugLog ...
# DebugShell "tag" ...
@@ -30,6 +29,11 @@
# If the '-o' flag is given, tracing is turned off unless there
# was a matched "tag", useful for functions too noisy to tace.
#
+# Further; when we set "DEBUG_ON" if we find
+# "$DEBUG_ON:debug_add:tag" in "DEBUG_SH" we will
+# add the new "tag" to "DEBUG_SH" so it only has effect after that
+# point.
+#
# 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.
@@ -39,6 +43,9 @@
# default of 0. Thus if DebugOff is the last operation in a
# function, "rc" will be the return code of that function.
#
+# DebugAdd allows adding a "tag" to "DEBUG_SH" to influence
+# later events, possibly in a child process.
+#
# DebugEcho is just shorthand for:
#.nf
# $DEBUG_DO echo "$@"
@@ -74,16 +81,11 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: debug.sh,v 1.35 2024/02/03 19:04:47 sjg Exp $
+# $Id: debug.sh,v 1.47 2025/08/07 21:59:54 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.
+# SPDX-License-Identifier: BSD-2-Clause
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
@@ -98,38 +100,193 @@ DEBUG_DO=:
DEBUG_SKIP=
export DEBUGGING DEBUG_DO DEBUG_SKIP
+# have is handy
+if test -z "$_HAVE_SH"; then
+ _HAVE_SH=:
+
+ ##
+ # have that does not rely on return code of type
+ #
+ have() {
+ case `(type "$1") 2>&1` in
+ *" found") return 1;;
+ esac
+ return 0
+ }
+fi
+
+# does local *actually* work?
+local_works() {
+ local _fu
+}
+
+if local_works > /dev/null 2>&1; then
+ _local=local
+else
+ _local=:
+fi
+# for backwards compatability
+local=$_local
+
+if test -z "$isPOSIX_SHELL"; then
+ if (echo ${PATH%:*}) > /dev/null 2>&1; then
+ # true should be a builtin, : certainly is
+ isPOSIX_SHELL=:
+ else
+ isPOSIX_SHELL=false
+ false() {
+ return 1
+ }
+ fi
+fi
+
+is_posix_shell() {
+ $isPOSIX_SHELL
+ return
+}
+
+
+##
+# _debugAdd match
+#
+# Called from _debugOn when $match also appears in $DEBUG_SH with
+# a suffix of :debug_add:tag we will add tag to DEBUG_SH
+#
+_debugAdd() {
+ eval $_local tag
+
+ for tag in `IFS=,; echo $DEBUG_SH`
+ do
+ : tag=$tag
+ case "$tag" in
+ $1:debug_add:*)
+ if is_posix_shell; then
+ tag=${tag#$1:debug_add:}
+ else
+ tag=`expr $tag : '.*:debug_add:\(.*\)'`
+ fi
+ case ",$DEBUG_SH," in
+ *,$tag,*) ;;
+ *) set -x
+ : _debugAdd $1
+ DEBUG_SH=$DEBUG_SH,$tag
+ set +x
+ ;;
+ esac
+ ;;
+ esac
+ done
+ export DEBUG_SH
+}
+
+
+##
+# _debugOn match first
+#
+# Actually turn on tracing, set $DEBUG_ON=$match
+#
+# Check if $DEBUG_SH contains $match:debug_add:* and call _debugAdd
+# to add the suffix to DEBUG_SH. This useful when we only want
+# to trace some script when run under specific circumstances.
+#
+# If we have included hooks.sh $_HOOKS_SH will be set
+# and if $first (the first arg to DebugOn) is suitable as a variable
+# name we will run ${first}_debugOn_hooks.
+#
+# We disable tracing for hooks_run itself but functions can trace
+# if they want based on DEBUG_DO
+#
_debugOn() {
DEBUG_OFF=
DEBUG_DO=
DEBUG_SKIP=:
DEBUG_X=-x
+ # do this firt to reduce noise
+ case ",$DEBUG_SH," in
+ *,$1:debug_add:*) _debugAdd $1;;
+ *,$2:debug_add:*) _debugAdd $2;;
+ esac
set -x
DEBUG_ON=$1
+ case "$_HOOKS_SH,$2" in
+ ,*|:,|:,*[${CASE_CLASS_NEG:-!}A-Za-z0-9_]*) ;;
+ *) # avoid noise from hooks_run
+ set +x
+ hooks_run ${2}_debugOn_hooks
+ set -x
+ ;;
+ esac
}
+##
+# _debugOff match $DEBUG_ON $first
+#
+# Actually turn off tracing, set $DEBUG_OFF=$match
+#
+# If we have included hooks.sh $_HOOKS_SH will be set
+# and if $first (the first arg to DebugOff) is suitable as a variable
+# name we will run ${first}_debugOff_hooks.
+#
+# We do hooks_run after turning off tracing, but before resetting
+# DEBUG_DO so functions can trace if they want
+#
_debugOff() {
DEBUG_OFF=$1
set +x
+ case "$_HOOKS_SH,$3" in
+ ,*|:,|:,*[${CASE_CLASS_NEG:-!}A-Za-z0-9_]*) ;;
+ *) hooks_run ${3}_debugOff_hooks;;
+ esac
+ set +x # just to be sure
DEBUG_ON=$2
DEBUG_DO=:
DEBUG_SKIP=
DEBUG_X=
}
+##
+# DebugAdd tag
+#
+# Add tag to DEBUG_SH
+#
+DebugAdd() {
+ DEBUG_SH=${DEBUG_SH:+$DEBUG_SH,}$1
+ export DEBUG_SH
+}
+
+##
+# DebugEcho message
+#
+# Output message if we are debugging
+#
DebugEcho() {
$DEBUG_DO echo "$@"
}
+##
+# Debugging
+#
+# return 0 if we are debugging.
+#
Debugging() {
test "$DEBUG_SKIP"
}
+##
+# DebugLog message
+#
+# Outout message with timestamp if we are debugging
+#
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 message
+#
+# Something hard to miss when wading through huge -x output
+#
DebugTrace() {
$DEBUG_SKIP return 0
set +x
@@ -139,8 +296,13 @@ DebugTrace() {
set -x
}
-# Turn on debugging if appropriate
+##
+# DebugOn [-e] [-o] match ...
+#
+# Turn on debugging if any $match is found in $DEBUG_SH.
+#
DebugOn() {
+ eval ${local:-:} _e _match _off _rc
_rc=0 # avoid problems with set -e
_off=:
while :
@@ -170,14 +332,14 @@ DebugOn() {
*,!$_e,*|*,!$Myname:$_e,*)
# only turn it off if it was on
_rc=0
- $DEBUG_DO _debugOff $_e $DEBUG_ON
+ $DEBUG_DO _debugOff $_e $DEBUG_ON $1
break
;;
*,$_e,*|*,$Myname:$_e,*)
# only turn it on if it was off
_rc=0
_match=$_e
- $DEBUG_SKIP _debugOn $_e
+ $DEBUG_SKIP _debugOn $_e $1
break
;;
esac
@@ -185,7 +347,7 @@ DebugOn() {
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
+ $DEBUG_DO _debugOff $_e $DEBUG_ON $1
fi
DEBUGGING=$DEBUG_SKIP # backwards compatability
$DEBUG_DO set -x # back on if needed
@@ -193,11 +355,20 @@ DebugOn() {
return $_rc
}
+##
+# DebugOff [-e] [-o] [rc=$?] match ...
+#
# 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.
+#
+# The options '-e' and '-o' are ignored, they just make it easier to
+# keep DebugOn and DebugOff lines in sync.
+#
DebugOff() {
+ eval ${local:-:} _e _rc
case ",${DEBUG_SH:-$DEBUG}," in
*,[Dd]ebug,*) ;;
*) $DEBUG_DO set +x;; # reduce the noise
@@ -216,7 +387,7 @@ DebugOff() {
: $_e==$DEBUG_OFF DEBUG_OFF
case "$DEBUG_OFF" in
"") break;;
- $_e) _debugOn $DEBUG_ON; return $_rc;;
+ $_e) _debugOn $DEBUG_ON $1; return $_rc;;
esac
done
for _e in $*
@@ -224,7 +395,7 @@ DebugOff() {
: $_e==$DEBUG_ON DEBUG_ON
case "$DEBUG_ON" in
"") break;;
- $_e) _debugOff; return $_rc;;
+ $_e) _debugOff "" "" $1; return $_rc;;
esac
done
DEBUGGING=$DEBUG_SKIP # backwards compatability
@@ -237,6 +408,7 @@ _TTY=${_TTY:-`test -t 0 && tty`}; export _TTY
# override this if you like
_debugShell() {
+ test "x$_TTY" != x || return 0
{
echo DebugShell "$@"
echo "Type 'exit' to continue..."
@@ -247,6 +419,7 @@ _debugShell() {
# Run an interactive shell if appropriate
# Note: you can use $DEBUG_SKIP DebugShell ... to skip unless debugOn
DebugShell() {
+ eval ${local:-:} _e
case "$_TTY%${DEBUG_INTERACTIVE}" in
*%|%*) return 0;; # no tty or no spec
esac