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");