--- a/src/CMakeLists.txt Sun Apr 12 17:18:06 2009 +0300
+++ b/src/CMakeLists.txt Sun Apr 12 17:42:34 2009 +0300
@@ -19,7 +19,7 @@
set (NEXUS_SOURCES nexus.c ${CORE_SOURCES} ${SOCK_SOURCES} ${IRC_SOURCES} ${LUA_SOURCES} ${CONSOLE_SOURCES} signals.c module.c config.c)
set (TEST_SOURCES test.c ${CORE_SOURCES} ${SOCK_SOURCES} ${IRC_SOURCES})
set (IRC_LOG_SOURCES modules/irc_log.c)
-set (LOGWATCH_SOURCES modules/logwatch.c modules/logwatch_source.c modules/logwatch_filter.c)
+set (LOGWATCH_SOURCES modules/logwatch.c modules/logwatch_source.c modules/logwatch_filter.c modules/logwatch_chan.c)
# define our libraries
set (MODULE_LIBRARIES "dl")
--- a/src/modules/logwatch.c Sun Apr 12 17:18:06 2009 +0300
+++ b/src/modules/logwatch.c Sun Apr 12 17:42:34 2009 +0300
@@ -27,60 +27,6 @@
return SUCCESS;
}
-/**
- * Look for an existing logwatch_chan entry, returning it if it exists
- */
-static struct logwatch_chan* logwatch_chan_lookup (struct logwatch *ctx, struct irc_chan *irc_chan)
-{
- struct logwatch_chan *chan;
-
- // look for it
- TAILQ_FOREACH(chan, &ctx->channels, logwatch_channels)
- if (chan->irc_chan == irc_chan)
- return chan;
-
- // not found
- return NULL;
-}
-
-/**
- * Create a new irc_chan with an initial refcount of one
- */
-static struct logwatch_chan* logwatch_chan_create (struct logwatch *ctx, struct irc_chan *irc_chan)
-{
- struct logwatch_chan *chan;
-
- // alloc
- if ((chan = calloc(1, sizeof(*chan))) == NULL)
- return NULL;
-
- // store
- chan->ctx = ctx;
- chan->irc_chan = irc_chan;
- chan->refcount = 1;
-
- // add
- TAILQ_INSERT_TAIL(&ctx->channels, chan, logwatch_channels);
-
- // ok
- return chan;
-}
-
-/**
- * Destroy a logwatch_chan
- */
-static void logwatch_chan_destroy (struct logwatch_chan *chan)
-{
- // XXX: check refcount
- assert(chan->refcount == 0);
-
- // remove
- TAILQ_REMOVE(&chan->ctx->channels, chan, logwatch_channels);
-
- // release
- free(chan);
-}
-
struct logwatch_chan* logwatch_get_chan (struct logwatch *ctx, struct irc_chan *irc_chan)
{
struct logwatch_chan *chan;
@@ -100,19 +46,6 @@
return chan;
}
-void logwatch_put_chan (struct logwatch_chan *chan)
-{
- // valid refcount
- assert(chan->refcount);
-
- // still alive?
- if (--chan->refcount)
- return;
-
- // destroy
- logwatch_chan_destroy(chan);
-}
-
void logwatch_on_line (struct logwatch *ctx, const struct logwatch_source *source, const char *line)
{
const struct logwatch_filter *filter;
@@ -125,12 +58,20 @@
}
}
+
void logwatch_on_error (struct logwatch *ctx, const struct logwatch_source *source, const struct error_info *err)
{
struct logwatch_chan *chan;
- struct logwatch_filter *filter;
// notify each relevant channel
+ TAILQ_FOREACH(chan, &ctx->channels, logwatch_channels) {
+ // skip irrelevant channels
+ if (!logwatch_chan_has_source(chan, source))
+ continue;
+
+ // send an error message
+ logwatch_chan_msg(chan, "!!! Source '%s' failed: %s", source->name, error_msg(err));
+ }
}
/**
--- a/src/modules/logwatch.h Sun Apr 12 17:18:06 2009 +0300
+++ b/src/modules/logwatch.h Sun Apr 12 17:42:34 2009 +0300
@@ -53,6 +53,13 @@
};
/**
+ * Maximum length of a logwatch_chan message, not including NUL byte
+ *
+ * XXX: this is a bad way to handle truncation
+ */
+#define LOGWATCH_CHAN_MSG_MAX 470
+
+/**
* A filter specifies what lines to match, and how to then format the output.
*/
struct logwatch_filter {
@@ -90,7 +97,7 @@
#define LOGWATCH_FILTER_GROUPS_MAX 16
/**
- * Maximum length of output string, not including NUL byte
+ * Maximum length of logwatch_filter output
*/
#define LOGWATCH_FILTER_OUT_MAX 450
@@ -134,6 +141,33 @@
const struct logwatch_source* logwatch_source_lookup (struct logwatch *ctx, const char *name);
/**
+ * Returns true if the given chan is linked to the given source via at least one filter
+ */
+bool logwatch_chan_has_source (struct logwatch_chan *chan, const struct logwatch_source *source);
+
+/**
+ * Look for an existing logwatch_chan entry, returning it if it exists
+ */
+struct logwatch_chan* logwatch_chan_lookup (struct logwatch *ctx, struct irc_chan *irc_chan);
+
+/**
+ * Create a new irc_chan with an initial refcount of one.
+ *
+ * @returns NULL on ERR_CALLOC
+ */
+struct logwatch_chan* logwatch_chan_create (struct logwatch *ctx, struct irc_chan *irc_chan);
+
+/**
+ * Returns a logwatch_chan reference, destroying as needed.
+ */
+void logwatch_chan_put (struct logwatch_chan *chan);
+
+/**
+ * Send a notice of at most LOGWATCH_CHAN_MSG_MAX bytes to the channel using the given format string.
+ */
+err_t logwatch_chan_msg (struct logwatch_chan *chan, const char *fmt, ...);
+
+/**
* Find an existing logwatch_chan for the given channel, or create a new one. Returns a real reference that should be
* returned using logwatch_put_chan().
*
@@ -142,11 +176,6 @@
struct logwatch_chan* logwatch_get_chan (struct logwatch *ctx, struct irc_chan *irc_chan);
/**
- * Returns a reference aquired using logwatch_get_chan().
- */
-void logwatch_put_chan (struct logwatch_chan *chan);
-
-/**
* Add a new filter.
*
* The given logwatch_chan should be a new reference.
@@ -176,5 +205,7 @@
/**
* Handle a disasterous error on a logwatch_source by notifying any irc_chan's that it is linked to via our filters.
+ *
+ * The logwatch_source will dispose of itself after this.
*/
void logwatch_on_error (struct logwatch *ctx, const struct logwatch_source *source, const struct error_info *err);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/logwatch_chan.c Sun Apr 12 17:42:34 2009 +0300
@@ -0,0 +1,94 @@
+#include "logwatch.h"
+
+#include "../str.h"
+#include <assert.h>
+
+bool logwatch_chan_has_source (struct logwatch_chan *chan, const struct logwatch_source *source)
+{
+ const struct logwatch_filter *filter;
+
+ // look for a link
+ TAILQ_FOREACH(filter, &chan->ctx->filters, logwatch_filters)
+ if (filter->chan == chan && filter->source == source)
+ return true;
+
+ // no match
+ return false;
+}
+
+struct logwatch_chan* logwatch_chan_lookup (struct logwatch *ctx, struct irc_chan *irc_chan)
+{
+ struct logwatch_chan *chan;
+
+ // look for it
+ TAILQ_FOREACH(chan, &ctx->channels, logwatch_channels)
+ if (chan->irc_chan == irc_chan)
+ return chan;
+
+ // not found
+ return NULL;
+}
+
+/**
+ * Destroy a logwatch_chan
+ */
+static void logwatch_chan_destroy (struct logwatch_chan *chan)
+{
+ // XXX: check refcount
+ assert(chan->refcount == 0);
+
+ // remove
+ TAILQ_REMOVE(&chan->ctx->channels, chan, logwatch_channels);
+
+ // release
+ free(chan);
+}
+
+struct logwatch_chan* logwatch_chan_create (struct logwatch *ctx, struct irc_chan *irc_chan)
+{
+ struct logwatch_chan *chan;
+
+ // alloc
+ if ((chan = calloc(1, sizeof(*chan))) == NULL)
+ return NULL;
+
+ // store
+ chan->ctx = ctx;
+ chan->irc_chan = irc_chan;
+ chan->refcount = 1;
+
+ // add
+ TAILQ_INSERT_TAIL(&ctx->channels, chan, logwatch_channels);
+
+ // ok
+ return chan;
+}
+
+void logwatch_chan_put (struct logwatch_chan *chan)
+{
+ // valid refcount
+ assert(chan->refcount);
+
+ // still alive?
+ if (--chan->refcount)
+ return;
+
+ // destroy
+ logwatch_chan_destroy(chan);
+}
+
+err_t logwatch_chan_msg (struct logwatch_chan *chan, const char *fmt, ...)
+{
+ char buf[LOGWATCH_CHAN_MSG_MAX + 1];
+ va_list vargs;
+
+ // format the output
+ // XXX: overflow...
+ va_start(vargs, fmt);
+ str_append_fmt_va(buf, sizeof(buf), fmt, vargs);
+ va_end(vargs);
+
+ // send it
+ return irc_chan_NOTICE(chan->irc_chan, buf);
+}
+
--- a/src/modules/logwatch_filter.c Sun Apr 12 17:18:06 2009 +0300
+++ b/src/modules/logwatch_filter.c Sun Apr 12 17:42:34 2009 +0300
@@ -65,7 +65,7 @@
pcre_free(filter->regexp);
// release the logwatch_chan ref
- logwatch_put_chan(filter->chan);
+ logwatch_chan_put(filter->chan);
// free misc
free(filter->format);
@@ -141,8 +141,8 @@
err_t logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err)
{
int ovec[LOGWATCH_FILTER_OVEC_ITEMS], ret;
- char buf[LOGWATCH_FILTER_OUT_PREFIX_LEN + LOGWATCH_FILTER_OUT_MAX + 1], *buf_ptr = buf;
- size_t buf_size = LOGWATCH_FILTER_OUT_PREFIX_LEN + LOGWATCH_FILTER_OUT_MAX + 1;
+ char buf[LOGWATCH_FILTER_OUT_MAX + 1], *buf_ptr = buf;
+ size_t buf_size = sizeof(buf);
// XXX: what to do for truncated data?
@@ -165,9 +165,6 @@
RETURN_SET_ERROR_EXTRA(err, ERR_PCRE_EXEC, ret);
}
- // format header
- buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, LOGWATCH_FILTER_OUT_PREFIX_LEN + 1, "[%.12s] ", filter->name));
-
// format?
if (filter->format) {
// setup the ctx
@@ -184,13 +181,16 @@
} else {
// quote the entire line
+ // XXX: overflow
buf_ptr += str_advance(NULL, &buf_size, str_quote(buf_ptr, buf_size, line, -1));
+
}
+ // log
log_info("<%s>:%s -> %s:%s", source->name, line, irc_chan_name(filter->chan->irc_chan), buf);
-
- // then send it as a notice
- if ((ERROR_CODE(err) = irc_chan_NOTICE(filter->chan->irc_chan, buf)))
+
+ // send it
+ if ((ERROR_CODE(err) = logwatch_chan_msg(filter->chan, "[%s] %s", filter->name, buf)))
goto error;
// ok
--- a/src/modules/logwatch_source.c Sun Apr 12 17:18:06 2009 +0300
+++ b/src/modules/logwatch_source.c Sun Apr 12 17:42:34 2009 +0300
@@ -15,11 +15,9 @@
void logwatch_source_on_error (struct error_info *err, void *arg)
{
struct logwatch_source *source = arg;
-
- (void) source;
- // XXX: complain more loudly
- log_error("%s", error_msg(err));
+ // notify
+ logwatch_on_error(source->ctx, source, err);
// drop it
logwatch_source_destroy(source);
@@ -46,7 +44,7 @@
/**
* Initialize with the given sock
*/
-err_t logwatch_source_init (struct logwatch_source *source, struct logwatch *ctx, const char *name, struct sock_stream *stream, struct error_info *err)
+static err_t logwatch_source_init (struct logwatch_source *source, struct logwatch *ctx, const char *name, struct sock_stream *stream, struct error_info *err)
{
// duplicate name?
if (logwatch_source_lookup(ctx, name))
--- a/src/str.c Sun Apr 12 17:18:06 2009 +0300
+++ b/src/str.c Sun Apr 12 17:42:34 2009 +0300
@@ -2,7 +2,6 @@
#include <ctype.h>
#include <stdio.h>
-#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
@@ -46,22 +45,29 @@
return 1;
}
+size_t str_append_fmt_va (char *buf, size_t buf_size, const char *fmt, va_list vargs)
+{
+ int ret;
+
+ // do the formatting
+ ret = vsnprintf(buf, buf_size, fmt, vargs);
+
+ // XXX: not all vsnprintf implementations do this
+ assert(ret >= 0);
+
+ // ok
+ return ret;
+}
+
size_t str_append_fmt (char *buf, size_t buf_size, const char *fmt, ...)
{
va_list vargs;
int ret;
va_start(vargs, fmt);
-
- // do the formatting
- ret = vsnprintf(buf, buf_size, fmt, vargs);
-
+ ret = str_append_fmt_va(buf, buf_size, fmt, vargs);
va_end(vargs);
- // XXX: not all vsnprintf implementations do this
- assert(ret >= 0);
-
- // ok
return ret;
}
--- a/src/str.h Sun Apr 12 17:18:06 2009 +0300
+++ b/src/str.h Sun Apr 12 17:42:34 2009 +0300
@@ -7,6 +7,7 @@
* Miscellaneous string utility functions
*/
#include <sys/types.h>
+#include <stdarg.h>
#include "error.h"
/**
@@ -52,6 +53,13 @@
size_t str_append_fmt (char *buf, size_t buf_size, const char *fmt, ...);
/**
+ * Like str_append_fmt, but using a vargs list instead.
+ *
+ * @see str_append_fmt()
+ */
+size_t str_append_fmt_va (char *buf, size_t buf_size, const char *fmt, va_list vargs);
+
+/**
* Use str_append* to write out the quoted char value to the given buffer.
*/
size_t str_quote_char (char *buf, size_t buf_size, char c);