From: Jonathan McDowell <noodles@earth.li>
Date: Mon, 31 May 2004 23:46:52 +0000 (+0000)
Subject: cscvs to tla changeset 2
X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/commitdiff_plain/8e58a1769ce5e492dd68904dfc81b6e077fc2a3a

cscvs to tla changeset 2
Author: noodles
Date: 2002/09/08 09:04:54


Committing onak 0.0.2.
---

diff --git a/BUGS b/BUGS
index f84368e..df01ac3 100644
--- a/BUGS
+++ b/BUGS
@@ -1,11 +1 @@
-gpgwww:
-
-> Sometimes I just get:
-> Looking for path from 0xDF5CE2B4 to 0xB2713C8
-> Does that mean there is no path?
-
-Failing assert. Need to investigate.
-
-> And it takes forever (well it's not returned yet and I'm not really
-> expecting it to) on DF5CE2B4 to ED9547ED
-
+Nothing that isn't on the TODO list at present.
diff --git a/HISTORY b/HISTORY
index bbcf69c..e72f3df 100644
--- a/HISTORY
+++ b/HISTORY
@@ -2,3 +2,22 @@
 
 * First release.
 * Merges gpgstats 0.0.2 (never released).
+
+0.0.2 - 28th May 2002.
+
+* Added support for subpacket type 0x83 (critical key expiration)
+* Fixed bug in parsing of one byte new format packet length.
+* Added support for 4 byte old format packet lengths.
+* Changed various error statements to output to stderr instead of stdout.
+* Fixed bug in deleting keys in Postgres backend.
+* Moved code to merge a list of keys to merge.c and changed add.c to use it
+  rather than just replacing existing keys.
+* Added comment & trust packets as known but ignored types.
+* Added storage of uids to Postgres backend; this speeds up verbose indexing
+  and will also allow searching on UIDs.
+* Fixed bug in armor handling (didn't like 2 newlines before the armor header).
+* Made dearmor gracefully handle non armored input.
+* Added support for incoming incremental update mails.
+* Added searching on uids to lookup & keydb_pg.
+* Changed Postgres backend to use 64 bit keyids instead of 32 bit.
+* Made dearmor ignore CRs when looking for 2 blank lines.
diff --git a/Makefile b/Makefile
index aacd7a8..115ebe0 100644
--- a/Makefile
+++ b/Makefile
@@ -10,10 +10,10 @@ LIBS = -L/usr/local/lib -lpq
 
 PROGS = keymerge add lookup gpgwww
 OBJS = armor.o parsekey.o keydb_$(DBTYPE).o merge.o keyid.o md5.o sha.o \
-	getcgi.o keyindex.o mem.o stats.o ll.o hash.o
+	getcgi.o keyindex.o mem.o stats.o ll.o hash.o onak_conf.o
 SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha.c main.c getcgi.c stats.c \
 	keyindex.c mem.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
-	pathtest.c gpgwww.c
+	pathtest.c gpgwww.c onak_conf.c
 
 all: $(PROGS) testparse pathtest maxpath
 
@@ -30,19 +30,28 @@ gpgwww: gpgwww.o $(OBJS)
 	$(CC) -o gpgwww gpgwww.o $(OBJS) $(LIBS)
 
 lookup: lookup.o getcgi.o keyindex.o keydb_$(DBTYPE).o keyid.o sha.o \
-		parsekey.o mem.o armor.o ll.o hash.o
+		parsekey.o mem.o armor.o ll.o hash.o onak_conf.o
 	$(CC) -o lookup lookup.o getcgi.o keyindex.o keydb_$(DBTYPE).o keyid.o \
-		sha.o parsekey.o mem.o armor.o ll.o hash.o $(LIBS)
+		sha.o parsekey.o mem.o armor.o ll.o hash.o onak_conf.o $(LIBS)
 
 add: add.o getcgi.o armor.o parsekey.o keydb_$(DBTYPE).o keyid.o sha.o mem.o \
-		keyindex.o ll.o hash.o
+		keyindex.o ll.o hash.o merge.o onak_conf.o
 	$(CC) -o add add.o getcgi.o armor.o parsekey.o keydb_$(DBTYPE).o \
-		keyid.o sha.o mem.o keyindex.o ll.o hash.o $(LIBS)
+		keyid.o sha.o mem.o keyindex.o ll.o hash.o merge.o onak_conf.o \
+		$(LIBS)
 
 keymerge: keymerge.o merge.o keyid.o sha.o armor.o parsekey.o ll.o \
-		keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o
+		keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o onak_conf.o
 	$(CC) -o keymerge keymerge.o merge.o keyid.o sha.o armor.o parsekey.o \
-		keydb_$(DBTYPE).o mem.o keyindex.o ll.o hash.o getcgi.o $(LIBS)
+		keydb_$(DBTYPE).o mem.o keyindex.o ll.o hash.o getcgi.o \
+		onak_conf.o $(LIBS)
+
+onak: onak.o merge.o keyid.o sha.o armor.o parsekey.o ll.o \
+		keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o onak_conf.o
+	$(CC) -o onak onak.o merge.o keyid.o sha.o armor.o parsekey.o \
+		keydb_$(DBTYPE).o mem.o keyindex.o ll.o hash.o getcgi.o \
+		onak_conf.o $(LIBS)
+
 
 clean:
 	rm -f $(PROGS) $(OBJS) Makefile.bak testparse pathtest maxpath \
diff --git a/TODO b/TODO
index cd1005d..72dc698 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,10 @@
-* Search on key text.
 * Revoked keys on index.
 * Check keys on import?
 * Test library?
 * Better signature subpacket parsing (primary UID for example).
 * Better txt2html routine.
 * Remove bithelp.h (i386 only at present & inlined).
+  - Build and test on non-i386.
 * BSD license? (Needs md5 & sha routines rewritten/replaced then)
 * Pathfinder - graphical as well? Multiple paths?
 * Do pathlengths for similar email addresses to help aide keysigning.
@@ -14,15 +14,16 @@
 * DB access modules as a library to allow runtime configuration of it?
 * Clean up gcc warnings (`ll' length modifier especially! Also inline & wrong
   signedness for lo_read/write)
-* Webpages should bt UTF-8?
+* Webpages should be UTF-8?
 * autoconf
 * config file
-
-Must do before initial release:
-
-* Key deletion (needed for updating keys).
-* Fix output to make GPG happy with --keyserver.
+* Get all keys link for pathfinder? Or even just gpg command line to C&P.
+* logging framework so we can log debug/warning messages and so on. syslog?
+* Change over to PQescapeString in PostgreSQL backend once Woody releases.
 * Check freeing.
 * More comments.
 * Sort out merging (use keymerge + some Perl to answer incoming email. Not
   sure about keys via hkp yet though).
+* Look at db2 backend - is it db2's fault? (Well, deadlock in that the library
+  probably is...). Is there an alternative library that would provide us with
+  similar features but be more reliable? gdbm?
diff --git a/add.c b/add.c
index 323373b..d820b52 100644
--- a/add.c
+++ b/add.c
@@ -16,6 +16,7 @@
 #include "keydb.h"
 #include "keystructs.h"
 #include "parsekey.h"
+#include "merge.h"
 
 struct cgi_get_ctx {
 	char *buffer;
@@ -23,13 +24,15 @@ struct cgi_get_ctx {
 };
 
 
-int cgi_getchar(void *ctx, unsigned char *c)
+int cgi_getchar(void *ctx, size_t count, unsigned char *c)
 {
 	struct cgi_get_ctx *buf = NULL;
 
 	buf = (struct cgi_get_ctx *) ctx;
 
-	*c = buf->buffer[buf->offset++];
+	while (count-- > 0 && *c != 0) {
+		*c = buf->buffer[buf->offset++];
+	}
 
 	return (*c == 0);
 }
@@ -38,7 +41,6 @@ int main(int argc, char *argv[])
 {
 	struct openpgp_packet_list *packets = NULL;
 	struct openpgp_publickey *keys = NULL;
-	struct openpgp_publickey *curkey = NULL;
 	char **params = NULL;
 	struct cgi_get_ctx ctx;
 	int i;
@@ -52,8 +54,6 @@ int main(int argc, char *argv[])
 		}
 	}
 
-//	puts("HTTP/1.0 200 OK");
-//	puts("Server: onak 0.0.1");
 	puts("Content-Type: text/html\n");
 	puts("<html><title>onak : Add</title><body>");
 	if (ctx.buffer == NULL) {
@@ -64,18 +64,10 @@ int main(int argc, char *argv[])
 					&packets);
 		if (packets != NULL) {
 			parse_keys(packets, &keys);
-			curkey = keys;
 			initdb();
-			while (curkey != NULL) {
-				if (store_key(curkey)) {
-//					puts("Key added successfully.");
-				} else {
-					printf("Problem adding key '%s'.\n", strerror(errno));
-				}
-				curkey = curkey->next;
-			}
+			printf("Got %d new keys.\n",
+					update_keys(&keys));
 			cleanupdb();
-			puts("Keys added.");
 		} else {
 			puts("No OpenPGP packets found in input.");
 		}
diff --git a/armor.c b/armor.c
index e41cbad..d811e50 100644
--- a/armor.c
+++ b/armor.c
@@ -187,7 +187,7 @@ struct dearmor_context {
 	int curoctet;
 	int count;
 	long crc24;
-	int (*getchar_func)(void *ctx, unsigned char *c);
+	int (*getchar_func)(void *ctx, size_t count, unsigned char *c);
 	void *ctx;
 };
 
@@ -226,7 +226,7 @@ static int dearmor_getchar(void *ctx, unsigned char *c)
 	
 	tmpc = 65;
 	while (tmpc == 65) {
-		state->getchar_func(state->ctx, &tmpc);
+		state->getchar_func(state->ctx, 1, &tmpc);
 		tmpc = decode64(tmpc);
 	}
 
@@ -236,7 +236,7 @@ static int dearmor_getchar(void *ctx, unsigned char *c)
 			state->lastoctet = tmpc;
 			tmpc = 65;
 			while (tmpc == 65) {
-				state->getchar_func(state->ctx, &tmpc);
+				state->getchar_func(state->ctx, 1, &tmpc);
 				tmpc = decode64(tmpc);
 			}
 			*c = (state->lastoctet << 2) + (tmpc >> 4);
@@ -322,7 +322,8 @@ int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
  *	armored OpenPGP stream and outputs the data as a linked list of
  *	packets.
  */
-int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c),
+int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
+						unsigned char *c),
 				void *ctx,
 				struct openpgp_packet_list **packets)
 {
@@ -336,7 +337,7 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c),
 	 * with :s in them, then a blank line, then the data.
 	 */
 	state = 1;
-	while (state != 4 && !getchar_func(ctx, &curchar)) {
+	while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
 		switch (state) {
 			case 0:
 				if (curchar == '\n') {
@@ -350,7 +351,7 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c),
 					if (count == 5) {
 						state = 2;
 					}
-				} else {
+				} else if (curchar != '\n') {
 					state = 0;
 				}
 				break;
@@ -368,19 +369,21 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c),
 					if (count == 2) {
 						state = 4;
 					}
-				} else {
+				} else if (curchar != '\r') {
 					count = 0;
 				}
 				break;
 		}
 	}
 
-	dearmor_init(&dearmor_ctx);
-	dearmor_ctx.getchar_func = getchar_func;
-	dearmor_ctx.ctx = ctx;
-	read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx, packets);
-	dearmor_finish(&dearmor_ctx);
-	// TODO: Look for armor footer
+	if (state == 4) {
+		dearmor_init(&dearmor_ctx);
+		dearmor_ctx.getchar_func = getchar_func;
+		dearmor_ctx.ctx = ctx;
+		read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx, packets);
+		dearmor_finish(&dearmor_ctx);
+		// TODO: Look for armor footer
+	}
 
 	return 0;
 }
diff --git a/armor.h b/armor.h
index 63f9198..6b58a34 100644
--- a/armor.h
+++ b/armor.h
@@ -34,7 +34,8 @@ int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
  *	armored OpenPGP stream and outputs the data as a linked list of
  *	packets.
  */
-int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c),
+int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
+					unsigned char *c),
 				void *ctx,
 				struct openpgp_packet_list **packets);
 
diff --git a/gpgwww.c b/gpgwww.c
index 265422f..5f7da46 100644
--- a/gpgwww.c
+++ b/gpgwww.c
@@ -14,6 +14,7 @@
 #include "getcgi.h"
 #include "hash.h"
 #include "keydb.h"
+#include "onak_conf.h"
 #include "stats.h"
 
 void dofindpath(uint64_t have, uint64_t want, bool html)
@@ -137,7 +138,7 @@ int main(int argc, char *argv[])
 	puts("</PRE>");
 
 	puts("<HR>");
-	puts("Produced by gpgwww 0.0.1, part of onak. <A HREF=\"mailto:noodles-onak@earth.li\">Jonathan McDowell</A>");
+	puts("Produced by gpgwww " VERSION ", part of onak. <A HREF=\"mailto:noodles-onak@earth.li\">Jonathan McDowell</A>");
 	puts("</HTML>");
 
 	return EXIT_SUCCESS;
diff --git a/index.html b/index.html
deleted file mode 100644
index 3da573e..0000000
--- a/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<head><title>onak - Oh No, Another Keyserver</title></head>
-<body>
-<p>This is onak - Oh No, Another Keyserver. It is written by Jonathan McDowell
-<a href="mailto:noodles-onak@earth.li">&lt;noodles-onak@earth.li&gt;</a> and is
-currently far from finished.</p>
-<a href="pks/lookup?search=0x5B430367&op=vindex">My DSA key</a>
-<a href="pks/lookup?search=0x4DC4E7FD&op=vindex">My RSA key</a>
-</body>
-</html>
diff --git a/keydb.c b/keydb.c
index 2547b6b..a9e4cef 100644
--- a/keydb.c
+++ b/keydb.c
@@ -23,6 +23,7 @@
 #include "mem.h"
 #include "parsekey.h"
 
+#ifdef NEED_KEYID2UID
 /**
  *	keyid2uid - Takes a keyid and returns the primary UID for it.
  *	@keyid: The keyid to lookup.
@@ -53,7 +54,9 @@ char *keyid2uid(uint64_t keyid)
 		return buf;
 	}
 }
+#endif
 
+#ifdef NEED_GETKEYSIGS
 /**
  *	getkeysigs - Gets a linked list of the signatures on a key.
  *	@keyid: The keyid to get the sigs for.
@@ -75,6 +78,7 @@ struct ll *getkeysigs(uint64_t keyid)
 		}
 		free_publickey(publickey);
 	}
-	
+
 	return sigs;
 }
+#endif
diff --git a/keydb.h b/keydb.h
index ca8fdf7..9a248e3 100644
--- a/keydb.h
+++ b/keydb.h
@@ -65,6 +65,16 @@ int store_key(struct openpgp_publickey *publickey);
  */
 int delete_key(uint64_t keyid);
 
+/**
+ *	fetch_key_text - Trys to find the keys that contain the supplied text.
+ *	@search: The text to search for.
+ *	@publickey: A pointer to a structure to return the key in.
+ *
+ *	This function searches for the supplied text and returns the keys that
+ *	contain it.
+ */
+int fetch_key_text(const char *search, struct openpgp_publickey **publickey);
+
 /**
  *	keyid2uid - Takes a keyid and returns the primary UID for it.
  *	@keyid: The keyid to lookup.
diff --git a/keydb_db2.c b/keydb_db2.c
index 6aa47c0..771b2a5 100644
--- a/keydb_db2.c
+++ b/keydb_db2.c
@@ -21,9 +21,9 @@
 #include "keyindex.h"
 #include "keystructs.h"
 #include "mem.h"
+#include "onak_conf.h"
 #include "parsekey.h"
 
-#define DBDIR "/community/pgp-keyserver/db-copy"
 #define KEYDB_KEYID_BYTES 4
 
 /**
@@ -111,7 +111,8 @@ void initdb(void)
 	 */
 	db2_env.mp_size = 20 * 1024 * 1024;
 
-	ret = db_appinit(DBDIR, NULL, &db2_env, DB_INIT_MPOOL|DB_INIT_LOCK);
+	ret = db_appinit(config.db2_dbpath, NULL,
+			&db2_env, DB_INIT_MPOOL|DB_INIT_LOCK);
 	if (!ret) {
 		db2_keydbfiles = (DB **) malloc(sizeof (DB *) * db2_numdb);
 		memset(&keydbinfo, 0, sizeof(keydbinfo));
@@ -226,4 +227,6 @@ int delete_key(uint64_t keyid)
 /*
  * Include the basic keydb routines.
  */
+#define NEED_KEYID2UID 1
+#define NEED_GETKEYSIGS 1
 #include "keydb.c"
diff --git a/keydb_file.c b/keydb_file.c
index e5cf087..9784ecf 100644
--- a/keydb_file.c
+++ b/keydb_file.c
@@ -20,10 +20,9 @@
 #include "keystructs.h"
 #include "ll.h"
 #include "mem.h"
+#include "onak_conf.h"
 #include "parsekey.h"
 
-#define DBDIR "/home/noodles/onak-0.0.1/db"
-
 /**
  *	keydb_fetchchar - Fetches a char from a file.
  */
@@ -75,7 +74,8 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
 	char keyfile[1024];
 	int fd = -1;
 
-	snprintf(keyfile, 1023, "%s/0x%llX", DBDIR, keyid & 0xFFFFFFFF);
+	snprintf(keyfile, 1023, "%s/0x%llX", config.file_dbpath,
+			keyid & 0xFFFFFFFF);
 	fd = open(keyfile, O_RDONLY); // | O_SHLOCK);
 
 	if (fd > -1) {
@@ -104,7 +104,7 @@ int store_key(struct openpgp_publickey *publickey)
 	char keyfile[1024];
 	int fd = -1;
 
-	snprintf(keyfile, 1023, "%s/0x%llX", DBDIR,
+	snprintf(keyfile, 1023, "%s/0x%llX", config.file_dbpath,
 			get_keyid(publickey) & 0xFFFFFFFF);
 	fd = open(keyfile, O_WRONLY | O_CREAT, 0664); // | O_EXLOCK);
 
@@ -132,7 +132,7 @@ int delete_key(uint64_t keyid)
 {
 	char keyfile[1024];
 
-	snprintf(keyfile, 1023, "%s/0x%llX", DBDIR,
+	snprintf(keyfile, 1023, "%s/0x%llX", config.file_dbpath,
 			keyid & 0xFFFFFFFF);
 
 	return unlink(keyfile);
@@ -141,4 +141,6 @@ int delete_key(uint64_t keyid)
 /*
  * Include the basic keydb routines.
  */
+#define NEED_KEYID2UID 1
+#define NEED_GETKEYSIGS 1
 #include "keydb.c"
diff --git a/keydb_pg.c b/keydb_pg.c
index 845ec84..d2a2a55 100644
--- a/keydb_pg.c
+++ b/keydb_pg.c
@@ -25,6 +25,7 @@
 #include "keyindex.h"
 #include "keystructs.h"
 #include "mem.h"
+#include "onak_conf.h"
 #include "parsekey.h"
 
 /**
@@ -57,13 +58,13 @@ static int keydb_putchar(void *fd, unsigned char c)
  */
 void initdb(void)
 {
-	dbconn = PQsetdbLogin(NULL, // host
+	dbconn = PQsetdbLogin(config.pg_dbhost, // host
 			NULL, // port
 			NULL, // options
 			NULL, // tty
-			"noodles", // database
-			NULL,  //login
-			NULL); // password
+			config.pg_dbname, // database
+			config.pg_dbuser,  //login
+			config.pg_dbpass); // password
 
 	if (PQstatus(dbconn) == CONNECTION_BAD) {
 		fprintf(stderr, "Connection to database failed.\n");
@@ -104,39 +105,124 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
 	char *oids = NULL;
 	char statement[1024];
 	int fd = -1;
+	int i = 0;
+	int numkeys = 0;
 	Oid key_oid;
 
 	result = PQexec(dbconn, "BEGIN");
 	PQclear(result);
 	
-	snprintf(statement, 1023,
+	if (keyid > 0xFFFFFFFF) {
+		snprintf(statement, 1023,
 			"SELECT keydata FROM onak_keys WHERE keyid = '%llX'",
-			keyid & 0xFFFFFFFF);
+			keyid);
+	} else {
+		snprintf(statement, 1023,
+			"SELECT keydata FROM onak_keys WHERE keyid "
+			"LIKE '%%%llX'",
+			keyid);
+	}
 	result = PQexec(dbconn, statement);
 
-	if (PQresultStatus(result) == PGRES_TUPLES_OK &&
-			PQntuples(result) == 1) {
-		oids = PQgetvalue(result, 0, 0);
-		key_oid = (Oid) atoi(oids);
-
-		fd = lo_open(dbconn, key_oid, INV_READ);
-		if (fd < 0) {
-			fprintf(stderr, "Can't open large object.\n");
-		} else {
-			read_openpgp_stream(keydb_fetchchar, &fd, &packets);
-			parse_keys(packets, publickey);
-			lo_close(dbconn, fd);
+	if (PQresultStatus(result) == PGRES_TUPLES_OK) {
+		numkeys = PQntuples(result);
+		for (i = 0; i < numkeys && numkeys <= config.maxkeys; i++) {
+			oids = PQgetvalue(result, i, 0);
+			key_oid = (Oid) atoi(oids);
+
+			fd = lo_open(dbconn, key_oid, INV_READ);
+			if (fd < 0) {
+				fprintf(stderr, "Can't open large object.\n");
+			} else {
+				read_openpgp_stream(keydb_fetchchar, &fd,
+						&packets);
+				parse_keys(packets, publickey);
+				lo_close(dbconn, fd);
+			}
 		}
 	} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
-		fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
-				keyid);
+		fprintf(stderr, "Problem retrieving key from DB.\n");
+	}
+
+	PQclear(result);
+
+	result = PQexec(dbconn, "COMMIT");
+	PQclear(result);
+	return (numkeys);
+}
+
+/**
+ *	fetch_key_text - Trys to find the keys that contain the supplied text.
+ *	@search: The text to search for.
+ *	@publickey: A pointer to a structure to return the key in.
+ *
+ *	This function searches for the supplied text and returns the keys that
+ *	contain it.
+ */
+int fetch_key_text(const char *search, struct openpgp_publickey **publickey)
+{
+	struct openpgp_packet_list *packets = NULL;
+	PGresult *result = NULL;
+	char *oids = NULL;
+	char statement[1024];
+	int fd = -1;
+	int i = 0;
+	int numkeys = 0;
+	Oid key_oid;
+	char *dodgychar = NULL;
+
+	result = PQexec(dbconn, "BEGIN");
+	PQclear(result);
+
+	/*
+	 * TODO: We really want to use PQescapeString, but this isn't supported
+	 * by the version of Postgresql in Debian Stable. Roll on Woody and for
+	 * now kludge it.
+	 */
+	dodgychar = strchr(search, '\'');
+	while (dodgychar != NULL) {
+		*dodgychar = ' ';
+		dodgychar = strchr(search, '\'');
+	}
+	dodgychar = strchr(search, '\\');
+	while (dodgychar != NULL) {
+		*dodgychar = ' ';
+		dodgychar = strchr(search, '\\');
+	}
+
+	
+	snprintf(statement, 1023,
+			"SELECT DISTINCT onak_keys.keydata FROM onak_keys, "
+			"onak_uids WHERE onak_keys.keyid = onak_uids.keyid "
+			"AND onak_uids.uid LIKE '%%%s%%'",
+			search);
+	result = PQexec(dbconn, statement);
+
+	if (PQresultStatus(result) == PGRES_TUPLES_OK) {
+		numkeys = PQntuples(result);
+		for (i = 0; i < numkeys && numkeys <= config.maxkeys; i++) {
+			oids = PQgetvalue(result, i, 0);
+			key_oid = (Oid) atoi(oids);
+
+			fd = lo_open(dbconn, key_oid, INV_READ);
+			if (fd < 0) {
+				fprintf(stderr, "Can't open large object.\n");
+			} else {
+				read_openpgp_stream(keydb_fetchchar, &fd,
+						&packets);
+				parse_keys(packets, publickey);
+				lo_close(dbconn, fd);
+			}
+		}
+	} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
+		fprintf(stderr, "Problem retrieving key from DB.\n");
 	}
 
 	PQclear(result);
 
 	result = PQexec(dbconn, "COMMIT");
 	PQclear(result);
-	return (fd > -1);
+	return (numkeys);
 }
 
 /**
@@ -157,6 +243,10 @@ int store_key(struct openpgp_publickey *publickey)
 	char statement[1024];
 	Oid key_oid;
 	int fd;
+	char **uids = NULL;
+	char *primary = NULL;
+	char *dodgychar = NULL;
+	int i;
 
 
 	/*
@@ -189,7 +279,7 @@ int store_key(struct openpgp_publickey *publickey)
 	snprintf(statement, 1023, 
 			"INSERT INTO onak_keys (keyid, keydata) VALUES "
 			"('%llX', '%d')", 
-			get_keyid(publickey) & 0xFFFFFFFF,
+			get_keyid(publickey),
 			key_oid);
 	result = PQexec(dbconn, statement);
 
@@ -199,6 +289,45 @@ int store_key(struct openpgp_publickey *publickey)
 	}
 	PQclear(result);
 
+	uids = keyuids(publickey, &primary);
+	if (uids != NULL) {
+		for (i = 0; uids[i] != NULL; i++) {
+			/*
+			 * TODO: We really want to use PQescapeString, but this
+			 * isn't supported by the version of Postgresql in
+			 * Debian Stable. Roll on Woody and for now kludge it.
+			 */
+			dodgychar = strchr(uids[i], '\'');
+			while (dodgychar != NULL) {
+				*dodgychar = ' ';
+				dodgychar = strchr(uids[i], '\'');
+			}
+			dodgychar = strchr(uids[i], '\\');
+				while (dodgychar != NULL) {
+				*dodgychar = ' ';
+				dodgychar = strchr(uids[i], '\\');
+			}
+
+			snprintf(statement, 1023,
+				"INSERT INTO onak_uids (keyid, uid, pri) "
+				"VALUES	('%llX', '%s', '%c')",
+				get_keyid(publickey),
+				uids[i],
+				(uids[i] == primary) ? 't' : 'f');
+			result = PQexec(dbconn, statement);
+
+			if (PQresultStatus(result) != PGRES_COMMAND_OK) {
+				fprintf(stderr, "Problem storing key in DB.\n");
+				fprintf(stderr, "%s\n",
+						PQresultErrorMessage(result));
+			}
+			/*
+			 * TODO: Check result.
+			 */
+			PQclear(result);
+		}
+	}
+
 	result = PQexec(dbconn, "COMMIT");
 	PQclear(result);
 	
@@ -218,6 +347,7 @@ int delete_key(uint64_t keyid)
 	char *oids = NULL;
 	char statement[1024];
 	int found = 1;
+	int i;
 	Oid key_oid;
 
 	result = PQexec(dbconn, "BEGIN");
@@ -225,19 +355,29 @@ int delete_key(uint64_t keyid)
 	
 	snprintf(statement, 1023,
 			"SELECT keydata FROM onak_keys WHERE keyid = '%llX'",
-			keyid & 0xFFFFFFFF);
+			keyid);
 	result = PQexec(dbconn, statement);
 
-	if (PQresultStatus(result) == PGRES_TUPLES_OK &&
-			PQntuples(result) == 1) {
+	if (PQresultStatus(result) == PGRES_TUPLES_OK) {
 		found = 0;
-		oids = PQgetvalue(result, 0, 0);
-		key_oid = (Oid) atoi(oids);
-		lo_unlink(dbconn, key_oid);
+		i = PQntuples(result);
+		while (i > 0) {
+			oids = PQgetvalue(result, i-1, 0);
+			key_oid = (Oid) atoi(oids);
+			lo_unlink(dbconn, key_oid);
+			i--;
+		}
+		PQclear(result);
+
+		snprintf(statement, 1023,
+			"DELETE FROM onak_keys WHERE keyid = '%llX'",
+			keyid);
+		result = PQexec(dbconn, statement);
 		PQclear(result);
+
 		snprintf(statement, 1023,
-			"DELETE * FROM onak_keys WHERE keyid = '%llX'",
-			keyid & 0xFFFFFFFF);
+			"DELETE FROM onak_uids WHERE keyid = '%llX'",
+			keyid);
 		result = PQexec(dbconn, statement);
 	} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
 		fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
@@ -251,7 +391,43 @@ int delete_key(uint64_t keyid)
 	return (found);
 }
 
+/**
+ *	keyid2uid - Takes a keyid and returns the primary UID for it.
+ *	@keyid: The keyid to lookup.
+ */
+char *keyid2uid(uint64_t keyid)
+{
+	PGresult *result = NULL;
+	char statement[1024];
+	char *uid = NULL;
+
+	snprintf(statement, 1023,
+		"SELECT uid FROM onak_uids WHERE keyid = '%llX' AND pri = 't'",
+		keyid);
+	result = PQexec(dbconn, statement);
+
+	/*
+	 * Technically we only expect one response to the query; a key only has
+	 * one primary ID. Better to return something than nothing though.
+	 *
+	 * TODO: Log if we get more than one response? Needs logging framework
+	 * first though.
+	 */
+	if (PQresultStatus(result) == PGRES_TUPLES_OK &&
+			PQntuples(result) >= 1) {
+		uid = strdup(PQgetvalue(result, 0, 0));
+	} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
+		fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
+				keyid);
+	}
+
+	PQclear(result);
+
+	return uid;
+}
+
 /*
  * Include the basic keydb routines.
  */
+#define NEED_GETKEYSIGS 1
 #include "keydb.c"
diff --git a/keyid.c b/keyid.c
index 5252e81..8131e16 100644
--- a/keyid.c
+++ b/keyid.c
@@ -81,7 +81,8 @@ uint64_t get_keyid(struct openpgp_publickey *publickey)
 
 		break;
 	default:
-		printf("Unknown key type: %d\n", publickey->publickey->data[0]);
+		fprintf(stderr, "Unknown key type: %d\n",
+				publickey->publickey->data[0]);
 	}
 
 	return keyid;
diff --git a/keyindex.c b/keyindex.c
index 2c4e24c..dfa0d44 100644
--- a/keyindex.c
+++ b/keyindex.c
@@ -55,12 +55,17 @@ int parse_subpackets(unsigned char *data, bool html)
 			 */
 			break;
 		case 16:
-			uid = keyid2uid((data[offset+packetlen - 4] << 24) +
-	                                (data[offset+packetlen - 3] << 16) +
-	                                (data[offset+packetlen - 2] << 8) +
-	                                data[offset+packetlen - 1]);
+			uid = keyid2uid(
+				((uint64_t) data[offset+packetlen - 8] << 56) +
+				((uint64_t) data[offset+packetlen - 7] << 48) +
+				((uint64_t) data[offset+packetlen - 6] << 40) +
+				((uint64_t) data[offset+packetlen - 5] << 32) +
+				((uint64_t) data[offset+packetlen - 4] << 24) +
+				((uint64_t) data[offset+packetlen - 3] << 16) +
+				((uint64_t) data[offset+packetlen - 2] << 8) +
+				data[offset+packetlen - 1]);
 			if (html && uid != NULL) {
-				printf("sig        <a href=\"lookup?op=get&"
+				printf("sig         <a href=\"lookup?op=get&"
 					"search=%02X%02X%02X%02X\">"
 					"%02X%02X%02X%02X</a>             "
 					"<a href=\"lookup?op=vindex&"
@@ -81,7 +86,7 @@ int parse_subpackets(unsigned char *data, bool html)
 					data[offset+packetlen - 1],
 					txt2html(uid));
 			} else if (html && uid == NULL) {
-				printf("sig        "
+				printf("sig         "
 					"%02X%02X%02X%02X             "
 					"[User id not found]\n",
 					data[offset+packetlen - 4],
@@ -89,7 +94,7 @@ int parse_subpackets(unsigned char *data, bool html)
 					data[offset+packetlen - 2],
 					data[offset+packetlen - 1]);
 			} else {
-				printf("sig        %02X%02X%02X%02X"
+				printf("sig         %02X%02X%02X%02X"
 						"             %s\n",
 					data[offset+packetlen - 4],
 					data[offset+packetlen - 3],
@@ -122,12 +127,17 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
 		switch (sigs->packet->data[0]) {
 		case 2:
 		case 3:
-			uid = keyid2uid((sigs->packet->data[11] << 24) +
-	                                (sigs->packet->data[12] << 16) +
-	                                (sigs->packet->data[13] << 8) +
-	                                sigs->packet->data[14]);
+			uid = keyid2uid(
+				((uint64_t) sigs->packet->data[7] << 56) +
+				((uint64_t) sigs->packet->data[8] << 48) +
+				((uint64_t) sigs->packet->data[9] << 40) +
+				((uint64_t) sigs->packet->data[10] << 32) +
+				((uint64_t) sigs->packet->data[11] << 24) +
+				((uint64_t) sigs->packet->data[12] << 16) +
+				((uint64_t) sigs->packet->data[13] << 8) +
+				sigs->packet->data[14]);
 			if (html && uid != NULL) {
-				printf("sig        <a href=\"lookup?op=get&"
+				printf("sig         <a href=\"lookup?op=get&"
 					"search=%02X%02X%02X%02X\">"
 					"%02X%02X%02X%02X</a>             "
 					"<a href=\"lookup?op=vindex&"
@@ -148,7 +158,7 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
 					sigs->packet->data[14],
 					txt2html(uid));
 			} else if (html && uid == NULL) {
-				printf("sig        %02X%02X%02X%02X"
+				printf("sig         %02X%02X%02X%02X"
 					"             "
 					"[User id not found]\n",
 					sigs->packet->data[11],
@@ -156,7 +166,7 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
 					sigs->packet->data[13],
 					sigs->packet->data[14]);
 			} else {
-				printf("sig        %02X%02X%02X%02X"
+				printf("sig         %02X%02X%02X%02X"
 						"             %s\n",
 					sigs->packet->data[11],
 					sigs->packet->data[12],
@@ -189,10 +199,10 @@ int list_uids(struct openpgp_signedpacket_list *uids, bool verbose, bool html)
 			snprintf(buf, 1023, "%.*s",
 				(int) uids->packet->length,
 				uids->packet->data);
-			printf("uid                            %s\n",
+			printf("uid                             %s\n",
 				(html) ? txt2html(buf) : buf);
 		} else if (uids->packet->tag == 17) {
-			printf("uid                            "
+			printf("uid                             "
 				"[photo id]\n");
 		}
 		if (verbose) {
@@ -252,7 +262,7 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
 				keys->publickey->data[0]);
 		}
 		
-		printf("pub  %4d%c/%08X %04d/%02d/%02d ",
+		printf("pub  %5d%c/%08X %04d/%02d/%02d ",
 			length,
 			(type == 1) ? 'R' : ((type == 17) ? 'D' : '?'),
 			(uint32_t) (get_keyid(keys) & 0xFFFFFFFF),
@@ -267,7 +277,6 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
 				curuid->packet->data);
 			printf("%s\n", (html) ? txt2html(buf) : buf);
 			if (verbose) {
-
 				list_sigs(curuid->sigs, html);
 			}
 			curuid = curuid->next;
@@ -321,12 +330,27 @@ int get_subpackets_keyid(unsigned char *data, uint64_t *keyid)
 			 * Signature creation time. Might want to output this?
 			 */
 			break;
+		case 0x83:
+			/*
+			 * Signature expiration time. Might want to output this?
+			 */
+			break;
 		case 16:
-			*keyid = (data[offset+packetlen - 4] << 24) +
-				(data[offset+packetlen - 3] << 16) +
-				(data[offset+packetlen - 2] << 8) +
-				data[offset+packetlen - 1];
-			*keyid &= 0xFFFFFFFF;
+			*keyid = data[offset+packetlen - 8];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 7];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 6];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 5];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 4];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 3];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 2];
+			*keyid <<= 8;
+			*keyid += data[offset+packetlen - 1];
 			break;
 		default:
 			/*
@@ -362,11 +386,21 @@ struct ll *keysigs(struct ll *curll,
 		switch (sigs->packet->data[0]) {
 		case 2:
 		case 3:
-			keyid = sigs->packet->data[11] << 24;
-			keyid += (sigs->packet->data[12] << 16);
-			keyid += (sigs->packet->data[13] << 8);
+			keyid = sigs->packet->data[7];
+			keyid <<= 8;
+			keyid += sigs->packet->data[8];
+			keyid <<= 8;
+			keyid += sigs->packet->data[9];
+			keyid <<= 8;
+			keyid += sigs->packet->data[10];
+			keyid <<= 8;
+			keyid += sigs->packet->data[11];
+			keyid <<= 8;
+			keyid += sigs->packet->data[12];
+			keyid <<= 8;
+			keyid += sigs->packet->data[13];
+			keyid <<= 8;
 			keyid += sigs->packet->data[14];
-			keyid &= 0xFFFFFFFF;
 			break;
 		case 4:
 			length = get_subpackets_keyid(&sigs->packet->data[4],
@@ -386,3 +420,59 @@ struct ll *keysigs(struct ll *curll,
 
 	return curll;
 }
+
+/*
+ * TODO: Abstract out; all our linked lists should be generic and then we can
+ * llsize them.
+ */
+int spsize(struct openpgp_signedpacket_list *list)
+{
+	int size = 0;
+	struct openpgp_signedpacket_list *cur;
+
+	for (cur = list; cur != NULL; cur = cur->next, size++) ;
+
+	return size;
+}
+
+/**
+ *	keyuids - Takes a key and returns an array of its UIDs
+ *	@key: The key to get the uids of.
+ *	@primary: A pointer to store the primary UID in.
+ *
+ *	keyuids takes a public key structure and builds an array of the UIDs 
+ *	on the key. It also attempts to work out the primary UID and returns a
+ *	separate pointer to that particular element of the array.
+ */
+char **keyuids(struct openpgp_publickey *key, char **primary)
+{
+	struct openpgp_signedpacket_list *curuid = NULL;
+	char buf[1024];
+	char **uids = NULL;
+	int count = 0;
+
+	if (key != NULL && key->uids != NULL) {
+		uids = malloc((spsize(key->uids) + 1) * sizeof (char *));
+	
+		curuid = key->uids;
+		while (curuid != NULL) {
+			buf[0] = 0;
+			if (curuid->packet->tag == 13) {
+				snprintf(buf, 1023, "%.*s",
+						(int) curuid->packet->length,
+						curuid->packet->data);
+				uids[count++] = strdup(buf);
+			}
+			curuid = curuid -> next;
+		}
+		uids[count] = NULL;
+	}
+	/*
+	 * TODO: Parse subpackets for real primary ID (v4 keys)
+	 */
+	if (primary != NULL) {
+		*primary = uids[0];
+	}
+
+	return uids;
+}
diff --git a/keyindex.h b/keyindex.h
index 81b0287..5b567bc 100644
--- a/keyindex.h
+++ b/keyindex.h
@@ -37,4 +37,15 @@ int key_index(struct openpgp_publickey *keys, bool verbose,
 struct ll *keysigs(struct ll *curll,
 		struct openpgp_packet_list *sigs);
 
+/**
+ *	keyuids - Takes a key and returns an array of its UIDs
+ *	@key: The key to get the uids of.
+ *	@primary: A pointer to store the primary UID in.
+ *
+ *	keyuids takes a public key structure and builds an array of the UIDs 
+ *	on the key. It also attempts to work out the primary UID and returns a
+ *	separate pointer to that particular element of the array.
+ */
+char **keyuids(struct openpgp_publickey *key, char **primary);
+
 #endif
diff --git a/keymerge.c b/keymerge.c
index 09d71fc..fb95c2d 100644
--- a/keymerge.c
+++ b/keymerge.c
@@ -17,11 +17,15 @@
 #include "merge.h"
 #include "parsekey.h"
 
-int stdin_getchar(void *ctx, unsigned char *c)
+int stdin_getchar(void *ctx, size_t count, unsigned char *c)
 {
 	int ic;
-	ic = getchar();
-	*c = ic;
+
+	do {
+		ic = getchar();
+		*c = ic;
+		c++;
+	} while ((ic != EOF) && (--count > 0));
 	return (ic == EOF);
 }
 
@@ -36,54 +40,22 @@ int main(int argc, char *argv[])
 	struct openpgp_packet_list	*packets = NULL;
 	struct openpgp_packet_list	*list_end = NULL;
 	struct openpgp_publickey	*keys = NULL;
-	struct openpgp_publickey	*prev = NULL;
-	struct openpgp_publickey	*curkey = NULL;
-	struct openpgp_publickey	*oldkey = NULL;
-	int				 newkeys = 0;
 	int				 rc = EXIT_SUCCESS;
 
 	dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
-	parse_keys(packets, &keys);
-	free_packet_list(packets);
-	packets = NULL;
-
-	initdb();
-	for (curkey = keys; curkey != NULL; curkey = curkey->next) {
-		fprintf(stderr, "Dealing with key.\n");
-		fprintf(stderr, "fetch_key: %d\n",
-				fetch_key(get_keyid(curkey), &oldkey));
+	if (packets != NULL) {
+		parse_keys(packets, &keys);
+		free_packet_list(packets);
+		packets = NULL;
 
-		/*
-		 * If we already have the key stored in the DB then merge it
-		 * with the new one that's been supplied. Otherwise the key
-		 * we've just got is the one that goes in the DB and also the
-		 * one that we send out.
-		 */
-		if (oldkey != NULL) {
-			fprintf(stderr, "merge_keys: %d\n",
-					merge_keys(oldkey, curkey));
-			if (curkey->revocations == NULL &&
-					curkey->uids == NULL &&
-					curkey->subkeys == NULL) {
-				fprintf(stderr, "No new info.\n");
-				if (prev == NULL) {
-					keys = curkey->next;
-				} else {
-					prev->next = curkey->next;
-					prev = curkey->next;
-				}
-			} else {
-				prev = curkey;
-			}
-			/* TODO: store_key(oldkey); */
-			free_publickey(oldkey);
-			oldkey = NULL;
-		} else {
-			store_key(curkey);
-			newkeys++;
-		}
+		initdb();
+		fprintf(stderr, "Got %d new keys.\n",
+				update_keys(&keys));
+		cleanupdb();
+	} else {
+		rc = 1;
+		fprintf(stderr, "No keys read.\n");
 	}
-	cleanupdb();
 
 	if (keys != NULL) {
 		flatten_publickey(keys, &packets, &list_end);
@@ -95,6 +67,7 @@ int main(int argc, char *argv[])
 		packets = NULL;
 	} else {
 		rc = 1;
+		fprintf(stderr, "No changes.\n");
 	}
 
 	return rc;
diff --git a/keys/x509/pks-mail.2002.05.18.05.24.06.17245 b/keys/x509/pks-mail.2002.05.18.05.24.06.17245
new file mode 100644
index 0000000..5c5bad6
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.18.05.24.06.17245
@@ -0,0 +1,119 @@
+From jharris@skylane.kjsl.com Sat May 18 05:24:06 2002
+Received: from skylane.kjsl.com ([206.55.228.139])
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 178vlF-0004Tt-00
+	for <pgp-public-keys@the.earth.li>; Sat, 18 May 2002 05:24:06 +0100
+Received: (from pks@localhost)
+	by skylane.kjsl.com (8.11.6/8.11.6) id g4I4O1q59256;
+	Fri, 17 May 2002 21:24:01 -0700 (PDT)
+	(envelope-from jharris)
+Date: Fri, 17 May 2002 21:24:01 -0700 (PDT)
+Message-Id: <200205180424.g4I4O1q59256@skylane.kjsl.com>
+X-Authentication-Warning: skylane.kjsl.com: pks set sender to jharris using -f
+To: pgp-public-keys@blackhole.pca.dfn.de, pgp-public-keys@palunko.srce.hr,
+   pgp-public-keys@keys.cz.pgp.net, pgp-public-keys@pks.pgp.dk,
+   pgp-public-keys@keyserver.ch, pgp-public-keys@lorien.prato.linux.it,
+   pgp-public-keys@korell.cc.gatech.edu, pgp-public-keys@dir2.es.net,
+   pgp-public-keys@nicpgp1.nic.ad.jp, pgp-public-keys@pgp.rediris.es,
+   pgp-public-keys@pgp.uk.demon.net, pgp-public-keys@pgp.zdv.uni-mainz.de,
+   pgp-public-keys@the.earth.li, pgp-public-keys@uni-paderborn.de
+From: Jason Harris <jharris@widomaker.com>
+Subject: incremental
+X-KeyServer-Sent: pgp-public-keys@keys.nl.pgp.net
+X-KeyServer-Sent: pgp-public-keys@pgp.dtype.org
+X-KeyServer-Sent: pgp-public-keys@pgp.mit.edu
+X-KeyServer-Sent: pgp-public-keys@kjsl.com
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2+JHpatch1
+
+mQQPAzzDIPAAAAEgALeIKZQW/fIGILAcWgZyBWp6PaVsf++ftvQ+cJygelk+KJyp
+AKNCFJLXBZknlPYl+FMBszmjAjNlS/g/hdVHqL6VqjioO5WPvaILdq9fwGR8PLWt
+e2acT0YOKr8obPZCgZU4pr6JF9FKyqNvmPHigMnva8AbQz9hO1a6EtSI/EGKzp24
+UOjdGthS9KLfFhEOk7piAJVyt+HTZKpYrPLf+ebKag0BLZ1NGMZguvNBZr1Q5x0Z
+fr+hVoUR/wKOEABqS4uWrgslbMDLe7O4gdz3dzaLoxPTfqAQVFkdUInaClUWTqg9
+H9oleDvBzgte7isfPCsEAXJOzH02jXYWUvm1ZVYvD91nG3sM8YvM5d2LY4wu+OWd
+zJgIHqqyj4PG1HNg57uF/3nR0lfp36Hq48scfQLvmaGA9O+i2S0dQ0ZT5REmoSwx
+di8GZGj6dp6vxec6l/U+0ijOVXo0FEpx4z5kekVmixAtA2C6GDZzQqa/TgXmRU57
+8WV+U9ipsNwAWtY7XJV3FuTzzTchF482y+HVFRVeiqAbTU1Hioo17NdSrx648sQS
+cN4KOmqlhVXqCpzHDo4igvqGmV0Zz0ZyKWdZXINxAwMdUaJsexgC9B+Rbze6Vl7k
+HiTCpZr863JyjXYtmgbPHXSpL+lVRxid6pFnNBvl0G9XZM/BxpK8GDlDaKSbdDjB
+EEuaVvBCxe3oAHWy9QcUf/4UfRY4YXGeuRIrdlFtdV8h40L5xKu73ES3mPFdmePH
+BP54g27xviWiT09ZR5P0yt1ERHvBN8W0glhI+mkq3WxcR2s3t0pLSb07NTfGbBof
+/mF4wDCX9lEmM9EwyBZ4eQEislzBTucA6pfDI+MtaZnxg5FiL6IMON6dI8/oj5U0
+wnYgQvu4q6tZ3zSnlVHz/YI6py9+PMc0qyaeLqH51zZueuGNY5K/d3Y0NaCKKGGz
+DQFoM7iboXPoIaVN9gHbsV8Vy82doP2oyiGH+cKpXwGFd1DOkCqNfk40erchZEX7
+NM8eXOoec9vKTDY439N/aUEiokUe2H2zKDgtVeTrrhUvZ2fS+J3GO8LjpSaGX5hp
+92LhNZEVN5+ZwCpyXt0a5sQBA9twfJmL0dXgjDlF4WPb6CJGjh4+o0NIwnIeTBCa
+2gLmT+C6W6mOA6/hW2plEiALjgPQfS2obcvg4Dem82mZhVEAid5B7z1Aci6g384a
+DfVIRT41vR6JcE5TijcN1lIiguo6ZR6oWNSM+aCbFa5Dbs8zh2PmbSPIZszfsnr0
+Eo9PbSTx5T7dViZA1lZQZ1M6Q5JOKOrDWCon/FDFiOHTa9ZntvAAYuPIFnGvYPsP
+6XId5jBEC00qP6h96VQeeInyDyYDdimHqpL3upMAEQEAAbQhQXJteVJlZExlZyA8
+cmVkbGVnQG15cmVhbGJveC5jb20+iQssBBBkAQsfBQI8wyDwBQMDwmcAAhsByk5k
+AQEEMIILBjCCBu6gAwIBAgIBATANBgkqhkiG9w0BAQQFADBqMQswCQYDVQQGEwJV
+UzETMBEGA1UEChMKU2VjdXJlQ29tcDENMAsGA1UECxMEUkF0TTESMBAGA1UEAxQJ
+UmVkTGVnX1NBMSMwIQYJKoZIhvcNAQkBFhRyZWRsZWdAbXlyZWFsYm94LmNvbTAe
+Fw0wMjA0MjEyMDI4MzJaFw0wNDA0MjAyMDI4MzJaMGsxCzAJBgNVBAYTAlVTMRMw
+EQYDVQQKEwpTZWN1cmVDb21wMQ0wCwYDVQQLEwRSQXRNMRMwEQYDVQQDEwpBcm15
+UmVkTGVnMSMwIQYJKoZIhvcNAQkBFhRyZWRsZWdAbXlyZWFsYm94LmNvbTCCBCIw
+DQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBALeIKZQW/fIGILAcWgZyBWp6PaVs
+f++ftvQ+cJygelk+KJypAKNCFJLXBZknlPYl+FMBszmjAjNlS/g/hdVHqL6Vqjio
+O5WPvaILdq9fwGR8PLWte2acT0YOKr8obPZCgZU4pr6JF9FKyqNvmPHigMnva8Ab
+Qz9hO1a6EtSI/EGKzp24UOjdGthS9KLfFhEOk7piAJVyt+HTZKpYrPLf+ebKag0B
+LZ1NGMZguvNBZr1Q5x0Zfr+hVoUR/wKOEABqS4uWrgslbMDLe7O4gdz3dzaLoxPT
+fqAQVFkdUInaClUWTqg9H9oleDvBzgte7isfPCsEAXJOzH02jXYWUvm1ZVYvD91n
+G3sM8YvM5d2LY4wu+OWdzJgIHqqyj4PG1HNg57uF/3nR0lfp36Hq48scfQLvmaGA
+9O+i2S0dQ0ZT5REmoSwxdi8GZGj6dp6vxec6l/U+0ijOVXo0FEpx4z5kekVmixAt
+A2C6GDZzQqa/TgXmRU578WV+U9ipsNwAWtY7XJV3FuTzzTchF482y+HVFRVeiqAb
+TU1Hioo17NdSrx648sQScN4KOmqlhVXqCpzHDo4igvqGmV0Zz0ZyKWdZXINxAwMd
+UaJsexgC9B+Rbze6Vl7kHiTCpZr863JyjXYtmgbPHXSpL+lVRxid6pFnNBvl0G9X
+ZM/BxpK8GDlDaKSbdDjBEEuaVvBCxe3oAHWy9QcUf/4UfRY4YXGeuRIrdlFtdV8h
+40L5xKu73ES3mPFdmePHBP54g27xviWiT09ZR5P0yt1ERHvBN8W0glhI+mkq3Wxc
+R2s3t0pLSb07NTfGbBof/mF4wDCX9lEmM9EwyBZ4eQEislzBTucA6pfDI+MtaZnx
+g5FiL6IMON6dI8/oj5U0wnYgQvu4q6tZ3zSnlVHz/YI6py9+PMc0qyaeLqH51zZu
+euGNY5K/d3Y0NaCKKGGzDQFoM7iboXPoIaVN9gHbsV8Vy82doP2oyiGH+cKpXwGF
+d1DOkCqNfk40erchZEX7NM8eXOoec9vKTDY439N/aUEiokUe2H2zKDgtVeTrrhUv
+Z2fS+J3GO8LjpSaGX5hp92LhNZEVN5+ZwCpyXt0a5sQBA9twfJmL0dXgjDlF4WPb
+6CJGjh4+o0NIwnIeTBCa2gLmT+C6W6mOA6/hW2plEiALjgPQfS2obcvg4Dem82mZ
+hVEAid5B7z1Aci6g384aDfVIRT41vR6JcE5TijcN1lIiguo6ZR6oWNSM+aCbFa5D
+bs8zh2PmbSPIZszfsnr0Eo9PbSTx5T7dViZA1lZQZ1M6Q5JOKOrDWCon/FDFiOHT
+a9ZntvAAYuPIFnGvYPsP6XId5jBEC00qP6h96VQeeInyDyYDdimHqpL3upMCAwEA
+AaOCAbQwggGwMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgSwMAsGA1UdDwQE
+AwIF4DAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh
+dGUwHQYDVR0OBBYEFKrBJ8nQGmYSF+p22FKlAgNicnWBMIGRBgNVHSMEgYkwgYaA
+FKASfUQJzfMx7zcWxLwSzgvR/1n/oWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UE
+ChMKU2VjdXJlQ29tcDENMAsGA1UECxMEUkF0TTEPMA0GA1UEAxMGUmVkTGVnMSMw
+IQYJKoZIhvcNAQkBFhRyZWRsZWdAbXlyZWFsYm94LmNvbYIBATAfBgNVHREEGDAW
+gRRyZWRsZWdAbXlyZWFsYm94LmNvbTAfBgNVHRIEGDAWgRRyZWRsZWdAbXlyZWFs
+Ym94LmNvbTAvBglghkgBhvhCAQQEIhYgaHR0cDovL3d3dy5kb21haW4uZG9tL2Nh
+LWNybC5wZW0wLwYJYIZIAYb4QgEDBCIWIGh0dHA6Ly93d3cuZG9tYWluLmRvbS9j
+YS1jcmwucGVtMA0GCSqGSIb3DQEBBAUAA4IEAQAgMmOoeGqPwTcRM2ZfMTC75jot
+XJbrhDi84OAgEWRq3jpH7EKBSlG88vvAkAjXN4ph7P4es3A3gGkV/hbiK0CIOi1P
+ZFLIXcnhQFRlZ4hw/7ug+ppp/0ULtLoF5taySJ/LiI0Q0jv6+u3PX0pdLs+2u/Cm
+5kVlzQXyiYQCf8vaktdE1ArQ1UO1epS+bRpC5zlk3x4OOEMJZNypNMSAPlljNMsM
+c4h4otrxWXIUg4PKY78TqVRnTqVyuX3f69mWoKtYQUATRcJYMP6VCGnaAj8sbqB2
+3hXK86XiquruwDbtTLzEMTbeZyW2bGyXsEEZLgiROiNE+Mj3dz8325tBofdJ5Mye
+kZm9I9N++evASf15STZc1d56jUv4yqCFt/ufCzDbpxtkeawZVQAezpz29r8py2Vd
+Zgv0m6lXV8ui+jwqqSziDYqyJkOR9/ytSU6mGpu4qF+3n4mKCzX/WVQnNQ0nw/aN
+tl2o8adFYojfsidKEEDD0jTZhIIp8wTYFDDrSMsjxpWx3u9usuuNwvAOkM0puEmp
+YpPAuEs23RDQnmpj/K/dLwPqQ+LuUpBb9RkLN1O9vix5FnRwuW2LHfdrnfnewlBT
+EkREPhxTO2HnNuFhIdiDWtKKcRPUUGPlmrgg99IOZ7OtUhx7j/FnUm2dRWF1CGuX
+ni8f+jqFaqIvtnxB2+uwFE1fBnedPb2sKW1ClrhuwrhPn47v59W57XdVIW0wLy5h
+nI1pivoEZ6zWimqL0jtQXhak4mdwJnqNzXRsekYBWXpnkEKl8GPU4fhYAm8pIk4c
+JIWiA1z5vWlL5Nt0BV2nQH0q65Jm3q1GVZknG3QS/87QTCn0n7cUU5W72RatqAri
+PC1bTrQ1w18J0DuJzHp7D7FPtxCZG9xF5WWUniEUq9xtDVFZ2LQ+2Pezf/qSRjWw
+GDrIJZPIeGWPHddAa+uKq3bejJ4b/iUtSuvv2cdKv/k8vt00q8A0fpuRXjPJiuUr
+vYCT+1Fgu6Ax+DIUh7yoivEd6laPJ5sNejNPLr5YtORm2+4hlCST0LsB2vPGhpkr
+F3n9snog22eAvnGx/HKeiccndZH2vB2si8Da7OWIJXB/7esgJGip0n/oeXHwPLsz
+PyOQ2rhuDs3Jj71ENL7CH3i+6oW/hYLkn66ix+bOhW8SHbK8wwZkIaz0MSjLVPOS
+yJ+9dCF4lwL/ev9ywJUxeO6akANKRg1ve+L628IbZjw7anFwytQAG7bQHdffKE7U
+b4F6w1iH1YXAlZdpgEsMeAPnVCL6C6qX1pSy6zSvqhF0SXinw7uStFEMPi3XKklP
+CxZ39Px4W4lFpbKvD5Yv1FZYp5WZYifP0rWI1N2mfujaznFnGowITtmMJ6jUAAAA
+AAABAQ==
+=IOO6
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/keys/x509/pks-mail.2002.05.19.05.04.41.8604 b/keys/x509/pks-mail.2002.05.19.05.04.41.8604
new file mode 100644
index 0000000..def8b47
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.19.05.04.41.8604
@@ -0,0 +1,52 @@
+From pgp-keyserver-admin@prato.linux.it Sun May 19 05:04:41 2002
+Received: from lorien.prato.linux.it ([193.70.7.140] ident=postfix)
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 179Hw0-0002Ei-00
+	for <pgp-public-keys@the.earth.li>; Sun, 19 May 2002 05:04:41 +0100
+Received: by lorien.prato.linux.it (Postfix, from userid 1000)
+	id 2F95D33804; Sun, 19 May 2002 06:04:39 +0200 (CEST)
+To: pgp-public-keys@pgp.dtype.org, pgp-public-keys@the.earth.li
+From: PGP Key Server Administrator <pgp-keyserver-admin@keyserver.linux.it>
+Subject: incremental
+X-KeyServer-Sent: cserv@pgp.surfnet.nl
+X-KeyServer-Sent: pgp-public-keys@keys.nl.pgp.net
+X-KeyServer-Sent: pgp-public-keys@keyserver.linux.it
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+Message-Id: <20020519040439.2F95D33804@lorien.prato.linux.it>
+Date: Sun, 19 May 2002 06:04:39 +0200 (CEST)
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2
+
+mQCPAzyDd3gAAAEEAMISSUJKIz2LH3fxgvIN+9TEdpAWj5Ep5ZyruXPit/4Bxa8D
+JjifTyNN4iz88qZoR7niN1CZu8GukZ+FG0FnOWXLQMDUVjw+M34fwtE7s0kPzjb8
+NURbJWgRIA26P0wHia1qrsDgtsY2m/nYR4jjqe6rnuqegJ3IjDE+NvygTEKRABEB
+AAG0SU5PTUJSRSBSRVZJUklFR08gSEVSTkFOREVaIFJBRkFFTCAtIE5JRiAwNzg3
+NTQ3MkwgPHJhZmFlbEByZXZpcmllZ28ubmFtZT6JA/8EEGQCA/IFAjyDd3gFAwPD
+v4gCGwHDIWQBAQQwggPZMIIDQqADAgECAgQ8XE0mMA0GCSqGSIb3DQEBBQUAMDYx
+CzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9GTk1UIENsYXNl
+IDIgQ0EwHhcNMDIwMzA0MTMzMjQwWhcNMDQwMzA0MTQwMjQwWjCBhjELMAkGA1UE
+BhMCRVMxDTALBgNVBAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQTES
+MBAGA1UECxMJNTAwMDUwODk2MTowOAYDVQQDEzFOT01CUkUgUkVWSVJJRUdPIEhF
+Uk5BTkRFWiBSQUZBRUwgLSBOSUYgMDc4NzU0NzJMMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDCEklCSiM9ix938YLyDfvUxHaQFo+RKeWcq7lz4rf+AcWvAyY4
+n08jTeIs/PKmaEe54jdQmbvBrpGfhRtBZzlly0DA1FY8PjN+H8LRO7NJD842/DVE
+WyVoESANuj9MB4mtaq7A4LbGNpv52EeI46nuq57qnoCdyIwxPjb8oExCkQIDAQAB
+o4IBoTCCAZ0wKwYDVR0QBCQwIoAPMjAwMjAzMDQxMzMyNDBagQ8yMDA0MDMwNDE0
+MDI0MFowCwYDVR0PBAQDAgWgMBEGCWCGSAGG+EIBAQQEAwIFoDCBiwYDVR0RBIGD
+MIGAgRVyYWZhZWxAcmV2aXJpZWdvLm5hbWWkZzBlMRgwFgYJKwYBBAGsZgEEEwkw
+Nzg3NTQ3MmwxGDAWBgkrBgEEAaxmAQMTCWhlcm5hbmRlejEYMBYGCSsGAQQBrGYB
+AhMJcmV2aXJpZWdvMRUwEwYJKwYBBAGsZgEBEwZyYWZhZWwwWgYDVR0fBFMwUTBP
+oE2gS6RJMEcxCzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9G
+Tk1UIENsYXNlIDIgQ0ExDzANBgNVBAMTBkNSTDQyODAfBgNVHSMEGDAWgBRAmnZE
+l3QHxKwUyx6NTzpFfDDXYTAdBgNVHQ4EFgQUSy8+H3UaIcnluds8sInbPRAiriYw
+CQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNS4wAwIDqDANBgkqhkiG9w0B
+AQUFAAOBgQBHEfi+9z0G12Jn6eqY96/w4Hq0CmAcf9aZ2rKzH/KGvEoswSsp74DA
+iTYs5uBtXwkarjcB69InxtBycVhYuQkIaiQuMmlgNRWMf03mFvE685MDjnxhjRoE
+KSFLnlLsRy//M6KoLv1cflcQHrJIsf6zcewgrAeV0dMUdilsZh+COQAAAAAAAQE=
+=lBJh
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/keys/x509/pks-mail.2002.05.19.05.04.46.8629 b/keys/x509/pks-mail.2002.05.19.05.04.46.8629
new file mode 100644
index 0000000..2b3519f
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.19.05.04.46.8629
@@ -0,0 +1,59 @@
+From pks-admin@horowitz.surfnet.nl Sun May 19 05:04:46 2002
+Received: from horowitz.surfnet.nl ([194.171.167.2])
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 179Hw6-0002F8-00
+	for <pgp-public-keys@the.earth.li>; Sun, 19 May 2002 05:04:46 +0100
+Received: (from pks@localhost)
+	by horowitz.surfnet.nl (8.12.2/8.12.2) id g4J44URU012044;
+	Sun, 19 May 2002 06:04:30 +0200 (MET DST)
+Date: Sun, 19 May 2002 06:04:30 +0200 (MET DST)
+Message-Id: <200205190404.g4J44URU012044@horowitz.surfnet.nl>
+To: pgp-keys@keyserver.net, pgp-keys@szefler.com,
+   pgp-public-keys-pksd@math.uni-paderborn.de,
+   pgp-public-keys@blackhole.pca.dfn.de, pgp-public-keys@keys.cz.pgp.net,
+   pgp-public-keys@keyserver.ch, pgp-public-keys@lorien.prato.linux.it,
+   pgp-public-keys@korell.cc.gatech.edu, pgp-public-keys@pgp.dtype.org,
+   pgp-public-keys@dir2.es.net, pgp-public-keys@pgp.lsi.upc.es,
+   pgp-public-keys@nicpgp1.nic.ad.jp, pgp-public-keys@pgp.rediris.es,
+   pgp-public-keys@pgp.zdv.uni-mainz.de, pgp-public-keys@the.earth.li
+From: Server Administrator <pks-admin@keys.nl.pgp.net>
+Subject: incremental
+X-KeyServer-Sent: cserv@pgp.surfnet.nl
+X-KeyServer-Sent: pgp-public-keys@keys.nl.pgp.net
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2
+
+mQCPAzyDd3gAAAEEAMISSUJKIz2LH3fxgvIN+9TEdpAWj5Ep5ZyruXPit/4Bxa8D
+JjifTyNN4iz88qZoR7niN1CZu8GukZ+FG0FnOWXLQMDUVjw+M34fwtE7s0kPzjb8
+NURbJWgRIA26P0wHia1qrsDgtsY2m/nYR4jjqe6rnuqegJ3IjDE+NvygTEKRABEB
+AAG0SU5PTUJSRSBSRVZJUklFR08gSEVSTkFOREVaIFJBRkFFTCAtIE5JRiAwNzg3
+NTQ3MkwgPHJhZmFlbEByZXZpcmllZ28ubmFtZT6JA/8EEGQCA/IFAjyDd3gFAwPD
+v4gCGwHDIWQBAQQwggPZMIIDQqADAgECAgQ8XE0mMA0GCSqGSIb3DQEBBQUAMDYx
+CzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9GTk1UIENsYXNl
+IDIgQ0EwHhcNMDIwMzA0MTMzMjQwWhcNMDQwMzA0MTQwMjQwWjCBhjELMAkGA1UE
+BhMCRVMxDTALBgNVBAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQTES
+MBAGA1UECxMJNTAwMDUwODk2MTowOAYDVQQDEzFOT01CUkUgUkVWSVJJRUdPIEhF
+Uk5BTkRFWiBSQUZBRUwgLSBOSUYgMDc4NzU0NzJMMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDCEklCSiM9ix938YLyDfvUxHaQFo+RKeWcq7lz4rf+AcWvAyY4
+n08jTeIs/PKmaEe54jdQmbvBrpGfhRtBZzlly0DA1FY8PjN+H8LRO7NJD842/DVE
+WyVoESANuj9MB4mtaq7A4LbGNpv52EeI46nuq57qnoCdyIwxPjb8oExCkQIDAQAB
+o4IBoTCCAZ0wKwYDVR0QBCQwIoAPMjAwMjAzMDQxMzMyNDBagQ8yMDA0MDMwNDE0
+MDI0MFowCwYDVR0PBAQDAgWgMBEGCWCGSAGG+EIBAQQEAwIFoDCBiwYDVR0RBIGD
+MIGAgRVyYWZhZWxAcmV2aXJpZWdvLm5hbWWkZzBlMRgwFgYJKwYBBAGsZgEEEwkw
+Nzg3NTQ3MmwxGDAWBgkrBgEEAaxmAQMTCWhlcm5hbmRlejEYMBYGCSsGAQQBrGYB
+AhMJcmV2aXJpZWdvMRUwEwYJKwYBBAGsZgEBEwZyYWZhZWwwWgYDVR0fBFMwUTBP
+oE2gS6RJMEcxCzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9G
+Tk1UIENsYXNlIDIgQ0ExDzANBgNVBAMTBkNSTDQyODAfBgNVHSMEGDAWgBRAmnZE
+l3QHxKwUyx6NTzpFfDDXYTAdBgNVHQ4EFgQUSy8+H3UaIcnluds8sInbPRAiriYw
+CQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNS4wAwIDqDANBgkqhkiG9w0B
+AQUFAAOBgQBHEfi+9z0G12Jn6eqY96/w4Hq0CmAcf9aZ2rKzH/KGvEoswSsp74DA
+iTYs5uBtXwkarjcB69InxtBycVhYuQkIaiQuMmlgNRWMf03mFvE685MDjnxhjRoE
+KSFLnlLsRy//M6KoLv1cflcQHrJIsf6zcewgrAeV0dMUdilsZh+COQAAAAAAAQE=
+=lBJh
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/keys/x509/pks-mail.2002.05.19.05.04.55.8642 b/keys/x509/pks-mail.2002.05.19.05.04.55.8642
new file mode 100644
index 0000000..66a0029
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.19.05.04.55.8642
@@ -0,0 +1,53 @@
+From pgp@dtype.org Sun May 19 05:04:55 2002
+Received: from dtype.org ([64.71.163.201] ident=mail)
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 179HwE-0002FL-00
+	for <pgp-public-keys@the.earth.li>; Sun, 19 May 2002 05:04:55 +0100
+Received: from pgp by dtype.org with local (Exim 3.12 #1 (Debian))
+	id 179Hw3-0005l2-00; Sun, 19 May 2002 04:04:43 +0000
+To: pgp-public-keys@keys.pgp.dk, pgp-public-keys@keyserver.ch, pgp-public-keys@keyserver.linux.it, pgp-public-keys@pgp.cc.gatech.edu, pgp-public-keys@pgp.mit.edu, pgp-public-keys@pgp.uni-mainz.de, pgp-public-keys@the.earth.li
+From: PGP Key Server Administrator <dtype@dtype.org>
+Subject: incremental
+X-KeyServer-Sent: cserv@pgp.surfnet.nl
+X-KeyServer-Sent: pgp-public-keys@keys.nl.pgp.net
+X-KeyServer-Sent: pgp-public-keys@pgp.dtype.org
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+Message-Id: <E179Hw3-0005l2-00@dtype.org>
+Sender: PGP Keyserver <pgp@dtype.org>
+Date: Sun, 19 May 2002 04:04:43 +0000
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2
+
+mQCPAzyDd3gAAAEEAMISSUJKIz2LH3fxgvIN+9TEdpAWj5Ep5ZyruXPit/4Bxa8D
+JjifTyNN4iz88qZoR7niN1CZu8GukZ+FG0FnOWXLQMDUVjw+M34fwtE7s0kPzjb8
+NURbJWgRIA26P0wHia1qrsDgtsY2m/nYR4jjqe6rnuqegJ3IjDE+NvygTEKRABEB
+AAG0SU5PTUJSRSBSRVZJUklFR08gSEVSTkFOREVaIFJBRkFFTCAtIE5JRiAwNzg3
+NTQ3MkwgPHJhZmFlbEByZXZpcmllZ28ubmFtZT6JA/8EEGQCA/IFAjyDd3gFAwPD
+v4gCGwHDIWQBAQQwggPZMIIDQqADAgECAgQ8XE0mMA0GCSqGSIb3DQEBBQUAMDYx
+CzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9GTk1UIENsYXNl
+IDIgQ0EwHhcNMDIwMzA0MTMzMjQwWhcNMDQwMzA0MTQwMjQwWjCBhjELMAkGA1UE
+BhMCRVMxDTALBgNVBAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQTES
+MBAGA1UECxMJNTAwMDUwODk2MTowOAYDVQQDEzFOT01CUkUgUkVWSVJJRUdPIEhF
+Uk5BTkRFWiBSQUZBRUwgLSBOSUYgMDc4NzU0NzJMMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDCEklCSiM9ix938YLyDfvUxHaQFo+RKeWcq7lz4rf+AcWvAyY4
+n08jTeIs/PKmaEe54jdQmbvBrpGfhRtBZzlly0DA1FY8PjN+H8LRO7NJD842/DVE
+WyVoESANuj9MB4mtaq7A4LbGNpv52EeI46nuq57qnoCdyIwxPjb8oExCkQIDAQAB
+o4IBoTCCAZ0wKwYDVR0QBCQwIoAPMjAwMjAzMDQxMzMyNDBagQ8yMDA0MDMwNDE0
+MDI0MFowCwYDVR0PBAQDAgWgMBEGCWCGSAGG+EIBAQQEAwIFoDCBiwYDVR0RBIGD
+MIGAgRVyYWZhZWxAcmV2aXJpZWdvLm5hbWWkZzBlMRgwFgYJKwYBBAGsZgEEEwkw
+Nzg3NTQ3MmwxGDAWBgkrBgEEAaxmAQMTCWhlcm5hbmRlejEYMBYGCSsGAQQBrGYB
+AhMJcmV2aXJpZWdvMRUwEwYJKwYBBAGsZgEBEwZyYWZhZWwwWgYDVR0fBFMwUTBP
+oE2gS6RJMEcxCzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9G
+Tk1UIENsYXNlIDIgQ0ExDzANBgNVBAMTBkNSTDQyODAfBgNVHSMEGDAWgBRAmnZE
+l3QHxKwUyx6NTzpFfDDXYTAdBgNVHQ4EFgQUSy8+H3UaIcnluds8sInbPRAiriYw
+CQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNS4wAwIDqDANBgkqhkiG9w0B
+AQUFAAOBgQBHEfi+9z0G12Jn6eqY96/w4Hq0CmAcf9aZ2rKzH/KGvEoswSsp74DA
+iTYs5uBtXwkarjcB69InxtBycVhYuQkIaiQuMmlgNRWMf03mFvE685MDjnxhjRoE
+KSFLnlLsRy//M6KoLv1cflcQHrJIsf6zcewgrAeV0dMUdilsZh+COQAAAAAAAQE=
+=lBJh
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/keys/x509/pks-mail.2002.05.19.11.34.50.16078 b/keys/x509/pks-mail.2002.05.19.11.34.50.16078
new file mode 100644
index 0000000..9c7dcbc
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.19.11.34.50.16078
@@ -0,0 +1,53 @@
+From pgp-keyserver-admin@prato.linux.it Sun May 19 11:34:50 2002
+Received: from lorien.prato.linux.it ([193.70.7.140] ident=postfix)
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 179O1a-0004BH-00
+	for <pgp-public-keys@the.earth.li>; Sun, 19 May 2002 11:34:50 +0100
+Received: by lorien.prato.linux.it (Postfix, from userid 1000)
+	id AB4AC336CC; Sun, 19 May 2002 12:34:49 +0200 (CEST)
+To: pgp-public-keys@keys.nl.pgp.net, pgp-public-keys@the.earth.li
+From: PGP Key Server Administrator <pgp-keyserver-admin@keyserver.linux.it>
+Subject: incremental
+X-KeyServer-Sent: pgp-public-keys@pgp.mit.edu
+X-KeyServer-Sent: pgp-public-keys@pgp.dtype.org
+X-KeyServer-Sent: pgp-public-keys@keyserver.linux.it
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+Message-Id: <20020519103449.AB4AC336CC@lorien.prato.linux.it>
+Date: Sun, 19 May 2002 12:34:49 +0200 (CEST)
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2
+
+mQCPAzzPtoAAAAEEAL+/LN5t4U3d+8p5IfjYGpLI+7U4lFNynD+lISB6vgoQRv3/
+VbdafDAoJH7Bq8imILMJD8JyY720uc/cH/rRO0idpYqtgD1JPdxHevwdxMRqaTmB
+wsnBk7oKRjSetdLM+FB8FxudQt0t/5bjky53RFfeL3oBN57O2eO8UnJMCAdbABEB
+AAG0KkNsZW1lbnMgR3VldHRsZXIgPGNsZW1lbnMuZ3VldHRsZXJAd2ViLmRlPokE
+IQQQZAEEFAUCPM+2gAUDAeEzgMNGZAEBBDCCA/4wggLmoAMCAQICBACkpSYwDQYJ
+KoZIhvcNAQEEBQAwgaExCzAJBgNVBAYTAkRFMRowGAYDVQQHExFELTc2MjI3IEth
+cmxzcnVoZTESMBAGA1UEChMJV0VCLkRFIEFHMRcwFQYDVQQLEw5UcnVzdENlbnRl
+ciBDQTEsMCoGA1UEAxMjV0VCLkRFIFRydXN0Q2VudGVyIFZvbGwtWmVydGlmaWth
+dGUxGzAZBgkqhkiG9w0BCQEWDHRydXN0QHdlYi5kZTAeFw0wMjA1MDEwOTMzNTJa
+Fw0wMzA1MDEwOTMzNTJaMIGAMQswCQYDVQQGEwJERTEUMBIGA1UECBMLRGV1dHNj
+aGxhbmQxGDAWBgNVBAcTDzYxNDQ5IFN0ZWluYmFjaDEZMBcGA1UEAxMQQ2xlbWVu
+cyBHdWV0dGxlcjEmMCQGCSqGSIb3DQEJARYXY2xlbWVucy5ndWV0dGxlckB3ZWIu
+ZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL+/LN5t4U3d+8p5IfjYGpLI
++7U4lFNynD+lISB6vgoQRv3/VbdafDAoJH7Bq8imILMJD8JyY720uc/cH/rRO0id
+pYqtgD1JPdxHevwdxMRqaTmBwsnBk7oKRjSetdLM+FB8FxudQt0t/5bjky53RFfe
+L3oBN57O2eO8UnJMCAdbAgMBAAGjgeAwgd0wLAYJYIZIAYb4QgEEBB8WHWh0dHBz
+Oi8vdHJ1c3Qud2ViLmRlL3J2Q0EvP3M9MCMGCWCGSAGG+EIBAgQWFhRodHRwczov
+L3RydXN0LndlYi5kZTAWBglghkgBhvhCAQMECRYHL3J2Lz9zPTAWBglghkgBhvhC
+AQcECRYHL3JuLz9zPTAaBglghkgBhvhCAQgEDRYLL0hpbGZlL0FHQi8wKQYJYIZI
+AYb4QgENBBwWGkZyZWVtYWlsIEVtYWlsIGNlcnRpZmljYXRlMBEGCWCGSAGG+EIB
+AQQEAwIAsDANBgkqhkiG9w0BAQQFAAOCAQEAmlk1K+zdUKwE5KezT0uPZiFkLG23
+LGd49/A+Q3aRWXCuupP6EL7KzvwUyxz3HAIzMyQO4QWvzGeH3wawQwsRfWj8Wq8d
+J9V8zwsPNkL/jcjbWwi6qeoZueiBBCSc9MiO+OOpknzyH3K+C6FnOoxjANnP10ry
+WJFQf0BudmsoWWLPWOXct6A7ILYNiFbruTTI7Hk3ZkqjWvDb43RvWhLMprYcod6M
+wPgDh4t3rXyFdRz5ktBUNxVj5qnOHSYcvfgswDztv8IvUXm9aWqApvszATS+aX+Q
+mKhuT1oSvHfzXhJX0bAJZmoL65PzE87dahu6Ln0VBHzdZItzFtJtN3N7RwAAAAAA
+AQE=
+=yP81
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/keys/x509/pks-mail.2002.05.19.12.46.37.24380 b/keys/x509/pks-mail.2002.05.19.12.46.37.24380
new file mode 100644
index 0000000..586c303
--- /dev/null
+++ b/keys/x509/pks-mail.2002.05.19.12.46.37.24380
@@ -0,0 +1,69 @@
+From admin-pgp-public-keys@es.net Sun May 19 12:46:37 2002
+Received: from postal2.es.net ([198.128.3.206])
+	by the.earth.li with esmtp (Exim 3.12 #1 (Debian))
+	id 179P92-0006LB-00
+	for <pgp-public-keys@the.earth.li>; Sun, 19 May 2002 12:46:36 +0100
+Received: from ([198.128.3.122])
+        by postal2.es.net (Postal Node 2) with SMTP id GQF37091;
+        Sun, 19 May 2002 04:46:29 -0700
+Received: by dir2.es.net (LBNLMWH19/LBNLMWH11/ESOCF2) id EAA08197;
+	Sun, 19 May 2002 04:01:03 -0700 (PDT)
+Date: Sun, 19 May 2002 04:01:03 -0700 (PDT)
+Message-Id: <200205191101.EAA08197@dir2.es.net>
+X-Authentication-Warning: dir2.es.net: nispgp set sender to admin-pgp-public-keys@es.net using -f
+X-Authentication-Warning: dir2.es.net: Processed from queue /var/spool/mqueuepgp
+X-Authentication-Warning: dir2.es.net: Processed by nispgp with -C /etc/mail/sendmail.q.cf
+To: pgp-inc@dir2.es.net, pgp-public-keys@keyserver.ch,
+        pgp-public-keys@kjsl.com, pgp-public-keys@pgp.loxinfo.co.th,
+        pgp-public-keys@nicpgp1.nic.ad.jp, pgp-public-keys@pgp.rediris.es,
+        pgp-public-keys@pgp.uk.demon.net, pgp-public-keys@sunsite.icm.edu.pl,
+        pgp-public-keys@the.earth.li
+From: PGP Key Server Administrator <admin-pgp-public-keys@es.net>
+Subject: incremental
+X-KeyServer-Sent: pgp-public-keys@pgp.mit.edu
+X-KeyServer-Sent: pgp-public-keys@pgp.dtype.org
+X-KeyServer-Sent: pgp-public-keys@keys.nl.pgp.net
+X-KeyServer-Sent: pgp-public-keys@pgp.es.net
+Precedence: list
+MIME-Version: 1.0
+Content-type: application/pgp-keys
+Reply-To: keymaster@es.net
+X-Keyserver-Admin: keymaster@es.net
+Errors-To: admin-pgp-public-keys@es.net
+Sender: admin-pgp-public-keys@es.net
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 5.0
+Comment: PGP Key Server 0.9.4+patch2
+
+mQCPAzzPtoAAAAEEAL+/LN5t4U3d+8p5IfjYGpLI+7U4lFNynD+lISB6vgoQRv3/
+VbdafDAoJH7Bq8imILMJD8JyY720uc/cH/rRO0idpYqtgD1JPdxHevwdxMRqaTmB
+wsnBk7oKRjSetdLM+FB8FxudQt0t/5bjky53RFfeL3oBN57O2eO8UnJMCAdbABEB
+AAG0KkNsZW1lbnMgR3VldHRsZXIgPGNsZW1lbnMuZ3VldHRsZXJAd2ViLmRlPokE
+IQQQZAEEFAUCPM+2gAUDAeEzgMNGZAEBBDCCA/4wggLmoAMCAQICBACkpSYwDQYJ
+KoZIhvcNAQEEBQAwgaExCzAJBgNVBAYTAkRFMRowGAYDVQQHExFELTc2MjI3IEth
+cmxzcnVoZTESMBAGA1UEChMJV0VCLkRFIEFHMRcwFQYDVQQLEw5UcnVzdENlbnRl
+ciBDQTEsMCoGA1UEAxMjV0VCLkRFIFRydXN0Q2VudGVyIFZvbGwtWmVydGlmaWth
+dGUxGzAZBgkqhkiG9w0BCQEWDHRydXN0QHdlYi5kZTAeFw0wMjA1MDEwOTMzNTJa
+Fw0wMzA1MDEwOTMzNTJaMIGAMQswCQYDVQQGEwJERTEUMBIGA1UECBMLRGV1dHNj
+aGxhbmQxGDAWBgNVBAcTDzYxNDQ5IFN0ZWluYmFjaDEZMBcGA1UEAxMQQ2xlbWVu
+cyBHdWV0dGxlcjEmMCQGCSqGSIb3DQEJARYXY2xlbWVucy5ndWV0dGxlckB3ZWIu
+ZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL+/LN5t4U3d+8p5IfjYGpLI
++7U4lFNynD+lISB6vgoQRv3/VbdafDAoJH7Bq8imILMJD8JyY720uc/cH/rRO0id
+pYqtgD1JPdxHevwdxMRqaTmBwsnBk7oKRjSetdLM+FB8FxudQt0t/5bjky53RFfe
+L3oBN57O2eO8UnJMCAdbAgMBAAGjgeAwgd0wLAYJYIZIAYb4QgEEBB8WHWh0dHBz
+Oi8vdHJ1c3Qud2ViLmRlL3J2Q0EvP3M9MCMGCWCGSAGG+EIBAgQWFhRodHRwczov
+L3RydXN0LndlYi5kZTAWBglghkgBhvhCAQMECRYHL3J2Lz9zPTAWBglghkgBhvhC
+AQcECRYHL3JuLz9zPTAaBglghkgBhvhCAQgEDRYLL0hpbGZlL0FHQi8wKQYJYIZI
+AYb4QgENBBwWGkZyZWVtYWlsIEVtYWlsIGNlcnRpZmljYXRlMBEGCWCGSAGG+EIB
+AQQEAwIAsDANBgkqhkiG9w0BAQQFAAOCAQEAmlk1K+zdUKwE5KezT0uPZiFkLG23
+LGd49/A+Q3aRWXCuupP6EL7KzvwUyxz3HAIzMyQO4QWvzGeH3wawQwsRfWj8Wq8d
+J9V8zwsPNkL/jcjbWwi6qeoZueiBBCSc9MiO+OOpknzyH3K+C6FnOoxjANnP10ry
+WJFQf0BudmsoWWLPWOXct6A7ILYNiFbruTTI7Hk3ZkqjWvDb43RvWhLMprYcod6M
+wPgDh4t3rXyFdRz5ktBUNxVj5qnOHSYcvfgswDztv8IvUXm9aWqApvszATS+aX+Q
+mKhuT1oSvHfzXhJX0bAJZmoL65PzE87dahu6Ln0VBHzdZItzFtJtN3N7RwAAAAAA
+AQE=
+=yP81
+-----END PGP PUBLIC KEY BLOCK-----
+
+
diff --git a/keystructs.h b/keystructs.h
index 33dba65..10dfcc6 100644
--- a/keystructs.h
+++ b/keystructs.h
@@ -10,6 +10,7 @@
 #define __KEYSTRUCTS_H__
 
 #include <stdbool.h>
+#include <stdlib.h>
 
 /**
  *	struct openpgp_packet - Stores an OpenPGP packet.
diff --git a/lookup.c b/lookup.c
index 8f37fd2..3c55a61 100644
--- a/lookup.c
+++ b/lookup.c
@@ -18,6 +18,7 @@
 #include "keydb.h"
 #include "keyindex.h"
 #include "mem.h"
+#include "onak_conf.h"
 #include "parsekey.h"
 
 #define OP_UNKNOWN 0
@@ -34,20 +35,23 @@ void find_keys(char *search, uint64_t keyid, bool ishex,
 		bool fingerprint, bool exact, bool verbose)
 {
 	struct openpgp_publickey *publickey = NULL;
-	bool found = false;
+	int count = 0;
 
 	if (ishex) {
-		if (fetch_key(keyid, &publickey)) {
-			if (publickey != NULL) {
-				key_index(publickey, verbose, fingerprint,
-						true);
-				free_publickey(publickey);
-				found = true;
-			}
-		}
+		count = fetch_key(keyid, &publickey);
+	} else {
+		count = fetch_key_text(search, &publickey);
 	}
-	if (!found) {
+	if (publickey != NULL) {
+		key_index(publickey, verbose, fingerprint, true);
+		free_publickey(publickey);
+	} else if (count == 0) {
 		puts("Key not found.");
+	} else {
+		printf("Found %d keys, but maximum number to return is %d.\n",
+				count,
+				config.maxkeys);
+		puts("Try again with a more specific search.");
 	}
 }
 
@@ -138,7 +142,7 @@ int main(int argc, char *argv[])
 		cleanupdb();
 	}
 	puts("<hr>");
-	puts("Produced by onak 0.0.1 by Jonathan McDowell");
+	puts("Produced by onak " VERSION " by Jonathan McDowell");
 	puts("</body>\n</html>");
 	return (EXIT_SUCCESS);
 }
diff --git a/main.c b/main.c
index 1f86873..33b193d 100644
--- a/main.c
+++ b/main.c
@@ -29,26 +29,26 @@ int main(int argc, char *argv[])
 	struct openpgp_publickey *newkeys = NULL;
 	void *ctx = NULL;
 
-	fputs("Doing read_openpgp_stream():\n", stderr);
-	read_openpgp_stream(getnextchar, ctx, &packets);
+//	fputs("Doing read_openpgp_stream():\n", stderr);
+//	read_openpgp_stream(getnextchar, ctx, &packets);
 
-//	fputs("Doing dearmor_openpgp_stream():\n", stderr);
-//	dearmor_openpgp_stream(getnextchar, NULL, &packets);
-//	fputs("Doing armor_openpgp_stream():\n", stderr);
-//	armor_openpgp_stream(putnextchar, NULL, packets);
+	fputs("Doing dearmor_openpgp_stream():\n", stderr);
+	dearmor_openpgp_stream(getnextchar, NULL, &packets);
+	fputs("Doing armor_openpgp_stream():\n", stderr);
+	armor_openpgp_stream(putnextchar, NULL, packets);
 
-	fputs("Doing parse_keys():\n", stderr);
-	parse_keys(packets, &keys);
+//	fputs("Doing parse_keys():\n", stderr);
+//	parse_keys(packets, &keys);
 
-	printf("Key id is 0x%llX\n", get_keyid(keys));
+//	printf("Key id is 0x%llX\n", get_keyid(keys));
 
 //	key_index(keys, true, false, false);
 
-	initdb();
-	fetch_key(get_keyid(keys), &newkeys);
-	cleanupdb();
+//	initdb();
+//	fetch_key(get_keyid(keys), &newkeys);
+//	cleanupdb();
 
-	printf("New key id is 0x%llX\n", get_keyid(newkeys));
+//	printf("New key id is 0x%llX\n", get_keyid(newkeys));
 
 //	fputs("Doing flatten_publickey():\n", stderr);
 //	flatten_publickey(keys, &newpackets, &list_end);
diff --git a/merge.c b/merge.c
index c1410e1..96e628b 100644
--- a/merge.c
+++ b/merge.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "keydb.h"
 #include "keyid.h"
 #include "keystructs.h"
 #include "ll.h"
@@ -296,3 +297,55 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b)
 
 	return rc;
 }
+
+/**
+ *	update_keys - Takes a list of public keys and updates them in the DB.
+ *	@keys: The keys to update in the DB.
+ *
+ *	Takes a list of keys and adds them to the database, merging them with
+ *	the key in the database if it's already present there. The key list is
+ *	update to contain the minimum set of updates required to get from what
+ *	we had before to what we have now (ie the set of data that was added to
+ *	the DB). Returns the number of entirely new keys added.
+ */
+int update_keys(struct openpgp_publickey **keys)
+{
+	struct openpgp_publickey *curkey = NULL;
+	struct openpgp_publickey *oldkey = NULL;
+	struct	openpgp_publickey *prev = NULL;
+	int newkeys = 0;
+
+	for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
+		fetch_key(get_keyid(curkey), &oldkey);
+
+		/*
+		 * If we already have the key stored in the DB then merge it
+		 * with the new one that's been supplied. Otherwise the key
+		 * we've just got is the one that goes in the DB and also the
+		 * one that we send out.
+		 */
+		if (oldkey != NULL) {
+			merge_keys(oldkey, curkey);
+			if (curkey->revocations == NULL &&
+					curkey->uids == NULL &&
+					curkey->subkeys == NULL) {
+				if (prev == NULL) {
+					*keys = curkey->next;
+				} else {
+					prev->next = curkey->next;
+					prev = curkey->next;
+				}
+			} else {
+				prev = curkey;
+				store_key(oldkey);
+			}
+			free_publickey(oldkey);
+			oldkey = NULL;
+		} else {
+			store_key(curkey);
+			newkeys++;
+		}
+	}
+
+	return newkeys;
+}
diff --git a/merge.h b/merge.h
index 5abbeca..208c39b 100644
--- a/merge.h
+++ b/merge.h
@@ -25,4 +25,16 @@
  */
 int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b);
 
+/**
+ *	update_keys - Takes a list of public keys and updates them in the DB.
+ *	@keys: The keys to update in the DB.
+ *
+ *	Takes a list of keys and adds them to the database, merging them with
+ *	the key in the database if it's already present there. The key list is
+ *	update to contain the minimum set of updates required to get from what
+ *	we had before to what we have now (ie the set of data that was added to
+ *	the DB). Returns the number of entirely new keys added.
+ */
+int update_keys(struct openpgp_publickey **keys);
+
 #endif
diff --git a/onak-mail.pl b/onak-mail.pl
new file mode 100755
index 0000000..30e5b93
--- /dev/null
+++ b/onak-mail.pl
@@ -0,0 +1,66 @@
+#!/usr/bin/perl -w
+
+#
+# onak-mail.pl - Mail processing interface for onak, an OpenPGP Keyserver.
+#
+# Written by Jonathan McDowell <noodles@earth.li>
+# Copyright 2002 Project Purple
+# Released under the GPL.
+#
+
+use strict;
+use IPC::Open3;
+
+#
+# submitupdate
+#
+# Takes an armored OpenPGP stream and submits it to the keyserver. Returns the
+# difference between what we just added and what we had before (ie the least
+# data need to get from what we had to what we have).
+#
+sub submitupdate {
+	my @data = @_;
+	my (@errors, @mergedata);
+
+	open3(\*MERGEIN, \*MERGEOUT, \*MERGEERR, "/home/noodles/onak-0.0.2/keymerge");
+
+	print MERGEIN @data;
+	close MERGEIN;
+	@errors = <MERGEERR>;
+	@mergedata = <MERGEOUT>;
+
+	#print @errors;
+
+	return @mergedata;
+}
+
+my ($inheader, %syncsites, $subject, $from, $replyto, @body, @syncmail);
+
+$inheader = 1;
+$subject = "";
+
+while (<>) {
+	if ($inheader) {
+		if (/^Subject:\s*(.*)\s*$/i) {
+			$subject = $1;
+		} elsif (/^X-KeyServer-Sent:\s*(.*)\s*$/i) {
+			$syncsites{$1} = 1;
+		} elsif (/^From:\s*(.*)\s*$/i) {
+			$from = $1;
+		} elsif (/^Reply-To:\s*(.*)\s*$/i) {
+			$replyto = $1;
+		} elsif (/^$/) {
+			$inheader = 0;
+		}
+	}
+	if (!$inheader) {
+		push @body, $_;
+	}
+}
+
+# HELP, ADD, INCREMENTAL, VERBOSE INDEX <keyid>, INDEX <keyid>, GET <keyid>,
+# LAST <days>
+
+if ($subject =~ /^INCREMENTAL$/i) {
+	submitupdate(@body);
+}
diff --git a/onak.c b/onak.c
new file mode 100644
index 0000000..7b0f2f3
--- /dev/null
+++ b/onak.c
@@ -0,0 +1,71 @@
+/*
+ * onak.c - An OpenPGP keyserver.
+ *
+ * This is the main swiss army knife binary.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ * 
+ * Copyright 2002 Project Purple
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "armor.h"
+#include "keydb.h"
+#include "keyid.h"
+#include "keystructs.h"
+#include "mem.h"
+#include "merge.h"
+#include "parsekey.h"
+
+int stdin_getchar(void *ctx, size_t count, unsigned char *c)
+{
+	int ic;
+
+	do {
+		ic = getchar();
+		*c = ic;
+		c++;
+	} while ((ic != EOF) && (--count > 0));
+	return (ic == EOF);
+}
+
+int stdout_putchar(void *ctx, unsigned char c)
+{
+	return (putchar(c));
+}
+
+
+int main(int argc, char *argv[])
+{
+	struct openpgp_packet_list	*packets = NULL;
+	struct openpgp_packet_list	*list_end = NULL;
+	struct openpgp_publickey	*keys = NULL;
+	int				 rc = EXIT_SUCCESS;
+
+	read_openpgp_stream(stdin_getchar, NULL, &packets);
+	if (packets != NULL) {
+		parse_keys(packets, &keys);
+		free_packet_list(packets);
+		packets = NULL;
+
+		initdb();
+		fprintf(stderr, "Got %d new keys.\n",
+				update_keys(&keys));
+		cleanupdb();
+	} else {
+		rc = 1;
+		fprintf(stderr, "No keys read.\n");
+	}
+
+	if (keys != NULL) {
+		free_publickey(keys);
+		keys = NULL;
+	} else {
+		rc = 1;
+		fprintf(stderr, "No changes.\n");
+	}
+
+	return rc;
+}
diff --git a/onak.conf b/onak.conf
new file mode 100644
index 0000000..4b3800e
--- /dev/null
+++ b/onak.conf
@@ -0,0 +1,61 @@
+#
+# onak configuration file. Taken from pksd.conf as a starting point.
+#
+
+pks_bin_dir /community/pgp-keyserver/bin
+db_dir /community/pgp-keyserver/db
+
+### Set www_port to the port on which HTTP requests should be accepted.
+### If you do not want to process HTTP requests, set this to 0.
+
+www_port 11371
+socket_name /community/pgp-keyserver/pksd_socket
+
+### Specify the envelope sender address as the -f argument to
+###   sendmail.  This is the address which will receive any bounces.
+### If you don't use sendmail, then change this to an equivalent command.
+### If you do not want to process mail requests, leave this unset.
+
+mail_delivery_client /usr/sbin/sendmail -t -oi -fmailer-daemon
+
+### Set this to the address which should be displayed as the From: 
+###   address in all outgoing email, and as the maintainer in the body
+###   of each message.
+
+maintainer_email PGP Key Server Administrator <pgp-keyserver-admin@the.earth.li>
+mail_intro_file /community/pgp-keyserver/share/mail_intro
+help_dir /community/pgp-keyserver/share
+mail_dir /community/pgp-keyserver/incoming
+
+### If you change this, make sure to put a corresponding help file in
+### the help_dir named above
+
+default_language EN
+
+### This is the email address of this site.  It will be inserted in all
+###   outgoing incremental messages, so it should match whatever the
+###   downstream sites use as syncsite in their pksd.conf files.
+
+this_site pgp-public-keys@the.earth.li
+
+### Include a syncsite line for each site with which you are exchanging
+### incremental requests.
+
+syncsite pgp-public-keys@keys.nl.pgp.net
+syncsite pgp-public-keys@blackhole.pca.dfn.de
+syncsite pgp-public-keys@pgp.es.net
+syncsite pgp-public-keys@keyserver.linux.it
+syncsite pgp-public-keys@pgp.dtype.org
+syncsite pgp-public-keys@kjsl.com
+
+### Set this to 0 to disable mailserver LAST requests completely, to a
+### positive integer to limit LAST requests to that many days, or -1
+### to allow any argument to LAST.
+
+max_last 1
+
+### Set this to the maximum number of keys to return in the reply to
+### an index, verbose index, get, or since reply.  Setting it to -1
+### will allow any size reply.
+
+max_reply_keys 128
diff --git a/onak.sql b/onak.sql
index 6abb029..6afa737 100644
--- a/onak.sql
+++ b/onak.sql
@@ -3,16 +3,17 @@ DROP TABLE onak_uids;
 DROP TABLE onak_sigs;
 
 CREATE TABLE onak_keys (
-	keyid	char(8) NOT NULL,
+	keyid	char(16) NOT NULL,
 	keydata	oid NOT NULL
 );
 
 CREATE TABLE onak_uids (
-	keyid	char(8) NOT NULL,
-	uid	varchar(6000) NOT NULL
+	keyid	char(16) NOT NULL,
+	uid	varchar(6000) NOT NULL,
+	pri	boolean
 );
 
 CREATE TABLE onak_sigs (
-	signer	char(8) NOT NULL,
-	signee	char(8) NOT NULL
+	signer	char(16) NOT NULL,
+	signee	char(16) NOT NULL
 );
diff --git a/onak_conf.c b/onak_conf.c
new file mode 100644
index 0000000..a72d31d
--- /dev/null
+++ b/onak_conf.c
@@ -0,0 +1,39 @@
+/*
+ * onak_conf.c - Routines related to runtime config.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2002 Project Purple
+ */
+
+#include <stdlib.h>
+
+#include "onak_conf.h"
+
+/*
+ *	config - Runtime configuration for onak.
+ *
+ *	Currently this is all hardcoded, but only needs changed here. In future
+ *	it'll be read from a config file.
+ */
+struct onak_config config = {
+	128,			/* maxkeys */
+
+	/*
+	 * Options for the db2 file backend.
+	 */
+	NULL,			/* db2_dbpath */
+
+	/*
+	 * Options for the file backend.
+	 */
+	NULL,			/* file_dbpath */
+	
+	/*
+	 * Options for the Postgres backend.
+	 */
+	NULL,			/* pg_dbhost */
+	NULL,			/* pg_dbname */
+	"noodles",		/* pg_dbuser */
+	NULL,			/* pg_dbpass */
+};
diff --git a/onak_conf.h b/onak_conf.h
new file mode 100644
index 0000000..9e11167
--- /dev/null
+++ b/onak_conf.h
@@ -0,0 +1,57 @@
+/*
+ * onak_conf.h - Routines related to runtime config.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2002 Project Purple
+ */
+
+#ifndef __ONAK_CONF_H_
+#define __ONAK_CONF_H_
+
+#define VERSION "0.0.2"
+
+/*
+ *	struct onak_config - Runtime configuration for onak.
+ *	@maxkeys: The maximum number of keys a query should return.
+ *
+ * 	@db2_dbpath: The path to the directory containing the db2 files.
+ * 
+ *	@file_dbpath: The path to the flat file DB directory.
+ *
+ *	@pg_dbhost: The host that Postgres is running on.
+ *	@pg_dbname: The database name.
+ *	@pg_dbuser: The user we should connect as.
+ *	@pg_dbpass: The password for the user.
+ *
+ *	This structure holds various runtime configuration options for onak. It
+ *	will eventually be populated from the config file.
+ */
+struct onak_config {
+	int maxkeys;
+
+	/*
+	 * Options for the db2 file backend.
+	 */
+	char *db2_dbpath;
+
+	/*
+	 * Options for the file backend.
+	 */
+	char *file_dbpath;
+	
+	/*
+	 * Options for the Postgres backend.
+	 */
+	char *pg_dbhost;
+	char *pg_dbname;
+	char *pg_dbuser;
+	char *pg_dbpass;
+};
+
+/*
+ *	config - The variable containing our runtime config.
+ */
+extern struct onak_config config;
+
+#endif /* __ONAK_CONF_H_ */
diff --git a/parsekey.c b/parsekey.c
index df77493..f83e805 100644
--- a/parsekey.c
+++ b/parsekey.c
@@ -45,6 +45,13 @@ int parse_keys(struct openpgp_packet_list *packets,
 {
 	struct openpgp_publickey *curkey = NULL;
 
+	/*
+	 * If keys already has some keys in it then set curkey to the last one
+	 * so we add to the end of the list.
+	 */
+	for (curkey = *keys; curkey != NULL && curkey->next != NULL;
+			curkey = curkey->next) ;
+
 	while (packets != NULL) {
 		switch (packets->packet->tag) {
 		case 2:
@@ -103,8 +110,17 @@ int parse_keys(struct openpgp_packet_list *packets,
 				subkey,
 				packet_dup(packets->packet));
 			break;
+		case 12:
+		case 61:
+			/*
+			 * One of:
+			 *
+			 * Trust packet. Ignore.
+			 * Comment packet. Ignore.
+			 */
+			break;
 		default:
-			printf("Unsupported packet type: %d\n",
+			fprintf(stderr, "Unsupported packet type: %d\n",
 					packets->packet->tag);
 		}
 		packets = packets->next;
@@ -192,7 +208,7 @@ int read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
 				} else if (curpacket->packet->length > 223 &&
 					curpacket->packet->length < 255) {
 					printf("Partial length; not supported.\n");
-				} else {
+				} else if (curpacket->packet->length == 255) {
 					/*
 					 * 5 byte length; ie 255 followed by 3
 					 * bytes of MSB length.
@@ -209,7 +225,6 @@ int read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
 					rc = getchar_func(ctx, 1, &curchar);
 					curpacket->packet->length = curchar;
 				}
-
 			} else {
 				curpacket->packet->tag = (curchar & 0x3C) >> 2;
 				switch (curchar & 3) {
@@ -225,10 +240,20 @@ int read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
 					curpacket->packet->length += curchar;
 					break;
 				case 2:
-					printf("Unsupported length type 2.\n");
+					rc = getchar_func(ctx, 1, &curchar);
+					curpacket->packet->length = 
+						(curchar << 24);
+					rc = getchar_func(ctx, 1, &curchar);
+					curpacket->packet->length +=
+						(curchar << 16);
+					rc = getchar_func(ctx, 1, &curchar);
+					curpacket->packet->length +=
+						(curchar << 8);
+					rc = getchar_func(ctx, 1, &curchar);
+					curpacket->packet->length += curchar;
 					break;
 				case 3:
-					printf("Unsupported length type 3.\n");
+					fprintf(stderr, "Unsupported length type 3.\n");
 					break;
 				}
 			}
diff --git a/strace.out b/strace.out
deleted file mode 100644
index 9bc447a..0000000
--- a/strace.out
+++ /dev/null
@@ -1,409 +0,0 @@
-execve("./testparse", ["./testparse"], [/* 28 vars */]) = 0
-brk(0)                                  = 0x80549a4
-open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
-open("/etc/ld.so.cache", O_RDONLY)      = 4
-fstat(4, {st_mode=S_IFREG|0644, st_size=12180, ...}) = 0
-old_mmap(NULL, 12180, PROT_READ, MAP_PRIVATE, 4, 0) = 0x40014000
-close(4)                                = 0
-open("/usr/lib/libdb2.so.2", O_RDONLY)  = 4
-fstat(4, {st_mode=S_IFREG|0644, st_size=278604, ...}) = 0
-read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200\177"..., 4096) = 4096
-old_mmap(NULL, 275180, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4, 0) = 0x40017000
-mprotect(0x40059000, 4844, PROT_NONE)   = 0
-old_mmap(0x40059000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x41000) = 0x40059000
-close(4)                                = 0
-open("/lib/libc.so.6", O_RDONLY)        = 4
-fstat(4, {st_mode=S_IFREG|0755, st_size=888064, ...}) = 0
-read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\244\213"..., 4096) = 4096
-old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4005b000
-old_mmap(NULL, 902396, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4, 0) = 0x4005c000
-mprotect(0x40131000, 29948, PROT_NONE)  = 0
-old_mmap(0x40131000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0xd4000) = 0x40131000
-old_mmap(0x40135000, 13564, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40135000
-close(4)                                = 0
-munmap(0x40014000, 12180)               = 0
-getpid()                                = 5891
-write(2, "Doing read_openpgp_stream():\n", 29) = 29
-read(0, "\231", 1)                      = 1
-brk(0)                                  = 0x80549a4
-brk(0x80549c4)                          = 0x80549c4
-brk(0x8055000)                          = 0x8055000
-read(0, "\1", 1)                        = 1
-read(0, "\242", 1)                      = 1
-read(0, "\0048\25\307\311\21\4\0\340\203\230\232mP\306b\211\007"..., 418) = 418
-read(0, "\264", 1)                      = 1
-read(0, "$", 1)                         = 1
-read(0, "Jonathan McDowell <noodles@earth"..., 36) = 36
-read(0, "\210", 1)                      = 1
-read(0, "U", 1)                         = 1
-read(0, "\4\23\21\2\0\25\5\0028\25\307\311\3\v\n\3\3\25\3\2\3\26"..., 85) = 85
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\26=\5\0\n\t\20\353|\272\246\200\310"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028R\263\23\0\n\t\20\355\211\231\6\324"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028]+s\0\n\t\20>\222Z9\251}\375G\320"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\237Fb\0\n\t\20\200,\276\345B\366"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "?", 1)                         = 1
-read(0, "\3\5\0208\253\330P\261\202\275k\306?\346\22\21\2\24A\0"..., 63) = 63
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\313\277\0\n\t\20f\250\372\212"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\345\20\0\n\t\20\\\366T?2\372"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\0", 1)                        = 1
-read(0, "\225", 1)                      = 1
-brk(0x8056000)                          = 0x8056000
-read(0, "\3\5\0208\265\313\263 \24Y\314\200\2108\1\1\1\3622\4\0"..., 149) = 149
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\242\36\0\n\t\20\16\377\227\f"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "E", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\306~\0\n\t\20\263\276\v\213\5"..., 69) = 69
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\327Q\0\n\t\20;:O\n\307\236[j"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\266\325&\0\n\t\20\215$#\20U\35t\20"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\266\332\332\0\n\t\20$\305\303\201"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\267\21\265\0\n\t\20\212!t1Y|\322"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\367\30\0\n\t\20c;\205(Qx\342"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\1", 1)                        = 1
-read(0, "\25", 1)                       = 1
-read(0, "\3\5\0208\267\354\373\253VS\356\316\327l\1\1\1\237\336"..., 277) = 277
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\265\316\216\0\n\t\20p\377|je\26\1"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\2701b\0\n\t\20\200LyTvhw\263\017"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\272`E\0\n\t\20\211Z\313\r\27 \f("..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\274`\202\0\n\t\20\213\216\355\324"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\275j\16\0\n\t\20\221\274u\262\270"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\275\244\303\0\n\t\20`\24%0\3\337"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "?", 1)                         = 1
-read(0, "\3\5\0208\265\275\215\227CRw\36\370H,\21\2\300v\0\240\355"..., 63) = 63
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\276UK\0\n\t\20\267\0356\371\303\321"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\1", 1)                        = 1
-read(0, "\25", 1)                       = 1
-read(0, "\3\5\0208\310**V\r52\317`V\1\1\1\214\251\10\0\207R\366"..., 277) = 277
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\267\373\212\0\n\t\20r\373\375\226"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\326\266\245\0\n\t\20\20\372D\231"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\326\315\314\0\n\t\20\rIu\217\362"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0028\372\351\27\0\n\t\20\303\274\3669"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\0", 1)                        = 1
-read(0, "\225", 1)                      = 1
-read(0, "\3\5\02099^s\271\205\230\"M\304\347\375\1\0015d\4\0\235"..., 149) = 149
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0029;\346\v\0\n\t\20\0174\5w\320\227\242"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0029bW\363\0\n\t\20c0\342\243\247.\21"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\0029\207V\372\0\n\t\20\4\265\30\35\235"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\200H\304\0\n\t\20)\276]\"h\375T\237"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\246\34 \0\n\t\0201\7e\373\337\\\342"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\353\357\327\0\n\t\0201Z\321\36I\27"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2;F\376\333\0\n\t\20]\312\337\3415\1\346"..., 70) = 70
-read(0, "\210", 1)                      = 1
-brk(0x8057000)                          = 0x8057000
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\367\325$\0\n\t\20b\3\212K\335\233\231"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\367\324\263\0\n\t\20q\177\270\244\27"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\353\224\213\0\n\t\20|;yp\210\307\301"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\321\227\10\0\n\t\20\210\320\362T3\267"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\0", 1)                        = 1
-read(0, "\225", 1)                      = 1
-read(0, "\3\5\20:\354\245\227\266\233\30.\276\223\267\231\1\1s\355"..., 149) = 149
-read(0, "\211", 1)                      = 1
-read(0, "\0", 1)                        = 1
-read(0, "\225", 1)                      = 1
-read(0, "\3\5\20:\354\245\240\303\26\216\272#\365\255\333\1\1~z"..., 149) = 149
-read(0, "\211", 1)                      = 1
-read(0, "\0", 1)                        = 1
-read(0, "\225", 1)                      = 1
-read(0, "\2\5\20:\367\325f\305(\32\345\4d\347\345\1\1-H\4\0\203"..., 149) = 149
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2:\354\242\247\0\n\t\20\372\10\276\256"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2;I\372t\0\n\t\20!g%p\27O\3565Z\n\0\235"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2;\302\16\201\0\n\t\20s\277\226\253\240"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2;\25287\0\n\t\20\200?\356\22\'\24\33"..., 70) = 70
-read(0, "\211", 1)                      = 1
-read(0, "\1", 1)                        = 1
-read(0, "\36", 1)                       = 1
-read(0, "\4\20\24\3\0\6\5\2<\0\377\314\0\n\t\20\345\345\23\r\212"..., 286) = 286
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2<\2=\6\0\n\t\20=\3066\256\363\212]\215"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2<\25bR\0\n\t\20\235\331\36\234(c\313"..., 70) = 70
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\20\21\2\0\6\5\2<\22\221\312\0\n\t\20\253\16\3]\265M"..., 70) = 70
-read(0, "\271", 1)                      = 1
-read(0, "\2", 1)                        = 1
-read(0, "\r", 1)                        = 1
-read(0, "\0048\25\310\304\20\10\0\247\245\305\16\362\372\22\273"..., 525) = 525
-read(0, "\210", 1)                      = 1
-read(0, "F", 1)                         = 1
-read(0, "\4\30\21\2\0\6\5\0028\25\310\304\0\n\t\20\361\275K\344"..., 70) = 70
-read(0, "", 1)                          = 0
-write(2, "Doing parse_keys():\n", 20)   = 20
-brk(0x8058000)                          = 0x8058000
-brk(0x8059000)                          = 0x8059000
-fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 5), ...}) = 0
-old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000
-ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
-write(1, "Key id is 0xF1BD4BE45B430367\n", 29) = 29
-open("/community/pgp-keyserver/db-copy/DB_CONFIG", O_RDONLY) = -1 ENOENT (No such file or directory)
-stat("/var/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
-open("/community/pgp-keyserver/db-copy/__db_lock.share", O_RDWR) = 4
-fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
-fstat(4, {st_mode=S_IFREG|0640, st_size=729088, ...}) = 0
-old_mmap(NULL, 729088, PROT_READ|PROT_WRITE, MAP_SHARED, 4, 0) = 0x40139000
-open("/community/pgp-keyserver/db-copy/__db_mpool.share", O_RDWR) = 5
-fcntl(5, F_SETFD, FD_CLOEXEC)           = 0
-fstat(5, {st_mode=S_IFREG|0640, st_size=327680, ...}) = 0
-old_mmap(NULL, 327680, PROT_READ|PROT_WRITE, MAP_SHARED, 5, 0) = 0x401eb000
-open("/community/pgp-keyserver/db-copy/keydb000", O_RDONLY) = 6
-fcntl(6, F_SETFD, FD_CLOEXEC)           = 0
-read(6, "<\7\0\0\22\376{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0"..., 512) = 512
-close(6)                                = 0
-brk(0x805a000)                          = 0x805a000
-open("/community/pgp-keyserver/db-copy/keydb000", O_RDONLY) = 6
-fcntl(6, F_SETFD, FD_CLOEXEC)           = 0
-fstat(6, {st_mode=S_IFREG|0644, st_size=195452928, ...}) = 0
-brk(0x805d000)                          = 0x805d000
-open("/etc/fstab", O_RDONLY)            = 7
-fstat(7, {st_mode=S_IFREG|0644, st_size=638, ...}) = 0
-old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40015000
-read(7, "# /etc/fstab: static file system"..., 4096) = 638
-close(7)                                = 0
-munmap(0x40015000, 4096)                = 0
-open("/proc/cpuinfo", O_RDONLY)         = 7
-fstat(7, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
-old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40015000
-read(7, "processor\t: 0\nvendor_id\t: Genuin"..., 1024) = 381
-read(7, "", 1024)                       = 0
-close(7)                                = 0
-munmap(0x40015000, 4096)                = 0
-pread(6, "<\7\0\0\22\376{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb001", O_RDONLY) = 7
-fcntl(7, F_SETFD, FD_CLOEXEC)           = 0
-read(7, "<\7\0\0\351\206z\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 512) = 512
-close(7)                                = 0
-open("/community/pgp-keyserver/db-copy/keydb001", O_RDONLY) = 7
-fcntl(7, F_SETFD, FD_CLOEXEC)           = 0
-fstat(7, {st_mode=S_IFREG|0644, st_size=348774400, ...}) = 0
-brk(0x8060000)                          = 0x8060000
-pread(7, "<\7\0\0\351\206z\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb002", O_RDONLY) = 8
-fcntl(8, F_SETFD, FD_CLOEXEC)           = 0
-read(8, "<\7\0\0\255\307u\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 512) = 512
-close(8)                                = 0
-open("/community/pgp-keyserver/db-copy/keydb002", O_RDONLY) = 8
-fcntl(8, F_SETFD, FD_CLOEXEC)           = 0
-fstat(8, {st_mode=S_IFREG|0644, st_size=195371008, ...}) = 0
-pread(8, "<\7\0\0\255\307u\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb003", O_RDONLY) = 9
-fcntl(9, F_SETFD, FD_CLOEXEC)           = 0
-read(9, "<\7\0\0|S{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0\5"..., 512) = 512
-close(9)                                = 0
-open("/community/pgp-keyserver/db-copy/keydb003", O_RDONLY) = 9
-fcntl(9, F_SETFD, FD_CLOEXEC)           = 0
-fstat(9, {st_mode=S_IFREG|0644, st_size=201302016, ...}) = 0
-brk(0x8063000)                          = 0x8063000
-pread(9, "<\7\0\0|S{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0\5"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb004", O_RDONLY) = 10
-fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
-read(10, "<\7\0\0p\254t\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 512) = 512
-close(10)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb004", O_RDONLY) = 10
-fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
-fstat(10, {st_mode=S_IFREG|0644, st_size=195772416, ...}) = 0
-brk(0x8066000)                          = 0x8066000
-pread(10, "<\7\0\0p\254t\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb005", O_RDONLY) = 11
-fcntl(11, F_SETFD, FD_CLOEXEC)          = 0
-read(11, "<\7\0\0005Uw\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0\0\0"..., 512) = 512
-close(11)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb005", O_RDONLY) = 11
-fcntl(11, F_SETFD, FD_CLOEXEC)          = 0
-fstat(11, {st_mode=S_IFREG|0644, st_size=347947008, ...}) = 0
-pread(11, "<\7\0\0005Uw\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0\0\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb006", O_RDONLY) = 12
-fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
-read(12, "<\7\0\0\225\201s\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 512) = 512
-close(12)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb006", O_RDONLY) = 12
-fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
-fstat(12, {st_mode=S_IFREG|0644, st_size=195354624, ...}) = 0
-brk(0x8069000)                          = 0x8069000
-pread(12, "<\7\0\0\225\201s\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb007", O_RDONLY) = 13
-fcntl(13, F_SETFD, FD_CLOEXEC)          = 0
-read(13, "<\7\0\0tFu\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0\363"..., 512) = 512
-close(13)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb007", O_RDONLY) = 13
-fcntl(13, F_SETFD, FD_CLOEXEC)          = 0
-fstat(13, {st_mode=S_IFREG|0644, st_size=201105408, ...}) = 0
-brk(0x806c000)                          = 0x806c000
-pread(13, "<\7\0\0tFu\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0\363"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb008", O_RDONLY) = 14
-fcntl(14, F_SETFD, FD_CLOEXEC)          = 0
-read(14, "<\7\0\0\232Ir\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 512) = 512
-close(14)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb008", O_RDONLY) = 14
-fcntl(14, F_SETFD, FD_CLOEXEC)          = 0
-fstat(14, {st_mode=S_IFREG|0644, st_size=195674112, ...}) = 0
-brk(0x806f000)                          = 0x806f000
-pread(14, "<\7\0\0\232Ir\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb009", O_RDONLY) = 15
-fcntl(15, F_SETFD, FD_CLOEXEC)          = 0
-read(15, "<\7\0\0\207\211{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 512) = 512
-close(15)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb009", O_RDONLY) = 15
-fcntl(15, F_SETFD, FD_CLOEXEC)          = 0
-fstat(15, {st_mode=S_IFREG|0644, st_size=348651520, ...}) = 0
-pread(15, "<\7\0\0\207\211{\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb010", O_RDONLY) = 16
-fcntl(16, F_SETFD, FD_CLOEXEC)          = 0
-read(16, "<\7\0\0_Mz\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0f\27"..., 512) = 512
-close(16)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb010", O_RDONLY) = 16
-fcntl(16, F_SETFD, FD_CLOEXEC)          = 0
-fstat(16, {st_mode=S_IFREG|0644, st_size=195780608, ...}) = 0
-brk(0x8072000)                          = 0x8072000
-pread(16, "<\7\0\0_Mz\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0f\27"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb011", O_RDONLY) = 17
-fcntl(17, F_SETFD, FD_CLOEXEC)          = 0
-read(17, "<\7\0\0\304\375x\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 512) = 512
-close(17)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb011", O_RDONLY) = 17
-fcntl(17, F_SETFD, FD_CLOEXEC)          = 0
-fstat(17, {st_mode=S_IFREG|0644, st_size=200957952, ...}) = 0
-brk(0x8075000)                          = 0x8075000
-pread(17, "<\7\0\0\304\375x\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb012", O_RDONLY) = 18
-fcntl(18, F_SETFD, FD_CLOEXEC)          = 0
-read(18, "<\7\0\0\312\317k\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 512) = 512
-close(18)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb012", O_RDONLY) = 18
-fcntl(18, F_SETFD, FD_CLOEXEC)          = 0
-fstat(18, {st_mode=S_IFREG|0644, st_size=195829760, ...}) = 0
-pread(18, "<\7\0\0\312\317k\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb013", O_RDONLY) = 19
-fcntl(19, F_SETFD, FD_CLOEXEC)          = 0
-read(19, "<\7\0\0\320\220x\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 512) = 512
-close(19)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb013", O_RDONLY) = 19
-fcntl(19, F_SETFD, FD_CLOEXEC)          = 0
-fstat(19, {st_mode=S_IFREG|0644, st_size=349478912, ...}) = 0
-brk(0x8078000)                          = 0x8078000
-pread(19, "<\7\0\0\320\220x\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\17\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb014", O_RDONLY) = 20
-fcntl(20, F_SETFD, FD_CLOEXEC)          = 0
-read(20, "<\7\0\0\366@F\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 512) = 512
-close(20)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb014", O_RDONLY) = 20
-fcntl(20, F_SETFD, FD_CLOEXEC)          = 0
-fstat(20, {st_mode=S_IFREG|0644, st_size=195387392, ...}) = 0
-brk(0x807b000)                          = 0x807b000
-pread(20, "<\7\0\0\366@F\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 8192, 0) = 8192
-open("/community/pgp-keyserver/db-copy/keydb015", O_RDONLY) = 21
-fcntl(21, F_SETFD, FD_CLOEXEC)          = 0
-read(21, "<\7\0\0=\33z\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 512) = 512
-close(21)                               = 0
-open("/community/pgp-keyserver/db-copy/keydb015", O_RDONLY) = 21
-fcntl(21, F_SETFD, FD_CLOEXEC)          = 0
-fstat(21, {st_mode=S_IFREG|0644, st_size=201031680, ...}) = 0
-brk(0x807e000)                          = 0x807e000
-pread(21, "<\7\0\0=\33z\0\0\0\0\0a\25\6\0\5\0\0\0\0 \0\0\16\0\0\0"..., 8192, 0) = 8192
-pread(14, "\322\6\0\0*\305n\0\3\0\0\0\0\0\0\0\250Q\0\0\f\0\221\2\0"..., 8192, 24576) = 8192
-pread(14, "\363\4\0\0\5\24E\0\250Q\0\0\3\0\0\0\0\0\0\0\4\0\17\25\0"..., 8192, 171245568) = 8192
-close(6)                                = 0
-close(7)                                = 0
-close(8)                                = 0
-close(9)                                = 0
-close(10)                               = 0
-close(11)                               = 0
-close(12)                               = 0
-close(13)                               = 0
-close(14)                               = 0
-close(15)                               = 0
-close(16)                               = 0
-close(17)                               = 0
-close(18)                               = 0
-close(19)                               = 0
-close(20)                               = 0
-close(21)                               = 0
-brk(0x805e000)                          = 0x805e000
-close(5)                                = 0
-munmap(0x401eb000, 327680)              = 0
-close(4)                                = 0
-munmap(0x40139000, 729088)              = 0
-munmap(0x40014000, 4096)                = 0
-_exit(0)                                = ?