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);
69 void showkeysigs(uint64_t keyid, bool sigs)
71 struct stats_key *keyinfo = NULL;
75 if ((keyinfo = findinhash(keyid)) == NULL) {
76 printf("Couldn't find key 0x%llX.\n", keyid);
80 printf("0x%llX (%s) %s:\n", keyinfo->keyid, keyid2uid(keyinfo->keyid),
81 sigs ? "is signed by" : "signs");
84 cursig = keyinfo->sigs;
86 // cursig = keyinfo->signs;
89 while (cursig!=NULL) {
91 printf("\t0x%08lX (%s)\n",
92 ((struct key *)cursig->object)->keyid,
93 keyid2uid(((struct key *)cursig->object)->keyid));
97 printf("\t%s a total of %ld keys.\n", sigs ? "Signed by" : "Signs",
103 unsigned long loop, total, hash, hashmax, hashmin, cur, sigs, signs;
107 total=sigs=signs=hash=names=0;
111 for (loop=0; loop<HASHSIZE; loop++) {
112 curkey=gethashtableentry(loop);
114 if (cur>hashmax) hashmax=cur;
115 if (cur<hashmin) hashmin=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);
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);
137 printf("%10ld bytes total.\n", total);
140 void showmostsigns(int sigs)
142 unsigned long count,loop;
143 struct keycount signs[10];
146 memset(signs, 0, sizeof(signs));
147 // for (count=0; count<10; count++) { signs[count].count=0; };
149 for (loop=0; loop<HASHSIZE; loop++) {
150 curkey=gethashtableentry(loop);
151 while (curkey!=NULL) {
153 count=llsize(((struct key *)curkey->object)->sigs);
155 count=llsize(((struct key *)curkey->object)->signs);
158 insertval(count, signs, (struct key *)curkey->object);
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",
176 printf("gpgstats %s by Jonathan McDowell\n", VERSION);
177 puts("A simple program to do stats on a GPG keyring.\n");
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.");
195 void commandloop(void)
197 struct cfginf commands[]={{"QUIT", 0, NULL},
199 {"SIXDEGREES", 1, NULL},
206 {"SIGNSMOST", 0, NULL},
207 {"MOSTSIGNED", 0, NULL},
208 {"MEMSTATS", 0, NULL},
209 {"MAXPATH", 1, NULL}};
214 commands[1].var=commands[2].var=commands[3].var=¶m;
215 commands[4].var=commands[5].var=commands[8].var=¶m;
216 commands[12].var=¶m;
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);
231 //dofindpath(strtoul(param, NULL, 16),
232 // strtoul(strchr(param, ' ')+1, NULL, 16));
235 showkeysigs(strtoul(param, NULL, 16), true);
238 showkeysigs(strtoul(param, NULL, 16), false);
241 printf("%ld keys currently loaded, %ld self signed.\n",
250 printf("Starting first DFS.\n");
252 printf("Starting second DFS.\n");
254 printtrees(atoi(param));
270 int main(int argc, char *argv[])
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");
278 printf("%ld selfsigned.\n", checkselfsig());
279 printf("%ld distinct keys.\n", hashelements());