diff options
author | root <root@vps-18a7a2b7.vps.ovh.ca> | 2024-02-22 09:21:47 -0500 |
---|---|---|
committer | root <root@vps-18a7a2b7.vps.ovh.ca> | 2024-02-22 09:21:47 -0500 |
commit | 2705aa066b152c2583887dc558dd9822506d7362 (patch) | |
tree | 54a6bac4fbee3e82be6ba3248669f337ac51f7ff | |
parent | 2ab6533b04c4918e2d6c057bf78d5e2f85c7958a (diff) |
bash introspection experiments
-rw-r--r-- | bash/SOURCES.bash | 113 | ||||
l--------- | bash/bootstrap_SOURCES.bash | 1 | ||||
-rw-r--r-- | bash/denominate-function.bash | 82 |
3 files changed, 196 insertions, 0 deletions
diff --git a/bash/SOURCES.bash b/bash/SOURCES.bash new file mode 100644 index 0000000..a274223 --- /dev/null +++ b/bash/SOURCES.bash | |||
@@ -0,0 +1,113 @@ | |||
1 | #!/bin/bash | ||
2 | source() | ||
3 | { | ||
4 | if [[ $1 != */* ]] && | ||
5 | ( | ||
6 | command -v base64_embedded_source__"$1" || | ||
7 | command -v src/"$1" | ||
8 | ) >&2 # >/dev/null | ||
9 | then | ||
10 | rewrite_self \ | ||
11 | "$1" \ | ||
12 | src/"$1" \ | ||
13 | base64_embedded_source__"$1" \ | ||
14 | "${@:2}" | ||
15 | else | ||
16 | builtin source "$@" | ||
17 | fi | ||
18 | } | ||
19 | |||
20 | rewrite_self() | ||
21 | { | ||
22 | # TODO: Check if version in src/ updates this version | ||
23 | # by checking for its hash in a record kept in the source | ||
24 | # file in src/ | ||
25 | if command -v "$3" >/dev/null | ||
26 | then | ||
27 | ( | ||
28 | set +e | ||
29 | sha256sum <("$3") >&2 | ||
30 | sha256sum <(builtin source "$2" "${@:4}" && "$3") >&2 | ||
31 | ) | ||
32 | builtin source \ | ||
33 | <("$3") \ | ||
34 | "${@:4}" | ||
35 | return | ||
36 | fi | ||
37 | [ -f "$2" -a -r "$2" ] || return | ||
38 | declare -n tmpfile=tmpfile${RANDOM} | ||
39 | tmpfile=$(mktemp) || return | ||
40 | if embed "$1" "$2" > "$tmpfile" && | ||
41 | builtin source "$tmpfile" && | ||
42 | command -v "$3" >/dev/null && | ||
43 | builtin source <("$3") "${@:4}" && | ||
44 | [ -w "$0" ] && | ||
45 | sed \ | ||
46 | -i~"$(date -Ins)" \ | ||
47 | -e "1 { r ${tmpfile}"$'\n'" }" \ | ||
48 | "$0" | ||
49 | then | ||
50 | local r=0 | ||
51 | else | ||
52 | local r=$? | ||
53 | fi | ||
54 | rm "$tmpfile" | ||
55 | return $r | ||
56 | } | ||
57 | |||
58 | embed() | ||
59 | { | ||
60 | cat <<. | ||
61 | base64_embedded_source__${1}() | ||
62 | { | ||
63 | base64 -d <<. | ||
64 | $(base64 < "$2" && echo .) | ||
65 | } | ||
66 | . | ||
67 | } | ||
68 | |||
69 | print_test_script_for_SOURCES.bash() | ||
70 | { | ||
71 | cat <<. | ||
72 | #!/bin/bash | ||
73 | source SOURCES.bash | ||
74 | source SOURCES.bash | ||
75 | source rpc.bash | ||
76 | : base64_embedded_source__rpc.bash | ||
77 | : base64_embedded_source__dependencies.bash | ||
78 | BASH_RPC_REMOTE_DEST=localhost \\ | ||
79 | remote_run_function \\ | ||
80 | source rpc.bash | ||
81 | . | ||
82 | } | ||
83 | |||
84 | setup_test_dir() | ||
85 | { | ||
86 | ( | ||
87 | set -e | ||
88 | mkdir -p test_SOURCES.bash | ||
89 | cd test_SOURCES.bash | ||
90 | mkdir -p src | ||
91 | ln -sf -t src \ | ||
92 | ../../SOURCES.bash \ | ||
93 | ../../src/{rpc,dependencies}.bash | ||
94 | print_test_script_for_SOURCES.bash > test-SOURCES.bash | ||
95 | ) | ||
96 | } | ||
97 | |||
98 | run_test() | ||
99 | { | ||
100 | ( | ||
101 | set -ex | ||
102 | cd test_SOURCES.bash | ||
103 | PATH=$PWD/src:$PATH bash test-SOURCES.bash || true | ||
104 | PATH=$PWD/src:$PATH bash test-SOURCES.bash | ||
105 | ) | ||
106 | } | ||
107 | |||
108 | bootstrap_SOURCES.bash() | ||
109 | { | ||
110 | setup_test_dir && run_test | ||
111 | } | ||
112 | |||
113 | [ "$0" = 'bootstrap_SOURCES.bash' ] && bootstrap_SOURCES.bash | ||
diff --git a/bash/bootstrap_SOURCES.bash b/bash/bootstrap_SOURCES.bash new file mode 120000 index 0000000..a0054dd --- /dev/null +++ b/bash/bootstrap_SOURCES.bash | |||
@@ -0,0 +1 @@ | |||
SOURCES.bash \ No newline at end of file | |||
diff --git a/bash/denominate-function.bash b/bash/denominate-function.bash new file mode 100644 index 0000000..9e5cb31 --- /dev/null +++ b/bash/denominate-function.bash | |||
@@ -0,0 +1,82 @@ | |||
1 | #!/bin/bash | ||
2 | denominate_function() | ||
3 | { | ||
4 | declare -n func_name="$1" | ||
5 | local func_output_b64encoded output_hash | ||
6 | read -r -d '' \ | ||
7 | func_output_b64encoded \ | ||
8 | < <(base64) || [ "${func_output_b64encoded}" ] | ||
9 | read output_hash _ \ | ||
10 | < <(base64 -d <<< "$func_output_b64encoded" | sha256sum) | ||
11 | [ ${#output_hash} = 64 ] || return | ||
12 | func_name=SHA256_${output_hash:0:32} | ||
13 | source <(cat <<END | ||
14 | ${func_name} () | ||
15 | { | ||
16 | base64 -d <<. | ||
17 | ${func_output_b64encoded} | ||
18 | . | ||
19 | } | ||
20 | END | ||
21 | ) | ||
22 | } | ||
23 | |||
24 | reverse_hash() | ||
25 | { | ||
26 | case "$#.$1" in | ||
27 | 2.SHA256 ) | ||
28 | ;; | ||
29 | 1.SHA256_???????????????????????????????? ) | ||
30 | set -- SHA256 "${1#SHA256_}" | ||
31 | ;; | ||
32 | * ) | ||
33 | return 1 | ||
34 | ;; | ||
35 | esac | ||
36 | case ${#2} in | ||
37 | 32 | 64 ) | ||
38 | set -- "${1}_${2: 0 : 32}" | ||
39 | ;; | ||
40 | * ) | ||
41 | return 1 | ||
42 | ;; | ||
43 | esac | ||
44 | ( | ||
45 | set -o pipefail | ||
46 | set -e | ||
47 | declare -f "$1" | | ||
48 | sed -n -e '/^[ ]*base64 -d <<[.]$/,/^[.]$/ { p }' | | ||
49 | sed -e '1 d ; $ d' | | ||
50 | base64 -d | ||
51 | ) | ||
52 | } | ||
53 | |||
54 | example_input() | ||
55 | { | ||
56 | sed -n -e '/^reverse_hash *()/ , /^}$/ p' <"$0" | ||
57 | } | ||
58 | |||
59 | set -e | ||
60 | set -o pipefail | ||
61 | |||
62 | if [ -t 0 ] | ||
63 | then | ||
64 | if [ $# = 0 ] | ||
65 | then | ||
66 | denominate_function f < <(example_input) | ||
67 | else | ||
68 | denominate_function f <<< "$*" | ||
69 | fi | ||
70 | else | ||
71 | denominate_function f | ||
72 | fi | ||
73 | |||
74 | read -r -d '' < <( reverse_hash "$f" | base64) || [ "$REPLY" ] | ||
75 | if read s _ < <( base64 -d <<< "$REPLY" | sha256sum ) && | ||
76 | [ ${#s} -eq 64 -a "${s: 0 : 32}" = "${f: -32 : 32}" ] | ||
77 | then | ||
78 | declare -f "$f" | grep . && | ||
79 | printf '%s\n' "$f" | ||
80 | else | ||
81 | false | ||
82 | fi | ||