-
Notifications
You must be signed in to change notification settings - Fork 0
/
dmi2json
executable file
·155 lines (125 loc) · 4.32 KB
/
dmi2json
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/bin/bash
#
# convert the output of dmidecode into JSON
#
# labels are stripped of all non alphanumeric text
# we look for LABEL: VALUE (splitting on the ':')
# if there is no ':' then it is a VALUE
#
# because sections repeat, each instance is cached
# in a tmp directory and dumped at the end of processing
#
unset TAG OLDTAG HANDLE OLDHANDLE PREFIX
quote() {
WHAT="$*"
[[ ${WHAT} ]] || return # skip if blank
WHAT="${WHAT/[[:space:]]/}"
WHAT=$(echo $WHAT | tr -d '\t') # remove tabs
[[ $WHAT && ${IGNORE[${WHAT,,}]} ]] && WHAT=""
[[ $WHAT || $LABEL ]] || return
# enforce quoting on values that could look like numbers
[[ $LABEL =~ BIOSRevision || $LABEL =~ Version || $LABEL =~ Description || $LABEL =~ Address || $LABEL =~ Serial || $LABEL == "Rank" ]] && echo -n "${PREFIX}\"$WHAT\"" && return
[[ $* =~ ^[0-9]+(.[0-9])?$ ]] && echo -n "${PREFIX}$WHAT" || echo -n "${PREFIX}\"$WHAT\""
}
fail() { echo >&2 $* ; exit 1 ; }
emit() {
[[ $FILENAME ]] || fail "no filename set"
echo -n -e "$*" >> $FILENAME
}
show() { echo " {" ; cat $1 ; echo ; echo " }" ; }
TMPDIR=$(mktemp -d)
REJECT="^(Inactive|Table|End Of Table|SMBIOS|Group Associations|OEM-specific Type|#|[0-9])"
declare -A IGNORE=(
["unknown"]=true
["unspecified"]=true
["to be filled by o.e.m."]=true
["not provided"]=true
["not specified"]=true
["not present"]=true
["no module installed"]=true
["0123456789"]=true
["1234567890"]=true
["<out of spec>"]=true
)
while IFS= read -r LINE
do
[[ $LINE ]] || continue
if [[ $LINE =~ $REJECT ]]; then
while IFS= read -r LINE
do
[[ -z $LINE ]] && break
done
continue
fi
[[ $LINE =~ ^Handle ]] && HANDLE="${LINE:7:6}" && continue
[[ $LINE =~ ^[A-Z] ]] && TAG=${LINE//[[:space:]]/} && continue
unset SKIP
# LABEL is all text to left of ":"
# VALUE is all text to right of ":"
LABEL=${LINE%%:*}
VALUE=${LINE##*:}
# if no ':' they'll be the same, and therefore text represents VALUE
[[ $VALUE == $LABEL ]] && unset LABEL
[[ $LABEL && $VALUE ]] && BOTH=true || unset BOTH
# trim whitespace and undesirables as needed
LABEL=${LABEL//[()\"\.\/[:space:]-]/}
VALUE=${VALUE//\"/}
mkdir $TMPDIR/$TAG > /dev/null 2>&1
# TAG represents top level structure that starts at beginning of the line
if [[ $TAG != $OLDTAG || $HANDLE != $OLDHANDLE ]]; then
# clean up prior tag
[[ $PREFIX ]] && emit "\n${PREFIX}]\n" # prefix means list mode
mkdir $TMPDIR/$TAG > /dev/null 2>&1
FILENAME=$TMPDIR/$TAG/$HANDLE
unset LAST
unset PREFIX
OLDTAG=$TAG
OLDHANDLE=$HANDLE
fi
# if just a VALUE element then we are "SOLO"
# which represents a list element
[[ $VALUE && -z $LABEL ]] && SOLO=true || unset SOLO
[[ $SOLO && $LAST ]] && SKIP=true && VALUE=" " && unset SOLO # errant line we can live without
# did we encounter an end of list?
[[ $LABEL && $VALUE && $PREFIX ]] && emit "\n${PREFIX}],\n" && unset PREFIX
# we can't comma separate list items until we know there's another entry
# on the next line, which we won't know until then
# so we save actual line endings until the *beginning* of the next line
# and tack one on at the end of the section to clean up
[[ $SOLO && $PRIOR ]] && emit ",\n" # mid list
[[ $SOLO && $LAST ]] && emit "," # special case
[[ -z $VALUE && $LAST ]] && emit ",\n"
[[ $SKIP ]] && emit ",\n"
[[ $BOTH && $LAST ]] && emit ",\n"
# print item name
[[ $LABEL ]] && emit "$PREFIX \"$LABEL\": "
# print item value, or if none, start a new list
[[ -n $VALUE ]] && emit "$(quote "$VALUE")" || emit "[\n"
[[ $LABEL && -z $VALUE ]] && PREFIX=" "
# to compare prior states
LAST=$BOTH
PRIOR=$SOLO
done
TAGS=$(ls $TMPDIR | wc -l)
echo "{"
cd $TMPDIR
for TAG in *
do
let "TAGS--"
echo " \"$TAG\":"
CNT=$(ls $TMPDIR/$TAG | wc -l)
[[ $CNT -eq 1 ]] && [[ $TAGS -gt 0 ]] && show $TMPDIR/$TAG/* && echo -e "\n," && continue
[[ $CNT -eq 1 ]] && [[ $TAGS -eq 0 ]] && show $TMPDIR/$TAG/* && continue
echo " ["
for FILE in $TMPDIR/$TAG/*
do
show $FILE
let "CNT--"
[[ $CNT -gt 0 ]] && echo ","
done
echo
echo " ]"
[[ $TAGS -gt 0 ]] && echo ","
done
echo "}"
rm -rf $TMPDIR