summaryrefslogtreecommitdiff
path: root/wordpress/export-json.bash
blob: 033dcb3d5a79aa0a22f2cd87972f139c71bf38ee (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
#!/bin/bash
#
# export_JSON <variables>
# 
# Synopsis:
#
#	$ (
#		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_simple()
{
	(
		set -o pipefail
		vars_to_env0 "$@" | env0_to_JSON
	)
}

safe_stdout()
{
	set -- "$(mktemp)" "$@"
	if (shift; "$@") > "$1"
	then
		r=0
		cat < "$1"
	else
		r=$?
	fi
	rm "$1"
	return $r
}

export_JSON()
{
	safe_stdout export_JSON_simple "$@"
}

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
}