chiark / gitweb /
cryptop.list: Look for correct delimiter when fixing up key labels.
[distorted-keys] / cryptop.list
CommitLineData
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
26set -e
27case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
28. "$KEYSLIB"/keyfunc.sh
29
30defhelp <<HELP
31[-Ha] [-C COLUMN,...] [-u USER] [PATTERN ...]
32List stored keys. If PATTERNs are given, only list keys whose labels match
33at least one PATTERN.
34
35Options:
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
41A COLUMN spec consists of a column name and an optional column width; the
42separator 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 50Columns 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.
57HELP
58
59###--------------------------------------------------------------------------
60### Column types.
61
62ALLCOLS=""
63defcol () { ALLCOLS=${ALLCOLS:+$ALLCOLS,}$1; }
64
65defcol flags
66col_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
83defcol label
84col_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
94defcol profile
95col_profile () {
96 label=$1
97
98 readmeta store/$label
99 echo "$profile"
100}
101
102defcol recov
103col_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.
119header=t
120cols=$ALLCOLS
121all=nil
122user=$USERV_USER
123while 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
131done
132shift $(( $OPTIND - 1 ))
133case $# in 0) set "*" ;; esac
134cd $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.
139calcwd=nil
a22ca62e 140cc=$cols cols=""
f5673211
MW
141while :; 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
174done
175
176## Second and third pass: find the keys, compute their properties and either
177## measure column widths or display the results.
178while :; 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
263EOF
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
270done
271
272###----- That's all, folks --------------------------------------------------