Add -1 to Debian package version
[onak.git] / keyd.c
diff --git a/keyd.c b/keyd.c
index f8f5d4a50abd8f98bf2c053443c85f270af791b6..5d5b7ba8c883b68326361f7789bbb228e6ac1593 100644 (file)
--- a/keyd.c
+++ b/keyd.c
@@ -2,17 +2,22 @@
  * keyd.c - key retrieval daemon
  *
  * Jonathan McDowell <noodles@earth.li>
- * 
+ *
  * Copyright 2004 Project Purple
  */
 
+#include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/select.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "charfuncs.h"
 #include "mem.h"
 #include "onak-conf.h"
 #include "parsekey.h"
+#include "version.h"
+
+static struct keyd_stats *stats;
+
+void daemonize(void)
+{
+       pid_t pid;
+
+       pid = fork();
+
+       if (pid < 0) {
+               logthing(LOGTHING_CRITICAL,
+                       "Failed to fork into background: %d (%s)",
+                       errno,
+                       strerror(errno));
+               exit(EXIT_FAILURE);
+       } else if (pid > 0) {
+               logthing(LOGTHING_INFO, "Backgrounded as pid %d.", pid);
+               exit(EXIT_SUCCESS);
+       }
+
+       pid = setsid();
+
+       freopen("/dev/null", "r", stdin);
+       freopen("/dev/null", "w", stdout);
+       freopen("/dev/null", "w", stderr);
+
+       return;
+}
 
 void iteratefunc(void *ctx, struct openpgp_publickey *key)
 {
@@ -32,7 +66,7 @@ void iteratefunc(void *ctx, struct openpgp_publickey *key)
        struct openpgp_packet_list *list_end = NULL;
        struct buffer_ctx           storebuf;
        int                         ret = 0;
-       int                         fd = (int) ctx;
+       int                         *fd = (int *) ctx;
 
        if (key != NULL) {
                storebuf.offset = 0;
@@ -40,7 +74,7 @@ void iteratefunc(void *ctx, struct openpgp_publickey *key)
                storebuf.buffer = malloc(8192);
 
                logthing(LOGTHING_TRACE,
-                               "Iterating over 0x%016llX.",
+                               "Iterating over 0x%016" PRIX64 ".",
                                get_keyid(key));
 
                flatten_publickey(key,
@@ -52,10 +86,10 @@ void iteratefunc(void *ctx, struct openpgp_publickey *key)
                logthing(LOGTHING_TRACE,
                                "Sending %d bytes.",
                                storebuf.offset);
-               ret = write(fd, &storebuf.offset,
+               ret = write(*fd, &storebuf.offset,
                        sizeof(storebuf.offset));
                if (ret != 0) {
-                       write(fd, storebuf.buffer,
+                       write(*fd, storebuf.buffer,
                                storebuf.offset);
                }
 
@@ -96,7 +130,7 @@ int sock_init(const char *sockname)
 
 int sock_do(int fd)
 {
-       int      cmd = KEYD_CMD_UNKNOWN;
+       uint32_t cmd = KEYD_CMD_UNKNOWN;
        ssize_t  bytes = 0;
        ssize_t  count = 0;
        int      ret = 0;
@@ -119,10 +153,17 @@ int sock_do(int fd)
        }
        
        if (ret == 0) {
+               if (cmd < KEYD_CMD_LAST) {
+                       stats->command_stats[cmd]++;
+               } else {
+                       stats->command_stats[KEYD_CMD_UNKNOWN]++;
+               }
                switch (cmd) {
                case KEYD_CMD_VERSION:
                        cmd = KEYD_REPLY_OK;
                        write(fd, &cmd, sizeof(cmd));
+                       cmd = sizeof(keyd_version);
+                       write(fd, &cmd, sizeof(cmd));
                        write(fd, &keyd_version, sizeof(keyd_version));
                        break;
                case KEYD_CMD_GET:
@@ -135,8 +176,10 @@ int sock_do(int fd)
                        storebuf.offset = 0;
                        if (ret == 0) {
                                logthing(LOGTHING_INFO,
-                                               "Fetching 0x%llX, result: %d",
+                                               "Fetching 0x%" PRIX64
+                                               ", result: %d",
                                                keyid,
+                                               config.dbbackend->
                                                fetch_key(keyid, &key, false));
                                if (key != NULL) {
                                        storebuf.size = 8192;
@@ -184,6 +227,7 @@ int sock_do(int fd)
                                logthing(LOGTHING_INFO,
                                                "Fetching %s, result: %d",
                                                search,
+                                               config.dbbackend->
                                                fetch_key_text(search, &key));
                                if (key != NULL) {
                                        storebuf.size = 8192;
@@ -244,7 +288,7 @@ int sock_do(int fd)
                                                &packets,
                                                0);
                                parse_keys(packets, &key);
-                               store_key(key, false, false);
+                               config.dbbackend->store_key(key, false, false);
                                free_packet_list(packets);
                                packets = NULL;
                                free_publickey(key);
@@ -263,9 +307,11 @@ int sock_do(int fd)
                        }
                        if (ret == 0) {
                                logthing(LOGTHING_INFO,
-                                               "Deleting 0x%llX, result: %d",
+                                               "Deleting 0x%" PRIX64
+                                               ", result: %d",
                                                keyid,
-                                               delete_key(keyid, false));
+                                               config.dbbackend->delete_key(
+                                                       keyid, false));
                        }
                        break;
                case KEYD_CMD_GETFULLKEYID:
@@ -276,23 +322,41 @@ int sock_do(int fd)
                                ret = 1;
                        }
                        if (ret == 0) {
-                               keyid = getfullkeyid(keyid);
+                               keyid = config.dbbackend->getfullkeyid(keyid);
+                               cmd = sizeof(keyid);
+                               write(fd, &cmd, sizeof(cmd));
                                write(fd, &keyid, sizeof(keyid));
                        }
                        break;
                case KEYD_CMD_KEYITER:
                        cmd = KEYD_REPLY_OK;
                        write(fd, &cmd, sizeof(cmd));
-                       iterate_keys(iteratefunc, (void *) fd);
+                       config.dbbackend->iterate_keys(iteratefunc,
+                                       &fd);
                        bytes = 0;
                        write(fd, &bytes, sizeof(bytes));
                        break;
                case KEYD_CMD_CLOSE:
+                       cmd = KEYD_REPLY_OK;
+                       write(fd, &cmd, sizeof(cmd));
                        ret = 1;
                        break;
                case KEYD_CMD_QUIT:
+                       cmd = KEYD_REPLY_OK;
+                       write(fd, &cmd, sizeof(cmd));
+                       logthing(LOGTHING_NOTICE,
+                               "Exiting due to quit request.");
+                       ret = 1;
                        trytocleanup();
                        break;
+               case KEYD_CMD_STATS:
+                       cmd = KEYD_REPLY_OK;
+                       write(fd, &cmd, sizeof(cmd));
+                       cmd = sizeof(*stats);
+                       write(fd, &cmd, sizeof(cmd));
+                       write(fd, stats,
+                               sizeof(*stats));
+                       break;
                default:
                        logthing(LOGTHING_ERROR, "Got unknown command: %d",
                                        cmd);
@@ -306,7 +370,8 @@ int sock_do(int fd)
 
 int sock_close(int fd)
 {
-       return shutdown(fd, SHUT_RDWR);
+       shutdown(fd, SHUT_RDWR);
+       return close(fd);
 }
 
 int sock_accept(int fd)
@@ -323,6 +388,7 @@ int sock_accept(int fd)
        }
 
        if (ret != -1) {
+               stats->connects++;
                while (!sock_do(srv)) ;
                sock_close(srv);
        }
@@ -330,17 +396,65 @@ int sock_accept(int fd)
        return 1;
 }
 
+static void usage(void)
+{
+       puts("keyd " ONAK_VERSION " - backend key serving daemon for the "
+               "onak PGP keyserver.\n");
+       puts("Usage:\n");
+       puts("\tkeyd [options]\n");
+       puts("\tOptions:\n:");
+       puts("-c <file> - use <file> as the config file");
+       puts("-f        - run in the foreground");
+       puts("-h        - show this help text");
+       exit(EXIT_FAILURE);
+}
+
 int main(int argc, char *argv[])
 {
        int fd = -1;
        fd_set rfds;
        char sockname[1024];
+       char *configfile = NULL;
+       bool foreground = false;
+       int optchar;
+
+       while ((optchar = getopt(argc, argv, "c:fh")) != -1 ) {
+               switch (optchar) {
+               case 'c':
+                       configfile = strdup(optarg);
+                       break;
+               case 'f':
+                       foreground = true;
+                       break;
+               case 'h':
+               default:
+                       usage();
+                       break;
+               }
+       }
 
-       readconfig(NULL);
+       readconfig(configfile);
+       free(configfile);
+       configfile = NULL;
        initlogthing("keyd", config.logfile);
+       config.use_keyd = false;
+
+       if (!foreground) {
+               daemonize();
+       }
 
        catchsignals();
-       
+       signal(SIGPIPE, SIG_IGN);
+
+
+       stats = calloc(1, sizeof(*stats));
+       if (!stats) {
+               logthing(LOGTHING_ERROR,
+                       "Couldn't allocate memory for stats structure.");
+               exit(EXIT_FAILURE);
+       }
+       stats->started = time(NULL);
+
        snprintf(sockname, 1023, "%s/%s", config.db_dir, KEYD_SOCKET);
        fd = sock_init(sockname);
 
@@ -348,7 +462,7 @@ int main(int argc, char *argv[])
                FD_ZERO(&rfds);
                FD_SET(fd, &rfds);
 
-               initdb(false);
+               config.dbbackend->initdb(false);
 
                logthing(LOGTHING_NOTICE, "Accepting connections.");
                while (!cleanup() && select(fd + 1, &rfds, NULL, NULL, NULL) != -1) {
@@ -356,13 +470,15 @@ int main(int argc, char *argv[])
                        sock_accept(fd);
                        FD_SET(fd, &rfds);
                }
-               cleanupdb();
+               config.dbbackend->cleanupdb();
                sock_close(fd);
                unlink(sockname);
        }
 
+       free(stats);
+
        cleanuplogthing();
        cleanupconfig();
-       
+
        return(EXIT_SUCCESS);
 }