xref: /freebsd/libexec/rc/safe_eval.sh (revision a3cefe7f2b4df0f70ff92d4570ce18e517af43ec)
1:
2# RCSid:
3#	$Id: safe_eval.sh,v 1.26 2026/04/10 16:03:39 sjg Exp $
4#
5#	@(#) Copyright (c) 2023-2026 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 [xtras]
27#
28# return a safe variable setting
29# any non-alphanumeric chars other than those in "xtras"
30# will be replaced with '_'
31#
32# "xtras" should be used with caution and cannot include ';'
33#
34safe_set() {
35    ${SED:-sed} 's/[ 	]*#.*//;/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. 	"'"$1"'$,/=:+-];_;g'
36}
37
38##
39# safe_eval [file]
40#
41# eval variable assignments only from file
42# taking care to eliminate any shell meta chars
43#
44safe_eval() {
45    eval `cat "$@" | safe_set`
46}
47
48##
49# safe_eval_export [file]
50#
51# eval variable assignments only from file
52# taking care to eliminate any shell meta chars
53# export any variables thus set
54#
55safe_eval_export() {
56    eval `cat "$@" | safe_set | ${SED:-sed} 's/^\([^=]*\)=.*/&; export \1/'`
57}
58
59##
60# safe_dot file [...]
61#
62# feed all "file" that exist to safe_eval
63#
64safe_dot() {
65    eval $_local ef ex f rc
66    ef=
67    ex=
68    rc=1
69    while :
70    do
71        case "$1" in
72        --export) ex=_export; shift;;
73        *) break;;
74        esac
75    done
76    for f in "$@"
77    do
78        test -s "$f" -a -f "$f" || continue
79        : check for space or tab in "$f"
80        case "$f" in
81        *[[:space:]]*|*" "*|*"	"*) # we cannot do this efficiently
82            dotted="$dotted $f"
83            safe_eval$ex "$f"
84            rc=$?
85            continue
86            ;;
87        esac
88        ef="${ef:+$ef }$f"
89        dotted="$dotted $f"
90    done
91    test -z "$ef" && return $rc
92    safe_eval$ex $ef
93    return 0
94}
95
96case /$0 in
97*/safe_eval*)
98    case "$1" in
99    dot|eval|set) op=safe_$1; shift; $op "$@";;
100    *) safe_dot "$@";;
101    esac
102    ;;
103esac
104