Commit | Line | Data |
---|---|---|
f5673211 MW |
1 | #! /bin/sh |
2 | ### | |
3 | ### List a user's keys | |
4 | ### | |
5 | ### (c) 2011 Mark Wooding | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This file is part of the distorted.org.uk key management suite. | |
11 | ### | |
12 | ### distorted-keys is free software; you can redistribute it and/or modify | |
13 | ### it under the terms of the GNU General Public License as published by | |
14 | ### the Free Software Foundation; either version 2 of the License, or | |
15 | ### (at your option) any later version. | |
16 | ### | |
17 | ### distorted-keys is distributed in the hope that it will be useful, | |
18 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ### GNU General Public License for more details. | |
21 | ### | |
22 | ### You should have received a copy of the GNU General Public License | |
23 | ### along with distorted-keys; if not, write to the Free Software Foundation, | |
24 | ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
25 | ||
26 | set -e | |
27 | case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac | |
28 | . "$KEYSLIB"/keyfunc.sh | |
29 | ||
30 | defhelp <<HELP | |
31 | [-Ha] [-C COLUMN,...] [-u USER] [PATTERN ...] | |
32 | List stored keys. If PATTERNs are given, only list keys whose labels match | |
33 | at least one PATTERN. | |
34 | ||
35 | Options: | |
36 | -H Don't show the column headings (useful for scripts). | |
37 | -C COLUMN,... Select the columns to show. | |
38 | -a Show keys owned by all users. | |
39 | -u USER Show keys owned by USER. | |
40 | ||
d5fe0926 MW |
41 | A COLUMN spec consists of a column name and an optional column width; the |
42 | separator character determines the behaviour as shown below. The default is | |
43 | \`+0'. | |
44 | NAME=WIDTH Exact width: truncate the contents to fit if necessary. | |
45 | NAME:WIDTH Minimum width: spill into the next column (breaking the | |
46 | alignment) if necessary. | |
47 | NAME+WIDTH Minimum width: if a value won't fit then make the entire | |
48 | column wider. | |
f5673211 | 49 | |
d5fe0926 | 50 | Columns names: |
f5673211 MW |
51 | flags Various flags for the key. (Unset flags are shown as \`.') |
52 | R key has recovery information | |
53 | ! key nub needs recovery | |
54 | label The key's label (relative to its owner). | |
55 | profile The key's profile name. | |
56 | recov Recovery key labels, comma-separated. | |
57 | HELP | |
58 | ||
59 | ###-------------------------------------------------------------------------- | |
60 | ### Column types. | |
61 | ||
62 | ALLCOLS="" | |
63 | defcol () { ALLCOLS=${ALLCOLS:+$ALLCOLS,}$1; } | |
64 | ||
65 | defcol flags | |
66 | col_flags () { | |
67 | label=$1 | |
68 | flags="" | |
69 | ||
70 | rflag=. | |
71 | for i in recov/*/current/$label.recov; do | |
72 | if [ -f "$i" ]; then rflag=R; break; fi | |
73 | done | |
74 | flags=$flags$rflag | |
75 | ||
76 | bangflag=! | |
77 | if [ -f nub/$label ]; then bangflag=.; fi | |
78 | flags=$flags$bangflag | |
79 | ||
80 | echo "$flags" | |
81 | } | |
82 | ||
83 | defcol label | |
84 | col_label () { | |
85 | label=$1 | |
86 | ||
87 | case $all,$label in | |
f8e6a4ac | 88 | nil,$USERV_USER/*) plabel=${label#*/} ;; |
f5673211 MW |
89 | t,*) plabel=${label%%/*}:${label#*/} ;; |
90 | esac | |
91 | echo "$plabel" | |
92 | } | |
93 | ||
94 | defcol profile | |
95 | col_profile () { | |
96 | label=$1 | |
97 | ||
98 | readmeta store/$label | |
99 | echo "$profile" | |
100 | } | |
101 | ||
102 | defcol recov | |
103 | col_recov () { | |
104 | label=$1 | |
105 | recov="" | |
106 | ||
107 | for i in recov/*; do | |
108 | if [ -f "$i/current/$label.recov" ]; then | |
109 | recov=${recov:+$recov,}${i#recov/} | |
110 | fi | |
111 | done | |
112 | echo "$recov" | |
113 | } | |
114 | ||
115 | ###-------------------------------------------------------------------------- | |
116 | ### Main program. | |
117 | ||
118 | ## Parse the command-line options. Remaining arguments are glob patterns. | |
119 | header=t | |
120 | cols=$ALLCOLS | |
121 | all=nil | |
122 | user=$USERV_USER | |
123 | while getopts "HaC:u:" opt; do | |
124 | case "$opt" in | |
125 | a) all=t ;; | |
126 | H) header=nil ;; | |
127 | C) cols=$OPTARG ;; | |
128 | u) user=$OPTARG ;; | |
129 | *) usage_err ;; | |
130 | esac | |
131 | done | |
132 | shift $(( $OPTIND - 1 )) | |
133 | case $# in 0) set "*" ;; esac | |
134 | cd $KEYS | |
135 | ||
136 | ## First pass: validate the column specifications. Translate all bare column | |
137 | ## names into explicit `NAME+0' forms. Decide whether we need a width- | |
138 | ## measuring pass. | |
139 | calcwd=nil | |
a22ca62e | 140 | cc=$cols cols="" |
f5673211 MW |
141 | while :; do |
142 | ||
143 | ## Pick off the next column name. If none are left, leave the loop. | |
144 | case "$cc" in | |
145 | *,*) col=${cc%%,*} cc=${cc#*,} ;; | |
146 | ?*) col=$cc cc="" ;; | |
147 | *) break ;; | |
148 | esac | |
149 | ||
150 | ## Extract the column name for later. | |
151 | name=${col%[:=+]*} | |
152 | ||
153 | ## If we have a minimum width or no width, we need a measuring pass. | |
154 | case "$col" in *[:=]*) ;; *) calcwd=t ;; esac | |
155 | ||
156 | ## Check the column width is valid. Build the new column list with | |
157 | ## explicit widths. | |
158 | case "$col" in | |
159 | *[:=+]*) | |
160 | wd=${col#*[:=+]} | |
a22ca62e | 161 | cols=${cols:+$cols,}$col |
f5673211 MW |
162 | checknumber "column width" "$wd" |
163 | ;; | |
164 | *) | |
a22ca62e | 165 | cols=${cols:+$cols,}$col+0 |
f5673211 MW |
166 | ;; |
167 | esac | |
168 | ||
169 | ## Check the column name. | |
170 | case ,$ALLCOLS, in | |
171 | *,"$name",*) ;; | |
172 | *) echo >&2 "$quis: unknown column \`$name'"; exit 1 ;; | |
173 | esac | |
174 | done | |
175 | ||
176 | ## Second and third pass: find the keys, compute their properties and either | |
177 | ## measure column widths or display the results. | |
178 | while :; do | |
179 | ||
180 | ## Decide whether we need to display a header. (We need this on both | |
181 | ## passes, because it may contribute to width.) | |
182 | doheader=$header | |
183 | ||
184 | ## Find the metadata files. This tells us where the keys are. | |
185 | case $all in | |
186 | t) dir=store ;; | |
187 | nil) dir=store/$user ;; | |
188 | esac | |
d8c2ee90 | 189 | metas=$(find $dir -type f -name meta | sort) |
f5673211 MW |
190 | |
191 | ## Work through the keys we found. | |
192 | while :; do | |
193 | ||
194 | ## If we're not doing a header line, read the next metadata file name. | |
195 | ## Check that it matches at least one pattern. | |
196 | case $doheader in | |
197 | nil) | |
198 | if ! read meta; then break; fi | |
199 | label=${meta#store/}; label=${label%/meta} | |
200 | matchp=nil | |
201 | for pat in "$@"; do | |
202 | case "$label" in $pat) matchp=t; break ;; esac | |
203 | done | |
204 | case $matchp in nil) continue ;; esac | |
205 | ;; | |
206 | esac | |
207 | ||
208 | ## Now iterate over the columns. If we're calculating widths, use the | |
209 | ## ones we worked out last time, and clear the list so we can build a new | |
210 | ## one as we go. | |
a22ca62e MW |
211 | cc=$cols sep="" |
212 | case $calcwd in t) cols="" ;; esac | |
f5673211 MW |
213 | while :; do |
214 | ||
215 | ## Pick off the next column spec. | |
216 | case "$cc" in | |
217 | *,*) col=${cc%%,*} cc=${cc#*,} ;; | |
218 | ?*) col=$cc cc="" ;; | |
219 | *) break ;; | |
220 | esac | |
221 | ||
222 | ## Work out the column name. | |
223 | name=${col%[:=+]*} wd=${col#*[:=+]} | |
224 | ||
225 | ## Work out the value. If this is a header line, then it's just the | |
226 | ## column name in upper case; otherwise we have work to do. | |
227 | case $doheader in | |
228 | t) value=$(echo $name | tr a-z A-Z) ;; | |
229 | nil) value=$(col_$name $label) ;; | |
230 | esac | |
231 | ||
232 | ## Work out what to do about it. If we're measuring, then update our | |
233 | ## idea of the column width. If we're printing, work out a format. | |
234 | case $calcwd,$col in | |
235 | t,*[:=]*) | |
a22ca62e | 236 | cols=${cols:+$cols,}$col |
f5673211 MW |
237 | ;; |
238 | t,*+*) | |
239 | colwd=$(( $(echo "$value" | wc -c) - 1 )) | |
240 | if [ $colwd -gt $wd ]; then wd=$colwd; fi | |
a22ca62e | 241 | cols=${cols:+$cols,}$name+$wd |
f5673211 MW |
242 | ;; |
243 | nil,*[=+]*) | |
244 | fmt="%-${wd}.${wd}s" | |
245 | ;; | |
246 | nil,*:*) | |
247 | fmt="%-${wd}s" | |
248 | ;; | |
249 | esac | |
250 | ||
251 | ## If we're printing, then print something. Leave space between the | |
252 | ## columns. | |
253 | case $calcwd in nil) printf "$sep$fmt" "$value"; sep=" " ;; esac | |
254 | done | |
255 | ||
256 | ## The next line will certainly not be a header. | |
257 | doheader=nil | |
258 | ||
259 | ## Start a new line if we're printing. | |
260 | case $calcwd in nil) printf "\n" ;; esac | |
261 | done <<EOF | |
262 | $metas | |
263 | EOF | |
264 | ||
265 | ## If we were measuring, go round again and print; otherwise we're done. | |
266 | case $calcwd in | |
267 | t) calcwd=nil ;; | |
268 | nil) break ;; | |
269 | esac | |
270 | done | |
271 | ||
272 | ###----- That's all, folks -------------------------------------------------- |