PROGS = add lookup gpgwww onak
CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o keydb_$(DBTYPE).o \
- keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha.o md5.o
+ keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha.o md5.o log.o
OBJS = merge.o stats.o sendsync.o $(CORE_OBJS)
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 \
- gpgwww.c onak-conf.c charfuncs.c sendsync.c
+ gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c
all: $(PROGS) testparse maxpath sixdegrees
#include "getcgi.h"
#include "keydb.h"
#include "keystructs.h"
+#include "log.h"
#include "mem.h"
#include "merge.h"
#include "onak-conf.h"
if (ctx.buffer == NULL) {
puts("Error: No keytext to add supplied.");
} else {
+ readconfig();
+ initlogthing("add", config.logfile);
dearmor_openpgp_stream(buffer_fetchchar,
&ctx,
&packets);
if (packets != NULL) {
parse_keys(packets, &keys);
- readconfig();
initdb();
printf("Got %d new keys.\n",
- update_keys(&keys, false));
+ update_keys(&keys));
if (keys != NULL) {
sendkeysync(keys);
free_publickey(keys);
keys = NULL;
}
cleanupdb();
- cleanupconfig();
} else {
puts("No OpenPGP packets found in input.");
}
+ cleanuplogthing();
+ cleanupconfig();
}
end_html();
return (EXIT_SUCCESS);
#include "getcgi.h"
#include "hash.h"
#include "keydb.h"
+#include "log.h"
#include "onak-conf.h"
#include "stats.h"
printf("<P>Looking for path from 0x%llX to 0x%llX</P>\n", from, to);
readconfig();
+ initlogthing("gpgwww", config.logfile);
initdb();
inithash();
dofindpath(from, to, true);
destroyhash();
cleanupdb();
+ cleanuplogthing();
cleanupconfig();
puts("<HR>");
#include "keyid.h"
#include "keyindex.h"
#include "keystructs.h"
+#include "log.h"
#include "mem.h"
#include "onak-conf.h"
#include "parsekey.h"
&db2_env, &keydbinfo,
&db2_keydbfiles[i]);
if (ret) {
- fprintf(stderr, "Error opening db file %d (errno %d)\n",
+ logthing(LOGTHING_CRITICAL,
+ "Error opening db file %d (errno %d)",
i, ret);
exit(1);
}
}
} else {
- fprintf(stderr, "Error initializing db (%d).\n", ret);
+ logthing(LOGTHING_CRITICAL, "Error initializing db (%d).",
+ ret);
exit(1);
}
}
#include "decodekey.h"
#include "keystructs.h"
#include "mem.h"
+#include "log.h"
#include "onak-conf.h"
#include "parsekey.h"
ret = db_env_create(&dbenv, 0);
if (ret != 0) {
- fprintf(stderr, "db_env_create: %s\n", db_strerror(ret));
+ logthing(LOGTHING_CRITICAL,
+ "db_env_create: %s", db_strerror(ret));
exit(1);
}
ret = db_create(&dbconn, dbenv, 0);
if (ret != 0) {
- fprintf(stderr, "db_create: %s\n", db_strerror(ret));
+ logthing(LOGTHING_CRITICAL,
+ "db_create: %s", db_strerror(ret));
exit(1);
}
ret = db_create(&worddb, dbenv, 0);
if (ret != 0) {
- fprintf(stderr, "db_create: %s\n", db_strerror(ret));
+ logthing(LOGTHING_CRITICAL, "db_create: %s", db_strerror(ret));
exit(1);
}
ret = worddb->set_flags(worddb, DB_DUP);
#include "keyid.h"
#include "decodekey.h"
#include "keystructs.h"
+#include "log.h"
#include "mem.h"
#include "onak-conf.h"
#include "parsekey.h"
config.pg_dbpass); // password
if (PQstatus(dbconn) == CONNECTION_BAD) {
- fprintf(stderr, "Connection to database failed.\n");
- fprintf(stderr, "%s\n", PQerrorMessage(dbconn));
+ logthing(LOGTHING_CRITICAL, "Connection to database failed.");
+ logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
PQfinish(dbconn);
dbconn = NULL;
exit(1);
fd = lo_open(dbconn, key_oid, INV_READ);
if (fd < 0) {
- fprintf(stderr, "Can't open large object.\n");
+ logthing(LOGTHING_ERROR,
+ "Can't open large object.");
} else {
read_openpgp_stream(keydb_fetchchar, &fd,
&packets);
}
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
fd = lo_open(dbconn, key_oid, INV_READ);
if (fd < 0) {
- fprintf(stderr, "Can't open large object.\n");
+ logthing(LOGTHING_ERROR,
+ "Can't open large object.");
} else {
read_openpgp_stream(keydb_fetchchar, &fd,
&packets);
}
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
key_oid = lo_creat(dbconn, INV_READ | INV_WRITE);
if (key_oid == 0) {
- fprintf(stderr, "Can't create key OID\n");
+ logthing(LOGTHING_ERROR, "Can't create key OID");
} else {
fd = lo_open(dbconn, key_oid, INV_WRITE);
write_openpgp_stream(keydb_putchar, &fd, packets);
result = PQexec(dbconn, statement);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
- fprintf(stderr, "Problem storing key in DB.\n");
- fprintf(stderr, "%s\n", PQresultErrorMessage(result));
+ logthing(LOGTHING_ERROR, "Problem storing key in DB.");
+ logthing(LOGTHING_ERROR, "%s", PQresultErrorMessage(result));
}
PQclear(result);
}
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
- fprintf(stderr, "Problem storing key in DB.\n");
- fprintf(stderr, "%s\n",
+ logthing(LOGTHING_ERROR,
+ "Problem storing key in DB.");
+ logthing(LOGTHING_ERROR, "%s",
PQresultErrorMessage(result));
}
/*
keyid);
result = PQexec(dbconn, statement);
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
+ logthing(LOGTHING_ERROR,
+ "Problem retrieving key (%llX) from DB.",
keyid);
}
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",
+ logthing(LOGTHING_ERROR,
+ "Problem retrieving key (%llX) from DB.",
keyid);
}
sigs = lladd(sigs, createandaddtohash(signer));
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
#include "keyid.h"
#include "keystructs.h"
+#include "log.h"
#include "md5.h"
#include "sha.h"
memcpy(fingerprint, buff, *len);
break;
default:
- fprintf(stderr, "Unknown key type: %d\n",
+ logthing(LOGTHING_ERROR, "Unknown key type: %d",
packet->data[0]);
}
keyid += packet->data[offset++];
}
} else {
- fputs("Type 2 or 3 key, but not RSA.\n", stderr);
+ logthing(LOGTHING_ERROR,
+ "Type 2 or 3 key, but not RSA.");
}
break;
case 4:
break;
default:
- fprintf(stderr, "Unknown key type: %d\n",
+ logthing(LOGTHING_ERROR, "Unknown key type: %d",
packet->data[0]);
}
#include "keyid.h"
#include "keyindex.h"
#include "keystructs.h"
+#include "log.h"
int list_sigs(struct openpgp_packet_list *sigs, bool html)
{
subkeys->packet->data[7];
break;
default:
- fprintf(stderr, "Unknown key type: %d\n",
+ logthing(LOGTHING_ERROR,
+ "Unknown key type: %d",
subkeys->packet->data[0]);
}
keys->publickey->data[7];
break;
default:
- fprintf(stderr, "Unknown key type: %d\n",
+ logthing(LOGTHING_ERROR, "Unknown key type: %d",
keys->publickey->data[0]);
}
--- /dev/null
+/*
+ * log.c - Simple logging framework.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2003 Project Purple
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "log.h"
+
+/*
+ * logthres - holds the minimum log level we'll output
+ *
+ * This variable keeps track of the threshold we've set for outputting
+ * logs - if we're asked to log something below this level we won't output
+ * it.
+ */
+static loglevels logthres = LOGTHING_DEBUG;
+
+/*
+ * logappname - the name of the application using us.
+ *
+ * This holds information about the name of the application we're being
+ * called by. It's set when we're initialized.
+ */
+static char *logappname = NULL;
+
+/*
+ * logfilename - the file to log to.
+ *
+ * The full name and path of the file we should log to.
+ */
+static char *logfilename = NULL;
+
+/*
+ * initlogthing - initialize the logging module
+ * @appname: The application name to use in the log.
+ * @filename: The filename to log to. NULL means stderr.
+ *
+ * This function sets up the logging module ready to log. The appname is
+ * written as part of every log entry and the filename is the file we
+ * should log to. If the appname is NULL then none is written. If the
+ * filename is NULL all output is sent to stderr.
+ */
+int initlogthing(const char *appname, const char *filename)
+{
+ if (appname != NULL) {
+ logappname = strdup(appname);
+ }
+
+ if (filename != NULL) {
+ logfilename = strdup(filename);
+ }
+
+ return 0;
+}
+
+/*
+ * cleanuplogthing - clean up the logging module
+ *
+ * This function cleans up the logging module after use.
+ */
+void cleanuplogthing(void)
+{
+ if (logappname != NULL) {
+ free(logappname);
+ logappname = NULL;
+ }
+
+ if (logfilename != NULL) {
+ free(logfilename);
+ logfilename = NULL;
+ }
+
+ return;
+}
+
+/*
+ * setlogthreshold - set the threshold for log output
+ * @loglevel: The minimum log level we should output
+ *
+ * Sets the threshold for log output; anything logged with a log level
+ * lower than this will be silently dropped. Returns the old log threshold
+ * value.
+ */
+loglevels setlogthreshold(loglevels loglevel)
+{
+ loglevels oldlevel;
+
+ oldlevel = logthres;
+ logthres = loglevel;
+
+ return oldlevel;
+}
+
+/*
+ * logthing - output a log entry
+ * @loglevel: The level of the log.
+ * @format: A format string, followed by any parameters required.
+ *
+ * This function outputs a log entry. A leading time/date stamp and a
+ * trailing newline are automatically added. The loglevel is compared to
+ * the current log threshold and if equal or above the log entry is
+ * output. The format parameter is of the same nature as that used in
+ * printf.
+ */
+int logthing(loglevels loglevel, const char *format, ...)
+{
+ FILE *logfile = NULL;
+ struct tm *timestamp = NULL;
+ time_t timer = 0;
+ va_list ap;
+
+ if (loglevel >= logthres) {
+ timer = time(NULL);
+ timestamp = localtime(&timer);
+
+ if (logfilename != NULL) {
+ logfile = fopen(logfilename, "a");
+ flockfile(logfile);
+ } else {
+ logfile = stderr;
+ }
+
+ fprintf(logfile, "[%02d/%02d/%4d %02d:%02d:%02d] %s[%d]: ",
+ timestamp->tm_mday,
+ timestamp->tm_mon,
+ timestamp->tm_year + 1900,
+ timestamp->tm_hour,
+ timestamp->tm_min,
+ timestamp->tm_sec,
+ (logappname == NULL) ? "" : logappname,
+ getpid());
+ va_start(ap, format);
+ vfprintf(logfile, format, ap);
+ va_end(ap);
+ fprintf(logfile, "\n");
+
+
+ if (logfilename != NULL) {
+ funlockfile(logfile);
+ fclose(logfile);
+ logfile = NULL;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * log.h - Simple logging framework.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2003 Project Purple
+ */
+
+#ifndef __LOG_H__
+#define __LOG_H__
+
+/*
+ * loglevels - levels of severity for a log entry
+ *
+ * These provide various different levels of severity for a log entry. In
+ * acesending order they are:
+ *
+ * LOGTHING_TRACE
+ * LOGTHING_DEBUG
+ * LOGTHING_INFO
+ * LOGTHING_NOTICE
+ * LOGTHING_ERROR
+ * LOGTHING_SERIOUS
+ * LOGTHING_CRITICAL
+ *
+ * By default the log threshold is set to LOGTHING_NOTICE, meaning
+ * anything with a lower priority won't be output.
+ */
+typedef enum {
+ LOGTHING_TRACE = 0,
+ LOGTHING_DEBUG = 1,
+ LOGTHING_INFO = 2,
+ LOGTHING_NOTICE = 3,
+ LOGTHING_ERROR = 4,
+ LOGTHING_SERIOUS = 5,
+ LOGTHING_CRITICAL = 6
+} loglevels;
+
+/*
+ * initlogthing - initialize the logging module
+ * @appname: The application name to use in the log.
+ * @filename: The filename to log to. NULL means stderr.
+ *
+ * This function sets up the logging module ready to log. The appname is
+ * written as part of every log entry and the filename is the file we
+ * should log to. If the appname is NULL then none is written. If the
+ * filename is NULL all output is sent to stderr.
+ */
+int initlogthing(const char *appname, const char *filename);
+
+/*
+ * cleanuplogthing - clean up the logging module
+ *
+ * This function cleans up the logging module after use.
+ */
+void cleanuplogthing(void);
+
+/*
+ * setlogthreshold - set the threshold for log output
+ * @loglevel: The minimum log level we should output
+ *
+ * Sets the threshold for log output; anything logged with a log level
+ * lower than this will be silently dropped. Returns the old log threshold
+ * value.
+ */
+loglevels setlogthreshold(loglevels loglevel);
+
+/*
+ * logthing - output a log entry
+ * @loglevel: The level of the log.
+ * @format: A format string, followed by any parameters required.
+ *
+ * This function outputs a log entry. A leading time/date stamp and a
+ * trailing newline are automatically added. The loglevel is compared to
+ * the current log threshold and if equal or above the log entry is
+ * output. The format parameter is of the same nature as that used in
+ * printf.
+ */
+int logthing(loglevels loglevel, const char *format, ...);
+
+#endif /* __LOG_H__ */
#include "getcgi.h"
#include "keydb.h"
#include "keyindex.h"
+#include "log.h"
#include "mem.h"
#include "onak-conf.h"
#include "parsekey.h"
puts("Error: No key to search for supplied.");
} else {
readconfig();
+ initlogthing("lookup", config.logfile);
initdb();
switch (op) {
case OP_GET:
puts("Unknown operation!");
}
cleanupdb();
+ cleanuplogthing();
cleanupconfig();
}
puts("<hr>");
#include "keyid.h"
#include "keystructs.h"
#include "ll.h"
+#include "log.h"
#include "mem.h"
#include "merge.h"
/**
* update_keys - Takes a list of public keys and updates them in the DB.
* @keys: The keys to update in the DB.
- * @verbose: Should we output more information as we add keys?
*
* 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
* 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, bool verbose)
+int update_keys(struct openpgp_publickey **keys)
{
struct openpgp_publickey *curkey = NULL;
struct openpgp_publickey *oldkey = NULL;
for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
intrans = starttrans();
- if (verbose) {
- fprintf(stderr, "Fetching key 0x%llX, result: %d\n",
- get_keyid(curkey),
- fetch_key(get_keyid(curkey), &oldkey, intrans));
- } else {
- fetch_key(get_keyid(curkey), &oldkey, intrans);
- }
+ logthing(LOGTHING_INFO,
+ "Fetching key 0x%llX, result: %d",
+ get_keyid(curkey),
+ fetch_key(get_keyid(curkey), &oldkey, intrans));
/*
* If we already have the key stored in the DB then merge it
}
} else {
prev = curkey;
- if (verbose) {
- fprintf(stderr,
- "Merged key; storing updated key.\n");
- }
+ logthing(LOGTHING_INFO,
+ "Merged key; storing updated key.");
store_key(oldkey, intrans, true);
}
free_publickey(oldkey);
oldkey = NULL;
} else {
- if (verbose) {
- fprintf(stderr,
- "Storing completely new key.\n");
- }
+ logthing(LOGTHING_INFO,
+ "Storing completely new key.");
store_key(curkey, intrans, false);
newkeys++;
}
/**
* update_keys - Takes a list of public keys and updates them in the DB.
* @keys: The keys to update in the DB.
- * @verbose: Should we output more information as we add keys?
*
* 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
* 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, bool verbose);
+int update_keys(struct openpgp_publickey **keys);
#endif
#include <string.h>
#include "ll.h"
+#include "log.h"
#include "onak-conf.h"
/*
NULL, /* adminemail */
NULL, /* mta */
NULL, /* syncsites */
+ NULL, /* logfile */
/*
* Options for directory backends.
} else if (!strncmp("syncsite ", curline, 9)) {
config.syncsites =
lladd(config.syncsites, strdup(&curline[9]));
+ } else if (!strncmp("logfile ", curline, 8)) {
+ config.logfile = strdup(&curline[8]);
} else if (!strncmp("this_site ", curline, 10)) {
config.thissite = strdup(&curline[10]);
} else if (!strncmp("socket_name ", curline, 12) ||
* Not applicable; ignored for compatibility with pksd.
*/
} else {
- fprintf(stderr, "Unknown config line: %s\n", curline);
+ logthing(LOGTHING_ERROR,
+ "Unknown config line: %s", curline);
}
fgets(curline, 1023, conffile);
}
fclose(conffile);
} else {
- fprintf(stderr, "Couldn't open config file; using defaults.\n");
+ logthing(LOGTHING_NOTICE,
+ "Couldn't open config file; using defaults.");
}
}
llfree(config.syncsites, free);
config.syncsites = NULL;
}
+ if (config.logfile != NULL) {
+ free(config.logfile);
+ config.logfile = NULL;
+ }
}
char *adminemail;
char *mta;
struct ll *syncsites;
+ char *logfile;
/*
* Options for any database backend that needs a directory, be it the
#include "keyid.h"
#include "keyindex.h"
#include "keystructs.h"
+#include "log.h"
#include "mem.h"
#include "merge.h"
#include "onak-conf.h"
break;
case 'v':
verbose = true;
+ setlogthreshold(LOGTHING_INFO);
break;
}
}
readconfig();
+ initlogthing("onak", config.logfile);
if ((argc - optind) < 1) {
usage();
if (binary) {
result = read_openpgp_stream(stdin_getchar, NULL,
&packets);
- if (verbose) {
- fprintf(stderr,
- "read_openpgp_stream: %d\n", result);
- }
+ logthing(LOGTHING_INFO,
+ "read_openpgp_stream: %d", result);
} else {
dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
}
result = parse_keys(packets, &keys);
free_packet_list(packets);
packets = NULL;
- if (verbose) {
- fprintf(stderr, "Finished reading %d keys.\n",
+ logthing(LOGTHING_INFO, "Finished reading %d keys.",
result);
- }
initdb();
- fprintf(stderr, "Got %d new keys.\n",
- update_keys(&keys, verbose));
+ logthing(LOGTHING_NOTICE, "Got %d new keys.",
+ update_keys(&keys));
if (keys != NULL && update) {
flatten_publickey(keys,
&packets,
cleanupdb();
} else {
rc = 1;
- fprintf(stderr, "No keys read.\n");
+ logthing(LOGTHING_NOTICE, "No keys read.");
}
if (keys != NULL) {
keys = NULL;
} else {
rc = 1;
- fprintf(stderr, "No changes.\n");
+ logthing(LOGTHING_NOTICE, "No changes.");
}
} else if ((argc - optind) == 2) {
search = argv[optind+1];
delete_key(getfullkeyid(keyid), false);
} else if (!strcmp("get", argv[optind])) {
if (fetch_key(keyid, &keys, false)) {
- if (verbose) {
- fprintf(stderr, "Got key.\n");
- }
+ logthing(LOGTHING_INFO, "Got key.");
flatten_publickey(keys,
&packets,
&list_end);
usage();
}
+ cleanuplogthing();
cleanupconfig();
return rc;
#include "keyid.h"
#include "keystructs.h"
#include "ll.h"
+#include "log.h"
#include "mem.h"
#include "parsekey.h"
*/
break;
default:
- fprintf(stderr, "Unsupported packet type: %d\n",
+ logthing(LOGTHING_ERROR,
+ "Unsupported packet type: %d",
packets->packet->tag);
}
packets = packets->next;
curpacket->packet->length += curchar;
break;
case 3:
- fprintf(stderr, "Unsupported length type 3.\n");
+ logthing(LOGTHING_ERROR,
+ "Unsupported length type 3.");
curpacket->packet->length = 0;
curpacket->packet->data = NULL;
rc = -1;
}
inpacket = false;
} else {
- fprintf(stderr, "Unexpected character: 0x%X\n",
+ logthing(LOGTHING_ERROR, "Unexpected character: 0x%X",
curchar);
}
}
0xFF;
putchar_func(ctx, 1, &curchar);
} else {
- fputs("Unsupported new format length.\n", stderr);
+ logthing(LOGTHING_ERROR,
+ "Unsupported new format length.");
}
} else {
curchar |= (packets->packet->tag << 2);