:1# NAME:2# hooks.sh - provide hooks for customization3#4# SYNOPSIS:5# hooks_add_all HOOKS [--first] func [...]6# hooks_add_once HOOKS [--first] func [...]7# hooks_add_default_set {all,once}8# hooks_add HOOKS func [...]9# hooks_get [--lifo] HOOKS10# hooks_run [--lifo] HOOKS ["args"]11# hooks_run_all [--lifo] HOOKS ["args"]12# hooks_has HOOKS func13#14# add_hooks HOOKS [--first] func [...]15# run_hooks HOOKS [LIFO] ["args"]16# run_hooks_all HOOKS [LIFO] ["args"]17#18# DESCRIPTION:19# The functions add_hooks and run_hooks are retained for20# backwards compatibility. They are aliases for hooks_add and21# hooks_run.22#23# hooks_add_all simply adds the "func"s to the list "HOOKS".24#25# If the first arg is '--first' "func"s are added to the start26# of the list.27#28# hooks_add_once does the same but only if "func" is not in "HOOKS".29# hooks_add uses one of the above based on "option", '--all' (default)30# or '--once'.31#32# hooks_add_default_set sets the default behavior of hooks_add33#34# hooks_get simply returns the named list of functions.35#36# hooks_has indicates whether "func" in in "HOOKS".37#38# hooks_run runs each "func" in $HOOKS and stops if any of them39# return a bad status.40#41# hooks_run_all does the same but does not stop on error.42#43# If run_hooks or run_hooks_all is given a flag of '--lifo' or44# 2nd argument of LIFO the hooks are run in the reverse order of45# calls to hooks_add.46# Any "args" specified are passed to each hook function.47#4849# RCSid:50# $Id: hooks.sh,v 1.26 2025/08/07 21:59:54 sjg Exp $51#52# @(#)Copyright (c) 2000-2024 Simon J. Gerraty53#54# SPDX-License-Identifier: BSD-2-Clause55#56# Please send copies of changes and bug-fixes to:57# [email protected]58#5960# avoid multiple inclusion61_HOOKS_SH=:6263# does local *actually* work?64local_works() {65local _fu66}6768if local_works > /dev/null 2>&1; then69_local=local70else71_local=:72fi73# for backwards compatability74local=$_local757677##78# hooks_add_all list func ...79#80# add "func"s to "list" regardless81#82hooks_add_all() {83eval $_local __h84__h=$1; shift85case "$1" in86--first)87shift88eval "$__h=\"$* \$$__h\""89;;90*) eval "$__h=\"\$$__h $*\"";;91esac92}9394##95# hooks_add_once list func ...96#97# add "func"s to "list" if not already there98#99hooks_add_once() {100eval $_local __h __hh __first101__h=$1; shift102case "$1" in103--first) shift; __first=:;;104*) __first=;;105esac106eval "__hh=\$$__h"107while [ $# -gt 0 ]108do109: __hh="$__hh" 1="$1"110case "$__first $__hh " in111*" $1 "*) ;; # dupe112:*) __hh="$1 $__hh";;113*) __hh="$__hh $1";;114esac115shift116done117eval "$__h=\"$__hh\""118}119120##121# hooks_add_default_set [--]{all,once}122#123# change the default method of hooks_add124#125hooks_add_default_set() {126case "$1" in127once|--once) HOOKS_ADD_DEFAULT=once;;128*) HOOKS_ADD_DEFAULT=all;;129esac130}131132##133# hooks_add [--{all,once}] list func ...134#135# add "func"s to "list"136#137# If '--once' use hooks_add_once,138# default is hooks_add_all.139#140hooks_add() {141case "$1" in142--all) shift; hooks_add_all "$@";;143--once) shift; hooks_add_once "$@";;144*) hooks_add_${HOOKS_ADD_DEFAULT:-all} "$@";;145esac146}147148##149# hooks_get [--lifo] list [LIFO]150#151# return $list152#153hooks_get() {154eval $_local __h __h2 e __l155case "$1" in156--lifo) __l=LIFO; shift;;157esac158eval "__h=\$$1"159case "$__l$2" in160LIFO*)161__h2="$__h"162__h=163for e in $__h2164do165__h="$e $__h"166done167;;168esac169echo "$__h"170}171172##173# hooks_has list func174#175# is func in $list ?176#177hooks_has() {178eval $_local __h179eval "__h=\$$1"180case " $__h " in181*" $1 "*) return 0;;182esac183return 1184}185186##187# hooks_run [--all] [--lifo] list [LIFO] [args]188#189# pass "args" to each function in "list"190# Without '--all'; if any return non-zero return that immediately191#192hooks_run() {193eval $_local __a e __h __hl __h2 __l194__a=return195__l=196197while :198do199case "$1" in200--all) __a=:; shift;;201--lifo) __l=$1; shift;;202*) break;;203esac204done205__hl=$1; shift206case "$1" in207LIFO) __l=--lifo; shift;;208esac209__h=`hooks_get $__l $__hl`210for e in $__h211do212$e "$@" || $__a $?213done214}215216##217# hooks_run_all [--lifo] list [LIFO] [args]218#219# pass "args" to each function in "list"220#221hooks_run_all() {222hooks_run --all "$@"223}224225##226# add_hooks,run_hooks[_all] aliases227#228add_hooks() {229hooks_add "$@"230}231232run_hooks() {233hooks_run "$@"234}235236run_hooks_all() {237hooks_run --all "$@"238}239240241case /$0 in242*/hooks.sh)243# simple unit-test244list=HOOKS245flags=246while :247do248: 1=$1249case "$1" in250HOOKS|*hooks) list=$1; shift;;251--*) flags="$flags $1"; shift;;252*) break;;253esac254done255for f in "$@"256do257: f=$f258case "$f" in259LIFO) ;;260false|true) ;;261*) eval "$f() { echo This is $f; }";;262esac263done264echo hooks_add $flags $list "$@"265hooks_add $flags $list "$@"266echo hooks_run $list267hooks_run $list268echo hooks_run --all --lifo $list269hooks_run --all --lifo $list270echo hooks_run $list LIFO271hooks_run $list LIFO272;;273esac274275276