blob: 343882177b169324d0f350d754b817770da0830c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/bin/bash
#
# Synopsis:
#
# #!/bin/bash
# . export-json.bash
# export_JSON <variables>
#
# Example:
#
# $ (
# source export-json.bash
# export_JSON SSH_TTY \
# SSH_CONNECTION \
# SSH_CLIENT \
# SSH_AUTH_SOCK
# )
#
# {
# "SSH_TTY": "/dev/pts/0",
# "SSH_CONNECTION": "192.0.2.140 41564 198.51.100.25 22",
# "SSH_CLIENT": "192.0.2.140 41564 22",
# "SSH_AUTH_SOCK": "/tmp/ssh-XXXXcePKJl/agent.36326"
# }
#
# This bash function exports shell variables as
# JSON ("javascript object notation") strings.
#
# The string is printed to stdout.
#
# JSON is a format that represents data as
# Javascript source code so modern programmers
# can read it unlike bash source code.
#
# Variable names are given to the function as its
# argument list:
#
# $ (source export-json.bash; export_JSON PATH)
#
# The output is a single JSON object containing
# key-value mappings between JSON strings:
#
# {
# "PATH": "/usr/local/sbin:[...]"
# }
#
# It uses the external tool "jq" to parse string
# values placed in jq's argument list by bash and
# then encode them as JSON string values. This
# is no accidental dependency. The jq program is
# the foundation of the trustworthiness of this
# code. If we were encoding JSON strings in bash
# we would have to be a lot more careful.
arg1_to_env0()
{
case "$1" in
*[^a-zA-Z0-9_=]* | *=*=* )
echo "Error: invalid variable: '$1'" >&2
return 10
;;
[a-zA-Z_]* )
set -- "${1#*=}" "${1%%=*}"
;;
* )
echo "Error: invalid variable: '$1'" >&2
return 20
;;
esac
if [ -v "$2" ]
then
printf '%s=%s\0' "$1" "${!2}"
else
echo "Warning: ignoring unset variable: '$2'" >&2
fi
}
vars_to_env0()
{
while [ $# -gt 0 ]
do
arg1_to_env0 "$1" || return
shift
done
}
env0_to_JSON()
{
set --
while read -d ''
do
set -- "$@" --arg "${REPLY%%=*}" "${REPLY#*=}"
done
jq -n -r '$ARGS.named' "$@"
}
export_JSON_unsafe()
{
(
set -o pipefail
vars_to_env0 "$@" | env0_to_JSON
)
}
safe_stdout()
{
set -- "$(mktemp)" "$@"
if (shift; "$@") > "$1"
then
set -- "$1" 0
cat < "$1"
else
set -- "$1" $?
fi
rm "$1"
return $2
}
export_JSON()
{
safe_stdout export_JSON_unsafe "$@"
}
try()
{
"$@"
printf '(Exit %s) <- [%s]\n' "$?" "${*@Q}" >&2
}
runtest()
{
set -- SSH_CLIENT SSH_TTY SSH_AUTH_SOCK SSH_CONNECTION
try export_JSON "$@"
unset unsetvar
try export_JSON SSH_TTY unsetvar
try export_JSON unsetvar SSH_TTY
try export_JSON
try export_JSON ''
try export_JSON '' SSH_TTY
}
|