2 gpgstats.c - Program to produce stats on a GPG keyring.
3 Written by Jonathan McDowell <noodles@earth.li>.
5 19/02/2000 - Started writing (sort of).
14 #include <readline/readline.h>
15 #include <readline/history.h>
19 #include "graphstuff.h"
26 struct keycount { unsigned long count; struct key *k; };
28 extern struct ll *trees;
29 extern struct ll *finished;
31 void insertval(unsigned long val, struct keycount a[], struct key *curkey)
36 if (val<a[loop--].count) return;
38 while (val>a[loop].count && loop >= 0) {
46 void printtrees(int minsize)
48 struct ll *curtree,*curkey;
49 unsigned long count, total;
53 while (curtree!=NULL) {
54 curkey=curtree->object;
57 while (curkey!=NULL) {
62 // log(LOG_INFO, "Tree size of %ld\n", count);
64 curtree=curtree->next;
66 // log(LOG_INFO, "Total of %ld trees.\n", total);
70 void sixdegrees(uint64_t keyid)
72 struct stats_key *keyinfo;
76 if ((keyinfo = findinhash(keyid)) == NULL) {
77 printf("Couldn't find key 0x%llX.\n", keyid);
81 printf("Six degrees for 0x%llX (%s):\n", keyinfo->keyid,
82 keyid2uid(keyinfo->keyid));
84 puts("\t\t Signs Signed by");
85 for (loop = 1; loop < 7; loop++) {
87 degree = countdegree(keyinfo, 0, loop);
88 printf("Degree %d:\t%8ld", loop, degree);
90 degree = countdegree(keyinfo, 1, loop);
91 printf("\t%8ld\n", degree);
96 void showkeysigs(uint64_t keyid, bool sigs)
98 struct stats_key *keyinfo = NULL;
102 if ((keyinfo = findinhash(keyid)) == NULL) {
103 printf("Couldn't find key 0x%llX.\n", keyid);
107 printf("0x%llX (%s) %s:\n", keyinfo->keyid, keyid2uid(keyinfo->keyid),
108 sigs ? "is signed by" : "signs");
111 cursig = keyinfo->sigs;
113 // cursig = keyinfo->signs;
116 while (cursig!=NULL) {
118 printf("\t0x%08lX (%s)\n",
119 ((struct key *)cursig->object)->keyid,
120 keyid2uid(((struct key *)cursig->object)->keyid));
124 printf("\t%s a total of %ld keys.\n", sigs ? "Signed by" : "Signs",
130 unsigned long loop, total, hash, hashmax, hashmin, cur, sigs, signs;
134 total=sigs=signs=hash=names=0;
138 for (loop=0; loop<HASHSIZE; loop++) {
139 curkey=gethashtableentry(loop);
141 if (cur>hashmax) hashmax=cur;
142 if (cur<hashmin) hashmin=cur;
144 while (curkey!=NULL) {
145 sigs+=llsize(((struct key *)curkey->object)->sigs);
146 signs+=llsize(((struct key *)curkey->object)->signs);
147 if (((struct key *)curkey->object)->name!=NULL)
148 names+=strlen(((struct key *)curkey->object)->name);
153 printf("%10ld bytes in %ld keys\n", hash*sizeof(struct key), hash);
154 total += hash*sizeof(struct key);
155 printf("%10ld bytes in hash structure\n", hash*sizeof(struct ll));
156 total += hash*sizeof(struct ll);
157 printf(" (Max hash bucket %ld, min hash bucket %ld.)\n", hashmax, hashmin);
158 printf("%10ld bytes in %ld sigs.\n", sigs*sizeof(struct ll), sigs);
159 total += sigs*sizeof(struct ll);
160 printf("%10ld bytes in %ld signs.\n", signs*sizeof(struct ll), signs);
161 total += signs*sizeof(struct ll);
162 printf("%10ld bytes in names.\n", names);
164 printf("%10ld bytes total.\n", total);
167 void showmostsigns(int sigs)
169 unsigned long count,loop;
170 struct keycount signs[10];
173 memset(signs, 0, sizeof(signs));
174 // for (count=0; count<10; count++) { signs[count].count=0; };
176 for (loop=0; loop<HASHSIZE; loop++) {
177 curkey=gethashtableentry(loop);
178 while (curkey!=NULL) {
180 count=llsize(((struct key *)curkey->object)->sigs);
182 count=llsize(((struct key *)curkey->object)->signs);
185 insertval(count, signs, (struct key *)curkey->object);
191 for (count=0; count<10; count++) {
192 if (signs[count].k != NULL) {
193 printf("0x%08lX (%s) %s %ld keys.\n",
194 signs[count].k->keyid, signs[count].k->name,
195 sigs ? "is signed by" : "signs",
201 void findmaxpath(unsigned long max)
203 struct key *from, *to, *tmp;
205 unsigned long distance, loop;
207 printf("In findmaxpath\n");
210 for (loop=0; loop<HASHSIZE && distance<max; loop++) {
211 curkey=gethashtableentry(loop);
212 while (curkey!=NULL && distance<max) {
214 tmp=furthestkey((struct key *)curkey->object);
215 if (tmp->colour>distance) {
216 from=(struct key *)curkey->object;
219 printf("Current max path (#%ld) is from %08lX to %08lX (%ld steps)\n", loop, from->keyid, to->keyid, distance);
224 printf("Max path is from %08lX to %08lX (%ld steps)\n",
232 printf("gpgstats %s by Jonathan McDowell\n", VERSION);
233 puts("A simple program to do stats on a GPG keyring.\n");
235 puts("DFS <minsize>\t\tOutput details on the strongly connected");
236 puts("\t\t\tsubtrees, min size <minsize>");
237 puts("MAXPATH\t\t\tShow the two further apart keys.");
238 puts("MEMSTATS\t\tShow some stats about memory usage.");
239 puts("MOSTSIGNED\t\tShow the 10 keys signed by most others.");
240 puts("PATH <keyida> <keyidb>\tShows the path of trust (if any) from.");
241 puts("\t\t\tkeyida to keyidb (ie I have keyida, I want keyidb).");
242 puts("QUIT\t\t\tQuits the program.");
243 puts("READ <file>\t\tRead <file> in and add to the loaded keyring.");
244 puts("SIGNS <keyid>\t\tShows the keys that the given key signs.");
245 puts("SIGNSMOST\t\tShow the 10 keys that sign most other keys.");
246 puts("SIGS <keyid>\t\tShows the signatures on the given key.");
247 puts("SIXDEGREES <keyid>\tShows the 6 degrees from the given keyid.");
248 puts("STATS\t\t\tDisplay some stats about the loaded keyring.");
251 void commandloop(void)
253 struct cfginf commands[]={{"QUIT", 0, NULL},
255 {"SIXDEGREES", 1, NULL},
262 {"SIGNSMOST", 0, NULL},
263 {"MOSTSIGNED", 0, NULL},
264 {"MEMSTATS", 0, NULL},
265 {"MAXPATH", 1, NULL}};
270 commands[1].var=commands[2].var=commands[3].var=¶m;
271 commands[4].var=commands[5].var=commands[8].var=¶m;
272 commands[12].var=¶m;
275 memset(tmpstr, 0, 1023);
276 fgets(tmpstr, 1023, stdin);
277 // printf("Read: '%s'\n", tmpstr);
278 cmd=parseline(commands, tmpstr);
279 // printf("Got command: '%d'\n", cmd);
280 // printf("Got command: '%d'\n", cmd);
287 sixdegrees(strtoul(param, NULL, 16));
290 //dofindpath(strtoul(param, NULL, 16),
291 // strtoul(strchr(param, ' ')+1, NULL, 16));
294 showkeysigs(strtoul(param, NULL, 16), true);
297 showkeysigs(strtoul(param, NULL, 16), false);
300 printf("%ld keys currently loaded, %ld self signed.\n",
309 printf("Starting first DFS.\n");
311 printf("Starting second DFS.\n");
313 printtrees(atoi(param));
325 findmaxpath(atoi(param));
332 int main(int argc, char *argv[])
334 printf("gpgstats %s by Jonathan McDowell\n", VERSION);
335 puts("Copyright 2000 Project Purple. Released under the GPL.");
336 puts("A simple program to do stats on a GPG keyring.\n");
340 printf("%ld selfsigned.\n", checkselfsig());
341 printf("%ld distinct keys.\n", hashelements());