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).
19 struct ll *finished = NULL;
20 struct ll *trees = NULL;
22 unsigned long hex2long(char *string)
28 for (loop = 0; loop < 8 && loop < strlen(string) && string[loop] > ' ';
30 value=((string[loop]>'9') ? toupper(string[loop])-'A'+10 :
31 string[loop]-'0')+(value << 4);
37 int keycmp(struct key *key1, struct key *key2)
39 if (key1->keyid==key2->keyid) {
46 struct ll *addkey(struct ll *curkey, struct key newkey)
48 return lladd(curkey, copyandaddtohash(newkey));
52 void initcolour(int pi) {
56 /* Init the colour/pi hashes */
57 for (loop=0; loop<HASHSIZE; loop++) {
58 curkey = gethashtableentry(loop);
59 while (curkey!=NULL) {
60 ((struct key *)curkey->object)->colour = 0;
62 ((struct key *)curkey->object)->pi = NULL;
64 curkey = curkey->next;
70 void readkeys(const char *filename)
73 unsigned long keys=0,sigs=0,pub=0, revoked=0;
75 struct key *curkey=NULL, *cursign=NULL;
81 keyin.name=cursig.name=NULL;
82 keyin.sigs=keyin.signs=cursig.sigs=cursig.signs=NULL;
83 keyin.selfsigned=cursig.selfsigned=0;
84 keyin.revoked=cursig.revoked=0;
86 log(LOG_INFO, "Reading key info from '%s'.\n", filename);
87 if ((keyfile=fopen(filename, "r"))==NULL) {
92 fgets(curline, 1023, keyfile);
93 while (!feof(keyfile)) {
94 if (curline[0]=='P') {
97 printf("\rRead %ld keys so far.", keys);
98 keyin.keyid=hex2long(&curline[1]);
99 curkey=copyandaddtohash(keyin);
100 if (curkey->keyid!=keyin.keyid) {
101 printf("Erk! Didn't get back the key we asked for! %08lX != %08lX\n", curkey->keyid, keyin.keyid);
103 } else if (curline[0]=='S') {
104 cursig.keyid=hex2long(&curline[1]);
105 if (curkey->keyid==cursig.keyid) {
106 curkey->selfsigned=1;
109 if (!llfind(curkey->sigs, &cursig, p)) {
110 curkey->sigs=addkey(curkey->sigs, cursig);
114 if ((cursign=findinhash(&cursig))==NULL) {
115 cursign=copyandaddtohash(cursig);
117 if (cursign->keyid!=cursig.keyid) {
118 printf("Erk! Didn't get back the key we asked for! %08lX != %08lX\n", cursign->keyid, cursig.keyid);
121 if (!llfind(cursign->signs, curkey, p))
122 cursign->signs=addkey(cursign->signs, *curkey);
123 } else if (curline[0]=='N') {
124 if (curkey->name==NULL) {
125 curkey->name=strdup(&curline[1]);
126 curkey->name[strlen(curkey->name)-1]=0;
127 if (strcmp(curkey->name, "[revoked]")==0) {
133 fgets(curline, 1023, keyfile);
136 printf("\rRead %lu keys, %lu pub, %lu sigs, %lu revoked.\n",
137 keys, pub, sigs, revoked);
141 void DFSVisit(int type, struct key *key, unsigned long *time, unsigned long *depth)
149 if (type==0) curkey=key->signs; else curkey=key->sigs;
150 while (curkey!=NULL) {
151 v=(struct key *)findinhash(curkey->object);
153 printf("Couldn't find key in hash. Most odd.\n");
155 if (v!=NULL && v->colour==0) {
156 if (type==1 && key->pi==NULL) {
157 printf("key->pi is NULL.\n");
158 } else if (type==1) {
159 key->pi->object=lladd(key->pi->object, v);
164 DFSVisit(type, v, time, depth);
170 if (type==0) finished=lladd(finished, key);
176 unsigned long loop,time=0,depth,maxdepth=0;
180 for (loop=0; loop<HASHSIZE; loop++) {
181 curkey=gethashtableentry(loop);
182 while (curkey!=NULL) {
183 if (((struct key *)curkey->object)->colour==0) {
185 DFSVisit(0, ((struct key *)curkey->object),
187 if (depth>maxdepth) maxdepth=depth;
192 printf("Max depth reached in DFS(): %ld\n", maxdepth);
198 unsigned long time=0,depth,maxdepth=0;
203 while (curkey!=NULL) {
204 if (((struct key *)curkey->object)->colour==0) {
205 trees=lladd(trees, curkey->object);
206 ((struct key *)curkey->object)->pi=trees;
207 ((struct key *)curkey->object)->pi->object=lladd(NULL, curkey->object);
210 DFSVisit(1, ((struct key *)curkey->object),
212 if (depth>maxdepth) maxdepth=depth;
216 printf("Max depth reached in DFSsorted(): %ld\n", maxdepth);
224 unsigned long selfsig=0;
226 for (loop=0; loop<HASHSIZE; loop++) {
227 curkey=gethashtableentry(loop);
228 while (curkey!=NULL) {
229 if (((struct key *)curkey->object)->selfsigned) ++selfsig;
238 void printtrees(int minsize)
240 struct ll *curtree,*curkey;
241 unsigned long count, total;
245 while (curtree!=NULL) {
246 curkey=curtree->object;
249 if (llsize(curkey)>=minsize) while (curkey!=NULL) {
250 printf("0x%08lX (%s)\n", ((struct key *)curkey->object)->keyid,
251 ((struct key *)curkey->object)->name);
255 if (count>=minsize) printf("Tree size of %ld\n", count);
256 curtree=curtree->next;
258 printf("Total of %ld trees.\n", total);
262 int main(int argc, char *argv[])
264 struct key *keyinfo,foo;
267 printf("gpgstats %s by Jonathan McDowell\n", VERSION);
268 puts("Copyright 2000 Project Purple. Released under the GPL.");
269 puts("A simple program to do stats on a GPG keyring.\n");
271 readkeys("keyfile.debian");
272 printf("%ld selfsigned.\n", checkselfsig());
273 printf("%ld distinct keys.\n", hashelements());
276 printf("Starting first DFS.\n");
278 printf("Starting second DFS.\n");