xref: /freebsd/libexec/rc/safe_eval.sh (revision 7a7741af18d6c8a804cc643cb7ecda9d730c6aa6)
1# SPDX-License-Identifier: BSD-2-Clause
2
3# RCSid:
4#	$Id: safe_eval.sh,v 1.20 2024/08/16 00:57:58 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##
21# safe_set
22#
23# return a safe variable setting
24# any non-alphanumeric chars are replaced with '_'
25#
26safe_set() {
27    ${SED:-sed} 's/[ 	]*#.*//;/^[A-Za-z_][A-Za-z0-9_]*=/!d;s;[^A-Za-z0-9_. 	"$,/=-];_;g'
28}
29
30##
31# safe_eval [file]
32#
33# eval variable assignments only from file
34# taking care to eliminate any shell meta chars
35#
36safe_eval() {
37    eval `cat "$@" | safe_set`
38}
39
40##
41# safe_eval_export [file]
42#
43# eval variable assignments only from file
44# taking care to eliminate any shell meta chars
45# export any variables thus set
46#
47safe_eval_export() {
48    eval `cat "$@" | safe_set | ${SED:-sed} 's/^\([^=]*\)=.*/&; export \1/'`
49}
50
51##
52# safe_dot file [...]
53#
54# feed all "file" that exist to safe_eval
55#
56safe_dot() {
57    eval ${local:-:} ef ex f rc
58    ef=
59    ex=
60    rc=1
61    while :
62    do
63        case "$1" in
64        --export) ex=_export; shift;;
65        *) break;;
66        esac
67    done
68    for f in "$@"
69    do
70        test -s "$f" -a -f "$f" || continue
71        : check for space or tab in "$f"
72        case "$f" in
73        *[[:space:]]*|*" "*|*"	"*) # we cannot do this efficiently
74            dotted="$dotted $f"
75            safe_eval$ex "$f"
76            rc=$?
77            continue
78            ;;
79        esac
80        ef="${ef:+$ef }$f"
81        dotted="$dotted $f"
82    done
83    test -z "$ef" && return $rc
84    safe_eval$ex $ef
85    return 0
86}
87
88case /$0 in
89*/safe_eval*)
90    case "$1" in
91    dot|eval|set) op=safe_$1; shift; $op "$@";;
92    *) safe_dot "$@";;
93    esac
94    ;;
95esac
96