update TODO, partially update error.c, rename module_get to modules_get, update config.lua
#include "logwatch.h"
#include "../config.h"
#include "../log.h"
#include <assert.h>
static err_t logwatch_init (struct nexus *nexus, void **ctx_ptr, struct error_info *err)
{
struct logwatch *ctx;
// allocate
if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
RETURN_SET_ERROR(err, ERR_CALLOC);
// init
TAILQ_INIT(&ctx->sources);
TAILQ_INIT(&ctx->filters);
TAILQ_INIT(&ctx->channels);
// store
ctx->nexus = nexus;
// ok
*ctx_ptr = ctx;
return SUCCESS;
}
struct logwatch_chan* logwatch_get_chan (struct logwatch *ctx, struct irc_chan *irc_chan)
{
struct logwatch_chan *chan;
// existing?
if ((chan = logwatch_chan_lookup(ctx, irc_chan))) {
// get ref
chan->refcount++;
} else {
// create a new one with a ref
// XXX: errors...
chan = logwatch_chan_create(ctx, irc_chan);
}
// ok
return chan;
}
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, %s, %s): %s", filter->name, source->name, line, error_msg(&err));
}
}
void logwatch_on_error (struct logwatch *ctx, const struct logwatch_source *source, const struct error_info *err)
{
struct logwatch_chan *chan;
// 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));
}
}
/**
* Add a logwatch_source with a FIFO at the given path
*/
static err_t logwatch_conf_source_fifo (void *_ctx, const struct config_option *option, const struct config_value values[], struct error_info *err)
{
struct logwatch *ctx = _ctx;
// parse arguments
const char *path = config_get_string(option, values, "path");
// open it
if (logwatch_open_fifo(ctx, path, err) == NULL)
return ERROR_CODE(err);
// ok
return SUCCESS;
}
/**
* Add a logwatch_filter for the given bits
*/
static err_t logwatch_conf_filter (void *_ctx, const struct config_option *option, const struct config_value values[], struct error_info *err)
{
struct logwatch *ctx = _ctx;
struct logwatch_filter *filter;
const struct logwatch_source *source = NULL;
struct logwatch_chan *chan;
const char *name, *source_name, *pattern, *format;
struct irc_chan *irc_chan;
// parse arguments
name = config_get_string (option, values, "name" );
source_name = config_get_string (option, values, "source" );
pattern = config_get_string (option, values, "pattern" );
format = config_get_string (option, values, "format" );
irc_chan = config_get_irc_chan (option, values, "chan" );
// lookup name
if (source_name && (source = logwatch_source_lookup(ctx, source_name)) == NULL)
RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown logwatch_source name");
// lookup the channel
if ((chan = logwatch_get_chan(ctx, irc_chan)) == NULL)
RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "logwatch_get_chan failed");
log_info("add filter: name=%s, source=%s, pattern=%s, format=%s, chan=%s",
name, source_name, pattern, format, irc_chan_name(irc_chan));
// invoke
if ((filter = logwatch_filter(ctx, name, source, pattern, format, chan, err)) == NULL)
goto error;
// ok
return SUCCESS;
error:
return ERROR_CODE(err);
}
/**
* Configuration options
*/
struct config_option logwatch_config_options[] = CONFIG_OPTIONS(
CONFIG_OPT( "source_fifo", logwatch_conf_source_fifo,
"read input lines from the FIFO at the given path",
CONFIG_PARAM( "path", CONFIG_STRING, "filesystem path to FIFO", false )
),
CONFIG_OPT( "filter", logwatch_conf_filter,
"filter lines from source (or all), using the given regular expression (or all lines), and format output "
"using the given format expression (or pass through directly), and finally send the output to the given channel",
CONFIG_PARAM( "name", CONFIG_STRING, "filter name", false ),
CONFIG_PARAM( "source", CONFIG_STRING, "optional logwatch_source to use", true ),
CONFIG_PARAM( "pattern", CONFIG_STRING, "optional regular expression pattern", true ),
CONFIG_PARAM( "format", CONFIG_STRING, "optional output format", true ),
CONFIG_PARAM( "chan", CONFIG_IRC_CHAN, "channel to send output to", false )
)
);
static void logwatch_destroy (void *_ctx)
{
struct logwatch *ctx = _ctx;
struct logwatch_filter *filter;
struct logwatch_source *source;
// flush the filters list
while ((filter = TAILQ_FIRST(&ctx->filters)))
logwatch_filter_destroy(filter);
// flush the sources list
while ((source = TAILQ_FIRST(&ctx->sources)))
logwatch_source_destroy(source);
// release the context
free(ctx);
}
/**
* The module function table
*/
struct module_desc logwatch_module = {
.init = logwatch_init,
.config_options = logwatch_config_options,
.unload = NULL,
.destroy = logwatch_destroy
};