implement logwatch_filter::format using str_format
authorTero Marttila <terom@fixme.fi>
Sat, 11 Apr 2009 06:03:24 +0300
changeset 130 ffefb6d85ea6
parent 129 361740b82fe5
child 131 df949b399491
implement logwatch_filter::format using str_format
src/modules/logwatch.c
src/modules/logwatch.h
src/modules/logwatch_filter.c
--- a/src/modules/logwatch.c	Sat Apr 11 06:03:08 2009 +0300
+++ b/src/modules/logwatch.c	Sat Apr 11 06:03:24 2009 +0300
@@ -91,7 +91,7 @@
     pattern = config_get_string     (option, values, "pattern"  );
     format  = config_get_string     (option, values, "format"   );
     chan    = config_get_irc_chan   (option, values, "chan"     );
-    
+
     // invoke
     if ((filter = logwatch_filter(ctx, name, source, pattern, format, chan, err)) == NULL)
         goto error;
--- a/src/modules/logwatch.h	Sat Apr 11 06:03:08 2009 +0300
+++ b/src/modules/logwatch.h	Sat Apr 11 06:03:24 2009 +0300
@@ -129,7 +129,7 @@
 struct logwatch_chan* logwatch_add_chan (struct logwatch *ctx, struct irc_chan *chan, struct error_info *err);
 
 /**
- * Add a new filter
+ * Add a new filter.
  */
 struct logwatch_filter* logwatch_filter (struct logwatch *ctx, const char *name, const struct logwatch_source *source,
         const char *pattern, const char *fmt, struct irc_chan *chan, struct error_info *err);
--- a/src/modules/logwatch_filter.c	Sat Apr 11 06:03:08 2009 +0300
+++ b/src/modules/logwatch_filter.c	Sat Apr 11 06:03:24 2009 +0300
@@ -1,9 +1,12 @@
 #include "logwatch.h"
 #include "../str.h"
+#include "../log.h"
 
 #include <stdlib.h>
 #include <string.h>
 
+#include <assert.h>
+
 struct logwatch_filter* logwatch_filter (struct logwatch *ctx, const char *name, const struct logwatch_source *source,
         const char *pattern, const char *format, struct irc_chan *chan, struct error_info *err)
 {
@@ -61,6 +64,48 @@
     free(filter);
 }
 
+/**
+ * str_format context for logwatch_filter_apply operation
+ */
+struct logwatch_filter_str_format_ctx {
+    /** The regexp we are processing */
+    pcre *regexp;
+
+    /** The subject string */
+    const char *subject;
+
+    /** The match group vector */
+    int *groups;
+    
+    /** Number of match items in groups */
+    size_t group_count;
+};
+
+static err_t logwatch_filter_str_format_cb (const char *name, const char **value, ssize_t *value_len, void *arg)
+{
+    struct logwatch_filter_str_format_ctx *ctx = arg;
+    int num;
+
+    // look it up
+    if (!ctx->regexp || (num = pcre_get_stringnumber(ctx->regexp, name)) < 0)
+        // no such capture group
+        return ERR_STR_FMT_NAME;
+
+    // sanity check
+    assert((size_t) num < ctx->group_count);
+
+    // look up the start/end offsets
+    int start = ctx->groups[num * 2 + 0];
+    int end = ctx->groups[num * 2 + 1];
+
+    // return a pointer to the subject
+    *value = ctx->subject + start;
+    *value_len = end - start;
+
+    // ok
+    return SUCCESS;
+}
+
 // number of pcre ovec elemnents required
 #define LOGWATCH_FILTER_OVEC_ITEMS ((LOGWATCH_FILTER_GROUPS_MAX + 1) * 3)
 
@@ -73,7 +118,6 @@
     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;
 
-    // XXX: implement output formatting
     // XXX: what to do for truncated data?
 
     // discard based on source?
@@ -96,17 +140,29 @@
     }
 
     // format header
-    buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, buf_size, "[%.12s] ", filter->name));
+    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) {
-        return SET_ERROR(err, -2);
+        // setup the ctx
+        struct logwatch_filter_str_format_ctx ctx = {
+            .regexp         = filter->regexp, 
+            .subject        = line,
+            .groups         = ovec,
+            .group_count    = ret 
+        };
+
+        // operate
+        if ((ERROR_CODE(err) = str_format(buf_ptr, buf_size, filter->format, logwatch_filter_str_format_cb, &ctx)))
+            goto error;
     
     } else {
         // quote the entire line
         buf_ptr += str_advance(NULL, &buf_size, str_quote(buf_ptr, buf_size, line, -1));
     }
 
+    log_info("%s:%p -> %s:%s", line, source, irc_chan_name(filter->chan), buf);
+
     // then send it as a notice
     if ((ERROR_CODE(err) = irc_chan_NOTICE(filter->chan, buf)))
         goto error;