aboutsummaryrefslogtreecommitdiff
path: root/libexec/rc/hooks.sh
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/rc/hooks.sh')
-rwxr-xr-xlibexec/rc/hooks.sh274
1 files changed, 274 insertions, 0 deletions
diff --git a/libexec/rc/hooks.sh b/libexec/rc/hooks.sh
new file mode 100755
index 000000000000..af4aff3d6bc5
--- /dev/null
+++ b/libexec/rc/hooks.sh
@@ -0,0 +1,274 @@
+:
+# NAME:
+# hooks.sh - provide hooks for customization
+#
+# SYNOPSIS:
+# hooks_add_all HOOKS [--first] func [...]
+# hooks_add_once HOOKS [--first] func [...]
+# hooks_add_default_set {all,once}
+# hooks_add HOOKS func [...]
+# hooks_get [--lifo] HOOKS
+# hooks_run [--lifo] HOOKS ["args"]
+# hooks_run_all [--lifo] HOOKS ["args"]
+# hooks_has HOOKS func
+#
+# add_hooks HOOKS [--first] func [...]
+# run_hooks HOOKS [LIFO] ["args"]
+# run_hooks_all HOOKS [LIFO] ["args"]
+#
+# DESCRIPTION:
+# The functions add_hooks and run_hooks are retained for
+# backwards compatibility. They are aliases for hooks_add and
+# hooks_run.
+#
+# hooks_add_all simply adds the "func"s to the list "HOOKS".
+#
+# If the first arg is '--first' "func"s are added to the start
+# of the list.
+#
+# hooks_add_once does the same but only if "func" is not in "HOOKS".
+# hooks_add uses one of the above based on "option", '--all' (default)
+# or '--once'.
+#
+# hooks_add_default_set sets the default behavior of hooks_add
+#
+# hooks_get simply returns the named list of functions.
+#
+# hooks_has indicates whether "func" in in "HOOKS".
+#
+# hooks_run runs each "func" in $HOOKS and stops if any of them
+# return a bad status.
+#
+# hooks_run_all does the same but does not stop on error.
+#
+# If run_hooks or run_hooks_all is given a flag of '--lifo' or
+# 2nd argument of LIFO the hooks are run in the reverse order of
+# calls to hooks_add.
+# Any "args" specified are passed to each hook function.
+#
+
+# RCSid:
+# $Id: hooks.sh,v 1.26 2025/08/07 21:59:54 sjg Exp $
+#
+# @(#)Copyright (c) 2000-2024 Simon J. Gerraty
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# avoid multiple inclusion
+_HOOKS_SH=:
+
+# 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
+
+
+##
+# hooks_add_all list func ...
+#
+# add "func"s to "list" regardless
+#
+hooks_add_all() {
+ eval $_local __h
+ __h=$1; shift
+ case "$1" in
+ --first)
+ shift
+ eval "$__h=\"$* \$$__h\""
+ ;;
+ *) eval "$__h=\"\$$__h $*\"";;
+ esac
+}
+
+##
+# hooks_add_once list func ...
+#
+# add "func"s to "list" if not already there
+#
+hooks_add_once() {
+ eval $_local __h __hh __first
+ __h=$1; shift
+ case "$1" in
+ --first) shift; __first=:;;
+ *) __first=;;
+ esac
+ eval "__hh=\$$__h"
+ while [ $# -gt 0 ]
+ do
+ : __hh="$__hh" 1="$1"
+ case "$__first $__hh " in
+ *" $1 "*) ;; # dupe
+ :*) __hh="$1 $__hh";;
+ *) __hh="$__hh $1";;
+ esac
+ shift
+ done
+ eval "$__h=\"$__hh\""
+}
+
+##
+# hooks_add_default_set [--]{all,once}
+#
+# change the default method of hooks_add
+#
+hooks_add_default_set() {
+ case "$1" in
+ once|--once) HOOKS_ADD_DEFAULT=once;;
+ *) HOOKS_ADD_DEFAULT=all;;
+ esac
+}
+
+##
+# hooks_add [--{all,once}] list func ...
+#
+# add "func"s to "list"
+#
+# If '--once' use hooks_add_once,
+# default is hooks_add_all.
+#
+hooks_add() {
+ case "$1" in
+ --all) shift; hooks_add_all "$@";;
+ --once) shift; hooks_add_once "$@";;
+ *) hooks_add_${HOOKS_ADD_DEFAULT:-all} "$@";;
+ esac
+}
+
+##
+# hooks_get [--lifo] list [LIFO]
+#
+# return $list
+#
+hooks_get() {
+ eval $_local __h __h2 e __l
+ case "$1" in
+ --lifo) __l=LIFO; shift;;
+ esac
+ eval "__h=\$$1"
+ case "$__l$2" in
+ LIFO*)
+ __h2="$__h"
+ __h=
+ for e in $__h2
+ do
+ __h="$e $__h"
+ done
+ ;;
+ esac
+ echo "$__h"
+}
+
+##
+# hooks_has list func
+#
+# is func in $list ?
+#
+hooks_has() {
+ eval $_local __h
+ eval "__h=\$$1"
+ case " $__h " in
+ *" $1 "*) return 0;;
+ esac
+ return 1
+}
+
+##
+# hooks_run [--all] [--lifo] list [LIFO] [args]
+#
+# pass "args" to each function in "list"
+# Without '--all'; if any return non-zero return that immediately
+#
+hooks_run() {
+ eval $_local __a e __h __hl __h2 __l
+ __a=return
+ __l=
+
+ while :
+ do
+ case "$1" in
+ --all) __a=:; shift;;
+ --lifo) __l=$1; shift;;
+ *) break;;
+ esac
+ done
+ __hl=$1; shift
+ case "$1" in
+ LIFO) __l=--lifo; shift;;
+ esac
+ __h=`hooks_get $__l $__hl`
+ for e in $__h
+ do
+ $e "$@" || $__a $?
+ done
+}
+
+##
+# hooks_run_all [--lifo] list [LIFO] [args]
+#
+# pass "args" to each function in "list"
+#
+hooks_run_all() {
+ hooks_run --all "$@"
+}
+
+##
+# add_hooks,run_hooks[_all] aliases
+#
+add_hooks() {
+ hooks_add "$@"
+}
+
+run_hooks() {
+ hooks_run "$@"
+}
+
+run_hooks_all() {
+ hooks_run --all "$@"
+}
+
+
+case /$0 in
+*/hooks.sh)
+ # simple unit-test
+ list=HOOKS
+ flags=
+ while :
+ do
+ : 1=$1
+ case "$1" in
+ HOOKS|*hooks) list=$1; shift;;
+ --*) flags="$flags $1"; shift;;
+ *) break;;
+ esac
+ done
+ for f in "$@"
+ do
+ : f=$f
+ case "$f" in
+ LIFO) ;;
+ false|true) ;;
+ *) eval "$f() { echo This is $f; }";;
+ esac
+ done
+ echo hooks_add $flags $list "$@"
+ hooks_add $flags $list "$@"
+ echo hooks_run $list
+ hooks_run $list
+ echo hooks_run --all --lifo $list
+ hooks_run --all --lifo $list
+ echo hooks_run $list LIFO
+ hooks_run $list LIFO
+ ;;
+esac