]> git.sommitrealweird.co.uk Git - onak.git/blob - gpgstats-0.0.2/gpgstats.c
a72879945e4f89526517f70b59239b9723fd2cf6
[onak.git] / gpgstats-0.0.2 / gpgstats.c
1 /*
2         gpgstats.c - Program to produce stats on a GPG keyring.
3         Written by Jonathan McDowell <noodles@earth.li>.
4
5         19/02/2000 - Started writing (sort of).
6 */
7
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #ifdef USEREADLINE
14 #include <readline/readline.h>
15 #include <readline/history.h>
16 #endif
17
18 #include "gpgstats.h"
19 #include "graphstuff.h"
20 #include "hash.h"
21 #include "keydb.h"
22 #include "ll.h"
23 #include "parse.h"
24 #include "stats.h"
25
26 struct keycount { unsigned long count; struct key *k; };
27
28 extern struct ll *trees;
29 extern struct ll *finished;
30
31 void insertval(unsigned long val, struct keycount a[], struct key *curkey)
32 {
33         int loop;
34
35         loop=9;
36         if (val<a[loop--].count) return;
37
38         while (val>a[loop].count && loop >= 0) {
39                 a[loop+1]=a[loop];
40                 loop--;
41         }
42         a[loop+1].count=val;
43         a[loop+1].k=curkey;
44 }
45
46 void printtrees(int minsize)
47 {
48         struct ll *curtree,*curkey;
49         unsigned long count, total;
50
51         curtree=trees;
52         total=0;
53         while (curtree!=NULL) { 
54                 curkey=curtree->object;
55                 ++total;
56                 count=0;
57                 while (curkey!=NULL) {
58                         count++;
59                         curkey=curkey->next;
60                 }
61                 if (count>=minsize) {
62 //                      log(LOG_INFO, "Tree size of %ld\n", count);
63                 }
64                 curtree=curtree->next;
65         }
66 //      log(LOG_INFO, "Total of %ld trees.\n", total);
67 }
68
69
70 void sixdegrees(uint64_t keyid)
71 {
72         struct stats_key *keyinfo;
73         int loop;
74         long degree;
75
76         if ((keyinfo = findinhash(keyid)) == NULL) {
77                 printf("Couldn't find key 0x%llX.\n", keyid);
78                 return;
79         }
80
81         printf("Six degrees for 0x%llX (%s):\n", keyinfo->keyid,
82                                                  keyid2uid(keyinfo->keyid));
83
84         puts("\t\t   Signs       Signed by");
85         for (loop = 1; loop < 7; loop++) {
86                 initcolour(false);
87                 degree = countdegree(keyinfo, 0, loop);
88                 printf("Degree %d:\t%8ld", loop, degree);
89                 initcolour(false);
90                 degree = countdegree(keyinfo, 1, loop);
91                 printf("\t%8ld\n", degree);
92         }
93 }
94
95
96 void showkeysigs(uint64_t keyid, bool sigs)
97 {
98         struct stats_key *keyinfo = NULL;
99         struct ll *cursig;
100         long count;
101
102         if ((keyinfo = findinhash(keyid)) == NULL) {
103                 printf("Couldn't find key 0x%llX.\n", keyid);
104                 return;
105         }
106
107         printf("0x%llX (%s) %s:\n", keyinfo->keyid, keyid2uid(keyinfo->keyid),
108                         sigs ? "is signed by" : "signs");
109
110         if (sigs) {
111                 cursig = keyinfo->sigs;
112         } else {
113 //              cursig = keyinfo->signs;
114         }
115         count=0;
116         while (cursig!=NULL) {
117                 count++;
118                 printf("\t0x%08lX (%s)\n",
119                                 ((struct key *)cursig->object)->keyid,
120                         keyid2uid(((struct key *)cursig->object)->keyid));
121                 cursig=cursig->next;
122         }
123
124         printf("\t%s a total of %ld keys.\n", sigs ? "Signed by" : "Signs",
125                                                 count); 
126 }
127
128 void memstats()
129 {
130         unsigned long loop, total, hash, hashmax, hashmin, cur, sigs, signs;
131         unsigned long names;
132         struct ll *curkey;
133
134         total=sigs=signs=hash=names=0;
135         hashmin=-1;
136         hashmax=0;
137
138         for (loop=0; loop<HASHSIZE; loop++) {
139                 curkey=gethashtableentry(loop);
140                 cur=llsize(curkey);
141                 if (cur>hashmax) hashmax=cur;
142                 if (cur<hashmin) hashmin=cur;
143                 hash+=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);
149                         curkey=curkey->next;
150                 }
151         }
152
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);
163         total += names;
164         printf("%10ld bytes total.\n", total);
165 }
166
167 void showmostsigns(int sigs)
168 {
169         unsigned long count,loop;
170         struct keycount signs[10];
171         struct ll *curkey;
172
173         memset(signs, 0, sizeof(signs));
174         // for (count=0; count<10; count++) { signs[count].count=0; };
175         count=0;
176         for (loop=0; loop<HASHSIZE; loop++) {
177                 curkey=gethashtableentry(loop);
178                 while (curkey!=NULL) {
179                         if (sigs) {
180                                 count=llsize(((struct key *)curkey->object)->sigs);
181                         } else {
182                                 count=llsize(((struct key *)curkey->object)->signs);
183                         }
184                         if (count != 0) {
185                                 insertval(count, signs, (struct key *)curkey->object);
186                         }
187                         curkey=curkey->next;
188                 }
189         }
190         
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",
196                                 signs[count].count);
197                 }
198         }
199 }
200
201 void findmaxpath(unsigned long max)
202 {
203         struct key *from, *to, *tmp;
204         struct ll *curkey;
205         unsigned long distance, loop;
206
207         printf("In findmaxpath\n");
208         distance=0;
209         from=to=NULL;
210         for (loop=0; loop<HASHSIZE && distance<max; loop++) {
211                 curkey=gethashtableentry(loop);
212                 while (curkey!=NULL && distance<max) {
213                         initcolour(false);
214                         tmp=furthestkey((struct key *)curkey->object);
215                         if (tmp->colour>distance) {
216                                 from=(struct key *)curkey->object;
217                                 to=tmp;
218                                 distance=to->colour;
219                                 printf("Current max path (#%ld) is from %08lX to %08lX (%ld steps)\n", loop, from->keyid, to->keyid, distance);
220                         }
221                         curkey=curkey->next;
222                 }
223         }
224         printf("Max path is from %08lX to %08lX (%ld steps)\n",
225                         from->keyid,
226                         to->keyid,
227                         distance);
228 }
229
230 void showhelp(void)
231 {
232         printf("gpgstats %s by Jonathan McDowell\n", VERSION);
233         puts("A simple program to do stats on a GPG keyring.\n");
234
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.");
249 }
250
251 void commandloop(void)
252 {
253         struct cfginf commands[]={{"QUIT", 0,  NULL},
254                                 {"READ", 1, NULL},
255                                 {"SIXDEGREES", 1, NULL},
256                                 {"PATH", 1, NULL},
257                                 {"SIGS", 1, NULL},
258                                 {"SIGNS", 1, NULL},
259                                 {"STATS", 0, NULL},
260                                 {"HELP", 0, NULL},
261                                 {"DFS", 1, NULL},
262                                 {"SIGNSMOST", 0, NULL},
263                                 {"MOSTSIGNED", 0, NULL},
264                                 {"MEMSTATS", 0, NULL},
265                                 {"MAXPATH", 1, NULL}};
266         char tmpstr[1024];
267         char *param;
268         int cmd;
269
270         commands[1].var=commands[2].var=commands[3].var=&param;
271         commands[4].var=commands[5].var=commands[8].var=&param;
272         commands[12].var=&param;
273
274         do {
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);
281
282                 switch (cmd) {
283                 case 2:
284                         readkeys(param);
285                         break;
286                 case 3:
287                         sixdegrees(strtoul(param, NULL, 16));
288                         break;
289                 case 4:
290                         //dofindpath(strtoul(param, NULL, 16),
291                         //      strtoul(strchr(param, ' ')+1, NULL, 16));
292                         break;
293                 case 5:
294                         showkeysigs(strtoul(param, NULL, 16), true);
295                         break;
296                 case 6:
297                         showkeysigs(strtoul(param, NULL, 16), false);
298                         break;
299                 case 7:
300                         printf("%ld keys currently loaded, %ld self signed.\n",
301                                         hashelements(),
302                                         checkselfsig());
303                         break;
304                 case 8:
305                         showhelp();
306                         break;
307                 case 9:
308                         finished=trees=NULL;
309                         printf("Starting first DFS.\n");
310                         DFS();
311                         printf("Starting second DFS.\n");
312                         DFSsorted();
313                         printtrees(atoi(param));
314                         break;
315                 case 10:
316                         showmostsigns(0);
317                         break;
318                 case 11:
319                         showmostsigns(1);
320                         break;
321                 case 12:
322                         memstats();
323                         break;
324                 case 13:
325                         findmaxpath(atoi(param));
326                         break;
327                 }
328         } while (cmd!=1);
329 }
330
331
332 int main(int argc, char *argv[])
333 {
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");
337
338         inithash();
339         readkeys("keyfile");
340         printf("%ld selfsigned.\n", checkselfsig());
341         printf("%ld distinct keys.\n", hashelements());
342
343         commandloop();
344         return 0;
345 }