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