Update Debian Vcs-* fields to point to git repository
[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 void showkeysigs(uint64_t keyid, bool sigs)
70 {
71         struct stats_key *keyinfo = NULL;
72         struct ll *cursig;
73         long count;
74
75         if ((keyinfo = findinhash(keyid)) == NULL) {
76                 printf("Couldn't find key 0x%llX.\n", keyid);
77                 return;
78         }
79
80         printf("0x%llX (%s) %s:\n", keyinfo->keyid, keyid2uid(keyinfo->keyid),
81                         sigs ? "is signed by" : "signs");
82
83         if (sigs) {
84                 cursig = keyinfo->sigs;
85         } else {
86 //              cursig = keyinfo->signs;
87         }
88         count=0;
89         while (cursig!=NULL) {
90                 count++;
91                 printf("\t0x%08lX (%s)\n",
92                                 ((struct key *)cursig->object)->keyid,
93                         keyid2uid(((struct key *)cursig->object)->keyid));
94                 cursig=cursig->next;
95         }
96
97         printf("\t%s a total of %ld keys.\n", sigs ? "Signed by" : "Signs",
98                                                 count); 
99 }
100
101 void memstats()
102 {
103         unsigned long loop, total, hash, hashmax, hashmin, cur, sigs, signs;
104         unsigned long names;
105         struct ll *curkey;
106
107         total=sigs=signs=hash=names=0;
108         hashmin=-1;
109         hashmax=0;
110
111         for (loop=0; loop<HASHSIZE; loop++) {
112                 curkey=gethashtableentry(loop);
113                 cur=llsize(curkey);
114                 if (cur>hashmax) hashmax=cur;
115                 if (cur<hashmin) hashmin=cur;
116                 hash+=cur;
117                 while (curkey!=NULL) {
118                         sigs+=llsize(((struct key *)curkey->object)->sigs);
119                         signs+=llsize(((struct key *)curkey->object)->signs);
120                         if (((struct key *)curkey->object)->name!=NULL)
121                         names+=strlen(((struct key *)curkey->object)->name);
122                         curkey=curkey->next;
123                 }
124         }
125
126         printf("%10ld bytes in %ld keys\n", hash*sizeof(struct key), hash);
127         total += hash*sizeof(struct key);
128         printf("%10ld bytes in hash structure\n", hash*sizeof(struct ll));
129         total += hash*sizeof(struct ll);
130         printf("           (Max hash bucket %ld, min hash bucket %ld.)\n", hashmax, hashmin);
131         printf("%10ld bytes in %ld sigs.\n", sigs*sizeof(struct ll), sigs);
132         total += sigs*sizeof(struct ll);
133         printf("%10ld bytes in %ld signs.\n", signs*sizeof(struct ll), signs);
134         total += signs*sizeof(struct ll);
135         printf("%10ld bytes in names.\n", names);
136         total += names;
137         printf("%10ld bytes total.\n", total);
138 }
139
140 void showmostsigns(int sigs)
141 {
142         unsigned long count,loop;
143         struct keycount signs[10];
144         struct ll *curkey;
145
146         memset(signs, 0, sizeof(signs));
147         // for (count=0; count<10; count++) { signs[count].count=0; };
148         count=0;
149         for (loop=0; loop<HASHSIZE; loop++) {
150                 curkey=gethashtableentry(loop);
151                 while (curkey!=NULL) {
152                         if (sigs) {
153                                 count=llsize(((struct key *)curkey->object)->sigs);
154                         } else {
155                                 count=llsize(((struct key *)curkey->object)->signs);
156                         }
157                         if (count != 0) {
158                                 insertval(count, signs, (struct key *)curkey->object);
159                         }
160                         curkey=curkey->next;
161                 }
162         }
163         
164         for (count=0; count<10; count++) {
165                 if (signs[count].k != NULL) {
166                         printf("0x%08lX (%s) %s %ld keys.\n",
167                                 signs[count].k->keyid, signs[count].k->name,
168                                 sigs ? "is signed by" : "signs",
169                                 signs[count].count);
170                 }
171         }
172 }
173
174 void showhelp(void)
175 {
176         printf("gpgstats %s by Jonathan McDowell\n", VERSION);
177         puts("A simple program to do stats on a GPG keyring.\n");
178
179         puts("DFS <minsize>\t\tOutput details on the strongly connected");
180         puts("\t\t\tsubtrees, min size <minsize>");
181         puts("MAXPATH\t\t\tShow the two further apart keys.");
182         puts("MEMSTATS\t\tShow some stats about memory usage.");
183         puts("MOSTSIGNED\t\tShow the 10 keys signed by most others.");
184         puts("PATH <keyida> <keyidb>\tShows the path of trust (if any) from.");
185         puts("\t\t\tkeyida to keyidb (ie I have keyida, I want keyidb).");
186         puts("QUIT\t\t\tQuits the program.");
187         puts("READ <file>\t\tRead <file> in and add to the loaded keyring.");
188         puts("SIGNS <keyid>\t\tShows the keys that the given key signs.");
189         puts("SIGNSMOST\t\tShow the 10 keys that sign most other keys.");
190         puts("SIGS <keyid>\t\tShows the signatures on the given key.");
191         puts("SIXDEGREES <keyid>\tShows the 6 degrees from the given keyid.");
192         puts("STATS\t\t\tDisplay some stats about the loaded keyring.");
193 }
194
195 void commandloop(void)
196 {
197         struct cfginf commands[]={{"QUIT", 0,  NULL},
198                                 {"READ", 1, NULL},
199                                 {"SIXDEGREES", 1, NULL},
200                                 {"PATH", 1, NULL},
201                                 {"SIGS", 1, NULL},
202                                 {"SIGNS", 1, NULL},
203                                 {"STATS", 0, NULL},
204                                 {"HELP", 0, NULL},
205                                 {"DFS", 1, NULL},
206                                 {"SIGNSMOST", 0, NULL},
207                                 {"MOSTSIGNED", 0, NULL},
208                                 {"MEMSTATS", 0, NULL},
209                                 {"MAXPATH", 1, NULL}};
210         char tmpstr[1024];
211         char *param;
212         int cmd;
213
214         commands[1].var=commands[2].var=commands[3].var=&param;
215         commands[4].var=commands[5].var=commands[8].var=&param;
216         commands[12].var=&param;
217
218         do {
219                 memset(tmpstr, 0, 1023);
220                 fgets(tmpstr, 1023, stdin);
221 //              printf("Read: '%s'\n", tmpstr);
222                 cmd=parseline(commands, tmpstr);
223 //              printf("Got command: '%d'\n", cmd);
224 //              printf("Got command: '%d'\n", cmd);
225
226                 switch (cmd) {
227                 case 2:
228                         readkeys(param);
229                         break;
230                 case 4:
231                         //dofindpath(strtoul(param, NULL, 16),
232                         //      strtoul(strchr(param, ' ')+1, NULL, 16));
233                         break;
234                 case 5:
235                         showkeysigs(strtoul(param, NULL, 16), true);
236                         break;
237                 case 6:
238                         showkeysigs(strtoul(param, NULL, 16), false);
239                         break;
240                 case 7:
241                         printf("%ld keys currently loaded, %ld self signed.\n",
242                                         hashelements(),
243                                         checkselfsig());
244                         break;
245                 case 8:
246                         showhelp();
247                         break;
248                 case 9:
249                         finished=trees=NULL;
250                         printf("Starting first DFS.\n");
251                         DFS();
252                         printf("Starting second DFS.\n");
253                         DFSsorted();
254                         printtrees(atoi(param));
255                         break;
256                 case 10:
257                         showmostsigns(0);
258                         break;
259                 case 11:
260                         showmostsigns(1);
261                         break;
262                 case 12:
263                         memstats();
264                         break;
265                 }
266         } while (cmd!=1);
267 }
268
269
270 int main(int argc, char *argv[])
271 {
272         printf("gpgstats %s by Jonathan McDowell\n", VERSION);
273         puts("Copyright 2000 Project Purple. Released under the GPL.");
274         puts("A simple program to do stats on a GPG keyring.\n");
275
276         inithash();
277         readkeys("keyfile");
278         printf("%ld selfsigned.\n", checkselfsig());
279         printf("%ld distinct keys.\n", hashelements());
280
281         commandloop();
282         return 0;
283 }