# HG changeset patch # User Tero Marttila # Date 1239413206 -10800 # Node ID 94e6c3b4230f54291104a0e2c64814264b31ae0a # Parent 8065a624ba373d306fbb155b490a173eaa286cd8 implement logwatch_on_line/logwatch_filter_apply, along with irc_*_NOTICE diff -r 8065a624ba37 -r 94e6c3b4230f src/error.h --- a/src/error.h Sat Apr 11 04:26:22 2009 +0300 +++ b/src/error.h Sat Apr 11 04:26:46 2009 +0300 @@ -111,6 +111,7 @@ /** pcre errors */ _ERR_PCRE = 0x000e00, ERR_PCRE_COMPILE, ///< pcre_compile: + ERR_PCRE_EXEC, ///< pcre_exec: /** General errors */ _ERR_GENERAL = 0xffff00, diff -r 8065a624ba37 -r 94e6c3b4230f src/irc_chan.c --- a/src/irc_chan.c Sat Apr 11 04:26:22 2009 +0300 +++ b/src/irc_chan.c Sat Apr 11 04:26:46 2009 +0300 @@ -392,3 +392,15 @@ return irc_conn_PRIVMSG(chan->net->conn, chan->info.channel, message); } +err_t irc_chan_NOTICE (struct irc_chan *chan, const char *message) +{ + // correct state + if (!chan->joined) + return ERR_IRC_CHAN_STATE; + + if (!chan->net->conn) + return ERR_IRC_NET_STATE; + + // send the PRIVMSG message + return irc_conn_NOTICE(chan->net->conn, chan->info.channel, message); +} diff -r 8065a624ba37 -r 94e6c3b4230f src/irc_chan.h --- a/src/irc_chan.h Sat Apr 11 04:26:22 2009 +0300 +++ b/src/irc_chan.h Sat Apr 11 04:26:46 2009 +0300 @@ -181,4 +181,12 @@ */ err_t irc_chan_PRIVMSG (struct irc_chan *chan, const char *message); +/** + * Send a NOTICE message to the channel. + * + * @param chan the IRC channel + * @param message the message to send + */ +err_t irc_chan_NOTICE (struct irc_chan *chan, const char *message); + #endif diff -r 8065a624ba37 -r 94e6c3b4230f src/irc_conn.c --- a/src/irc_conn.c Sat Apr 11 04:26:22 2009 +0300 +++ b/src/irc_conn.c Sat Apr 11 04:26:46 2009 +0300 @@ -388,6 +388,16 @@ return irc_conn_send(conn, &line); } +err_t irc_conn_NOTICE (struct irc_conn *conn, const char *target, const char *message) +{ + // NOTICE + struct irc_line line = { + NULL, "NOTICE", { target, message } + }; + + return irc_conn_send(conn, &line); +} + err_t irc_conn_QUIT (struct irc_conn *conn, const char *message) { err_t err; diff -r 8065a624ba37 -r 94e6c3b4230f src/irc_conn.h --- a/src/irc_conn.h Sat Apr 11 04:26:22 2009 +0300 +++ b/src/irc_conn.h Sat Apr 11 04:26:46 2009 +0300 @@ -318,6 +318,23 @@ err_t irc_conn_PRIVMSG (struct irc_conn *conn, const char *target, const char *message); /** + * Send a NOTICE messaeg to some target, usually a channel or another user (nickname). + * + * The same limitations on message length and data apply as for irc_conn_PRIVMSG. + * + * The only difference between PRIVMSG and NOTICE is that NOTICE messages should never generate an automated reply, + * hence, they are used for e.g. CTCP replies, and ideally, for IRC bot output. + * + * @param conn the IRC protocol connection + * @param target the message target, usually either a channel name or a nickname + * @param message the message to send + * + * Possible errors (from RFC2812): + * None. Servers do not ever reply to NOTICE messages. + */ +err_t irc_conn_NOTICE (struct irc_conn *conn, const char *target, const char *message); + +/** * Send a QUIT message to the server. The server will reply with an ERROR message and close the connection. * * This updates our state as disconnecting, and once EOF is recieved, the irc_conn_callbacks::on_quit callback is diff -r 8065a624ba37 -r 94e6c3b4230f src/modules/logwatch.c --- a/src/modules/logwatch.c Sat Apr 11 04:26:22 2009 +0300 +++ b/src/modules/logwatch.c Sat Apr 11 04:26:46 2009 +0300 @@ -1,6 +1,7 @@ #include "logwatch.h" #include "../config.h" +#include "../log.h" static err_t logwatch_init (struct nexus *nexus, void **ctx_ptr, struct error_info *err) { @@ -45,6 +46,18 @@ return NULL; } +void logwatch_on_line (struct logwatch *ctx, const struct logwatch_source *source, const char *line) +{ + const struct logwatch_filter *filter; + struct error_info err; + + // apply each filter + TAILQ_FOREACH(filter, &ctx->filters, logwatch_filters) { + if (logwatch_filter_apply(filter, source, line, &err)) + log_warn("logwatch_filter_apply(%s, %p, %s): %s", filter->name, source, line, error_msg(&err)); + } +} + /** * Add a logwatch_source with a FIFO at the given path */ @@ -112,7 +125,7 @@ * Deinitialize by freeing all filters, closing all sources, and releasing all channels. * * XXX: unused - */ + * / static err_t logwatch_unload (void *_ctx, struct module *module) { struct logwatch *ctx = _ctx; @@ -120,7 +133,7 @@ // XXX: implement return SUCCESS; -} +} */ static void logwatch_destroy (void *_ctx) { diff -r 8065a624ba37 -r 94e6c3b4230f src/modules/logwatch.h --- a/src/modules/logwatch.h Sat Apr 11 04:26:22 2009 +0300 +++ b/src/modules/logwatch.h Sat Apr 11 04:26:46 2009 +0300 @@ -65,6 +65,16 @@ }; /** + * Maximum number of capture groups in the filter's regexp + */ +#define LOGWATCH_FILTER_GROUPS_MAX 16 + +/** + * Maximum length of output string, not including NUL byte + */ +#define LOGWATCH_FILTER_OUT_MAX 450 + +/** * A channel for outputting logwatch output * * XXX; do we need this? @@ -129,3 +139,13 @@ */ void logwatch_filter_destroy (struct logwatch_filter *filter); +/** + * Pass the given line (from the given source) through the given filter + */ +err_t logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err); + +/** + * Handle a line from the given source by applying it to all filters + */ +void logwatch_on_line (struct logwatch *ctx, const struct logwatch_source *source, const char *line); + diff -r 8065a624ba37 -r 94e6c3b4230f src/modules/logwatch_filter.c --- a/src/modules/logwatch_filter.c Sat Apr 11 04:26:22 2009 +0300 +++ b/src/modules/logwatch_filter.c Sat Apr 11 04:26:46 2009 +0300 @@ -59,3 +59,59 @@ free(filter->name); free(filter); } + +// number of pcre ovec elemnents required +#define LOGWATCH_FILTER_OVEC_ITEMS ((LOGWATCH_FILTER_GROUPS_MAX + 1) * 3) + +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 out_buf[LOGWATCH_FILTER_OUT_MAX + 1]; + + // XXX: prefix output with filter->name tag + // XXX: implement output formatting + // XXX: escape the output data + // XXX: what to do for truncated data? + + // discard based on source? + if (filter->source && source != filter->source) + return SUCCESS; + + // match against the regexp + if ((ret = pcre_exec(filter->regexp, NULL, line, strlen(line), 0, 0, ovec, LOGWATCH_FILTER_OVEC_ITEMS)) <= 0) { + if (ret == PCRE_ERROR_NOMATCH) + // no match, ignore + return SUCCESS; + + else if (ret == 0) + // too many match groups + return SET_ERROR(err, -1); + + else + // misc. error + RETURN_SET_ERROR_EXTRA(err, ERR_PCRE_EXEC, ret); + } + + // format? + if (filter->format) { + return SET_ERROR(err, -2); + + } else { + // copy the line directly + if (strlen(line) > LOGWATCH_FILTER_OUT_MAX) + return SET_ERROR(err, -3); + + strcpy(out_buf, line); + } + + // then send it as a notice + if ((ERROR_CODE(err) = irc_chan_NOTICE(filter->chan, out_buf))) + goto error; + + // ok + return SUCCESS; + +error: + return ERROR_CODE(err); +} + diff -r 8065a624ba37 -r 94e6c3b4230f src/modules/logwatch_source.c --- a/src/modules/logwatch_source.c Sat Apr 11 04:26:22 2009 +0300 +++ b/src/modules/logwatch_source.c Sat Apr 11 04:26:46 2009 +0300 @@ -6,14 +6,18 @@ void logwatch_source_on_line (char *line, void *arg) { struct logwatch_source *source = arg; - - log_info("%s", line); + + // apply it to the logwatch's filters + logwatch_on_line(source->ctx, source, line); } 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)); } @@ -27,6 +31,7 @@ */ err_t logwatch_source_init (struct logwatch_source *source, struct logwatch *ctx, struct sock_stream *stream, struct error_info *err) { + // store source->ctx = ctx; // create the lp to wrap the sock