Prevent read_openpgp_stream from returning empty packets
[onak.git] / sixdegrees.c
1 /*
2  * sixdegrees.c - List the size of the six degrees of trust away from a key.
3  *
4  * Copyright 2001-2002 Jonathan McDowell <noodles@earth.li>
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; if not, write to the Free Software Foundation, Inc., 51
17  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "hash.h"
24 #include "keydb.h"
25 #include "keystructs.h"
26 #include "ll.h"
27 #include "log.h"
28 #include "onak-conf.h"
29 #include "stats.h"
30
31 unsigned long countdegree(struct stats_key *have, bool sigs, int maxdegree)
32 {
33         unsigned long     count = 0, curdegree = 0;
34         struct ll        *curll, *nextll, *sigll, *tmp;
35         struct stats_key *key = NULL;
36
37         ++curdegree;
38
39         nextll = NULL;
40         curll = lladd(NULL, have);
41
42         while (curll != NULL && curdegree <= maxdegree) {
43                 if (sigs) {
44                         sigll = config.dbbackend->cached_getkeysigs(
45                                 ((struct stats_key *)
46                                 curll->object)->keyid);
47                 } else {
48                         sigll = NULL;
49                         key = findinhash(((struct stats_key *)
50                                 curll->object)->keyid);
51                         if (key != NULL) {
52                                 sigll = key->signs;
53                         }
54                 }
55                 while (sigll != NULL) {
56                         if (((struct stats_key *) sigll->object)->colour==0) {
57                                 /* We've never seen it. Count it, mark it and
58                                         explore its subtree */
59                                 count++;
60                                 ((struct stats_key *)sigll->object)->colour = 
61                                         curdegree;
62                                 ((struct stats_key *)sigll->object)->parent = 
63                                         ((struct stats_key *)
64                                          curll->object)->keyid;
65                                 nextll=lladd(nextll, sigll->object);
66                         }
67                         sigll = sigll->next;
68                 }
69                 tmp = curll->next;
70                 free(curll);
71                 curll = tmp;
72                 if (curll == NULL) {
73                         curll = nextll;
74                         nextll = NULL;
75                         ++curdegree;
76                 };
77         }
78         if (curll != NULL) {
79                 llfree(curll, NULL);
80                 curll = NULL;
81         }
82         if (nextll != NULL) {
83                 llfree(nextll, NULL);
84                 nextll = NULL;
85         }
86
87         return count;
88 }
89
90 void sixdegrees(uint64_t keyid)
91 {
92         struct stats_key *keyinfo;
93         int loop;
94         long degree;
95         char *uid;
96
97         config.dbbackend->cached_getkeysigs(keyid);
98
99         if ((keyinfo = findinhash(keyid)) == NULL) {
100                 printf("Couldn't find key 0x%016" PRIX64 ".\n", keyid);
101                 return;
102         }
103
104         uid = config.dbbackend->keyid2uid(keyinfo->keyid);
105         printf("Six degrees for 0x%016" PRIX64 " (%s):\n", keyinfo->keyid,
106                         uid);
107         free(uid);
108         uid = NULL;
109
110         /*
111          * Cheat. This prefills the ->sign part of all the keys we want to
112          * look at so that we can output that info at the same time as the
113          * signers. However we're assuming that the signers and signees are
114          * reasonably closely related otherwise the info is wildly off - the
115          * only way to get 100% accurate results is to examine every key to see
116          * if it's signed by the key we're looking at.
117          */
118         initcolour(false);
119         degree = countdegree(keyinfo, true, 7);
120
121         puts("\t\tSigned by\t\tSigns");
122         for (loop = 1; loop < 7; loop++) {
123                 initcolour(false);
124                 degree = countdegree(keyinfo, true, loop);
125                 printf("Degree %d:\t%8ld", loop, degree);
126
127                 initcolour(false);
128                 degree = countdegree(keyinfo, false, loop);
129                 printf("\t\t%8ld\n", degree);
130         }
131 }
132
133 int main(int argc, char *argv[])
134 {
135         uint64_t keyid = 0x2DA8B985;
136
137         if (argc == 2) {
138                 keyid = strtoll(argv[1], NULL, 16);
139         }
140
141         readconfig(NULL);
142         initlogthing("sixdegrees", config.logfile);
143         config.dbbackend->initdb(true);
144         inithash();
145         sixdegrees(config.dbbackend->getfullkeyid(keyid));
146         destroyhash();
147         config.dbbackend->cleanupdb();
148         cleanuplogthing();
149         cleanupconfig();
150
151         return 0;
152 }