xref: /freebsd/libexec/rc/safe_eval.sh (revision b0ada425efb3fb1b744d66bd1d0c1bbd5a7f25e6)
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