implement logwatch_chan.c, logwatch_chan_msg, logwatch_on_error
authorTero Marttila <terom@fixme.fi>
Sun, 12 Apr 2009 17:42:34 +0300
changeset 133 e2d0c0c23b39
parent 132 f2ece471fb07
child 134 978041c1c04d
implement logwatch_chan.c, logwatch_chan_msg, logwatch_on_error
src/CMakeLists.txt
src/modules/logwatch.c
src/modules/logwatch.h
src/modules/logwatch_chan.c
src/modules/logwatch_filter.c
src/modules/logwatch_source.c
src/str.c
src/str.h
--- 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);