11#! /bin/bash
2- # Print each command before executing it (for debugging)
32# shellcheck disable=SC2155,SC2223
43
54# check for configuration
@@ -17,6 +16,7 @@ is_zsh(){
1716 p=" $( ps -p $$ -o comm= 2> /dev/null | awk -F/ ' {print $NF}' ) "
1817 case " $p " in
1918 zsh) return 0 ;;
19+ bash) return 1 ;;
2020 esac
2121 fi
2222
@@ -39,17 +39,26 @@ if is_zsh; then
3939 }
4040 # get current function name in zsh (be tolerant if indices differ)
4141 current_funcname (){
42- echo " ${funcstack[1]:- ${funcstack[0]:- } } "
42+ # Ensure standard zsh array indexing (1-based) regardless of user options
43+ emulate -L zsh
44+ # funcstack[1] is current function in zsh (1-indexed by default)
45+ # Handle potential edge cases with fallbacks
46+ printf ' %s' " ${funcstack[2]:- } "
47+ }
48+ # get function definition (zsh)
49+ get_function (){
50+ functions " $1 " 2> /dev/null
4351 }
4452else
4553 # bash
4654 export_func (){
4755 [ -n " $1 " ] || return
48- eval " export -f $1 " 2> /dev/null || true
56+ # shellcheck disable=SC2163
57+ export -f " $1 " 2> /dev/null || true
4958 }
5059 declare_assoc (){
5160 # create named associative array in bash
52- eval " declare -A $1 "
61+ declare -gA " $1 "
5362 }
5463 current_funcname (){
5564 # return the caller function name if available (FUNCNAME[1]), otherwise fall back to FUNCNAME[0]
5968 echo " ${FUNCNAME[0]:- } "
6069 fi
6170 }
71+ # get function definition (bash)
72+ get_function (){
73+ declare -f " $1 " 2> /dev/null
74+ }
6275fi
6376
77+ # portable indirect variable access (works in both bash and zsh)
78+ getvar (){
79+ eval " printf '%s' \"\$ {$1 :-}\" "
80+ }
81+
6482# validation
6583call_host_valid (){
6684 VAR_TO_VALIDATE=" $1 "
67- # retrieve the value of the named variable in a way that works in bash and zsh
68- VARVAL=" $( eval " printf '%s' \"\$ {$VAR_TO_VALIDATE }\" " ) "
69- # check allowed values in a POSIX-compatible way
70- if [ " $VARVAL " != " enable" ] && [ " $VARVAL " != " disable" ]; then
71- echo " Warning: unsupported value $VARVAL for $VAR_TO_VALIDATE ; disabling"
72- eval " export $VAR_TO_VALIDATE =disable"
73- fi
85+ # retrieve the value of the named variable
86+ VARVAL=" $( getvar " $VAR_TO_VALIDATE " ) "
87+ # check allowed values using portable case statement
88+ case " $VARVAL " in
89+ enable|disable)
90+ # valid value, do nothing
91+ ;;
92+ * )
93+ echo " Warning: unsupported value $VARVAL for $VAR_TO_VALIDATE ; disabling"
94+ eval " export $VAR_TO_VALIDATE =disable"
95+ ;;
96+ esac
7497}
7598export_func call_host_valid
7699
@@ -108,7 +131,7 @@ add_path_unique(){
108131 # args: varname value [sep]
109132 varname=" $1 " ; val=" $2 " ; sep=" ${3:-: } "
110133 # retrieve current value portably
111- cur=" $( eval " printf '%s' \"\$ { ${ varname} :-} \" " ) "
134+ cur=" $( getvar " $ varname" ) "
112135 # if empty, set and export
113136 if [ -z " $cur " ]; then
114137 eval " export $varname =\"\$ val\" "
@@ -240,23 +263,13 @@ export_func call_host
240263# from https://stackoverflow.com/questions/1203583/how-do-i-rename-a-bash-function
241264copy_function () {
242265 # portable retrieval of function source and re-definition under a new name
243- if is_zsh; then
244- # zsh: use `functions` to get the definition
245- if functions " $1 " > /dev/null 2>&1 ; then
246- fnsrc=" $( functions " $1 " 2> /dev/null) "
247- else
248- return
249- fi
250- else
251- # bash: use declare -f
252- if declare -f " $1 " > /dev/null 2>&1 ; then
253- fnsrc=" $( declare -f " $1 " ) "
254- else
255- return
256- fi
266+ fnsrc=" $( get_function " $1 " ) "
267+ if [ -z " $fnsrc " ]; then
268+ return
257269 fi
258- # replace the function name in the source and eval it to create new function
259- fnnew=" $( printf ' %s\n' " $fnsrc " | sed " s/^$1 \\ b/$2 /" ) "
270+ # replace only the first occurrence of the function name (at definition)
271+ # Use a more portable sed pattern without \b
272+ fnnew=" $( printf ' %s\n' " $fnsrc " | sed " 1s/^$1 /$2 /; 1s/^$1 ()/$2 ()/" ) "
260273 eval " $fnnew "
261274 export_func " $2 "
262275}
@@ -302,16 +315,24 @@ export_func apptainer
302315
303316# on host: get list of condor executables
304317if [ -z " $APPTAINER_CONTAINER " ]; then
318+ # define command prefixes to search for
319+ HOSTFN_PREFIXES=" condor_ eos"
320+
305321 # portable command list discovery:
306322 if command -v compgen > /dev/null 2>&1 ; then
307- export APPTAINERENV_HOSTFNS=$( compgen -c | grep -E ' ^condor_|^eos' | tr ' \n' ' ' )
323+ # bash: use compgen with grep pattern built from prefixes
324+ GREP_PATTERN=" $( echo " $HOSTFN_PREFIXES " | sed ' s/ /\\|^/g' | sed ' s/^/^/' ) "
325+ export APPTAINERENV_HOSTFNS=$( compgen -c | grep -E " $GREP_PATTERN " | tr ' \n' ' ' )
308326 else
309327 # fallback: scan PATH for matching executables (portable)
310328 APPTAINERENV_HOSTFNS=" $( ( IFS=:
311329 for d in $PATH ; do
312330 [ -d " $d " ] || continue
313- for f in " $d " /condor_* " $d " /eos* ; do
314- [ -x " $f " ] && basename " $f "
331+ for prefix in $HOSTFN_PREFIXES ; do
332+ # shellcheck disable=SC2231
333+ for f in " $d " /${prefix} * ; do
334+ [ -e " $f " ] && [ -x " $f " ] && basename " $f "
335+ done
315336 done
316337 done ) | sort -u | tr ' \n' ' ' ) "
317338 export APPTAINERENV_HOSTFNS
0 commit comments