1# SPDX-License-Identifier: BSD-2-Clause 2 3# RCSid: 4# $Id: safe_eval.sh,v 1.24 2025/05/23 21:34:54 sjg Exp $ 5# 6# @(#) Copyright (c) 2023-2024 Simon J. Gerraty 7# 8# This file is provided in the hope that it will 9# be of use. There is absolutely NO WARRANTY. 10# Permission to copy, redistribute or otherwise 11# use this file is hereby granted provided that 12# the above copyright notice and this notice are 13# left intact. 14# 15# Please send copies of changes and bug-fixes to: 16# sjg@crufty.net 17 18_SAFE_EVAL_SH=: 19 20# does local *actually* work? 21local_works() { 22 local _fu 23} 24 25if local_works > /dev/null 2>&1; then 26 _local=local 27else 28 _local=: 29fi 30 31## 32# safe_set 33# 34# return a safe variable setting 35# any non-alphanumeric chars are replaced with '_' 36# 37safe_set() { 38 ${SED:-sed} 's/[ ]*#.*//;/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. "$,/=:+-];_;g' 39} 40 41## 42# safe_eval [file] 43# 44# eval variable assignments only from file 45# taking care to eliminate any shell meta chars 46# 47safe_eval() { 48 eval `cat "$@" | safe_set` 49} 50 51## 52# safe_eval_export [file] 53# 54# eval variable assignments only from file 55# taking care to eliminate any shell meta chars 56# export any variables thus set 57# 58safe_eval_export() { 59 eval `cat "$@" | safe_set | ${SED:-sed} 's/^\([^=]*\)=.*/&; export \1/'` 60} 61 62## 63# safe_dot file [...] 64# 65# feed all "file" that exist to safe_eval 66# 67safe_dot() { 68 eval $_local ef ex f rc 69 ef= 70 ex= 71 rc=1 72 while : 73 do 74 case "$1" in 75 --export) ex=_export; shift;; 76 *) break;; 77 esac 78 done 79 for f in "$@" 80 do 81 test -s "$f" -a -f "$f" || continue 82 : check for space or tab in "$f" 83 case "$f" in 84 *[[:space:]]*|*" "*|*" "*) # we cannot do this efficiently 85 dotted="$dotted $f" 86 safe_eval$ex "$f" 87 rc=$? 88 continue 89 ;; 90 esac 91 ef="${ef:+$ef }$f" 92 dotted="$dotted $f" 93 done 94 test -z "$ef" && return $rc 95 safe_eval$ex $ef 96 return 0 97} 98 99case /$0 in 100*/safe_eval*) 101 case "$1" in 102 dot|eval|set) op=safe_$1; shift; $op "$@";; 103 *) safe_dot "$@";; 104 esac 105 ;; 106esac 107