From b78e45ed120acb429b90ddfeaa12fa722ecdfae2 Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Tue, 13 Sep 2016 22:02:28 +1000 Subject: [PATCH] + src/source.[ch] --- src/CMakeLists.txt | 2 +- src/source.c | 113 +++++++++++++++++++++++++++++++++++++++++++++ src/source.h | 32 +++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/source.c create mode 100644 src/source.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 61074fe..9bc1a9f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(SOURCES "daemon.c" "strlcpy.c" "logfile.c" "log.c" "matches.c" "ipaddr.c" "filelist.c" "filter.c" "config.c" "jail.c" "backend.c") +set(SOURCES "daemon.c" "strlcpy.c" "logfile.c" "log.c" "matches.c" "source.c" "ipaddr.c" "filelist.c" "filter.c" "config.c" "jail.c" "backend.c") if (WITH_CSOCKET) list(APPEND SOURCES "csocket.c" "cmsg.c") diff --git a/src/source.c b/src/source.c new file mode 100644 index 0000000..7c11f03 --- /dev/null +++ b/src/source.c @@ -0,0 +1,113 @@ +/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "common.h" +#include "source.h" + +#define SOURCE_LIBRARY_PARAM "load" + +f2b_source_t * +f2b_source_create(f2b_config_section_t *config, const char *init, void (*errcb)(const char *)) { + f2b_config_param_t *param = NULL; + f2b_source_t *source = NULL; + int flags = RTLD_NOW | RTLD_LOCAL; + const char *dlerr = NULL; + + assert(config != NULL); + assert(config->type == t_source); + + param = f2b_config_param_find(config->param, SOURCE_LIBRARY_PARAM); + if (!param) { + f2b_log_msg(log_error, "can't find '%s' param in source config", SOURCE_LIBRARY_PARAM); + return NULL; + } + + if ((source = calloc(1, sizeof(f2b_source_t))) == NULL) + return NULL; + + if ((source->h = dlopen(param->value, flags)) == NULL) + goto cleanup; + if ((*(void **) (&source->create) = dlsym(source->h, "create")) == NULL) + goto cleanup; + if ((*(void **) (&source->config) = dlsym(source->h, "config")) == NULL) + goto cleanup; + if ((*(void **) (&source->ready) = dlsym(source->h, "ready")) == NULL) + goto cleanup; + if ((*(void **) (&source->error) = dlsym(source->h, "error")) == NULL) + goto cleanup; + if ((*(void **) (&source->errcb) = dlsym(source->h, "errcb")) == NULL) + goto cleanup; + if ((*(void **) (&source->start) = dlsym(source->h, "start")) == NULL) + goto cleanup; + if ((*(void **) (&source->next) = dlsym(source->h, "next")) == NULL) + goto cleanup; + if ((*(void **) (&source->stop) = dlsym(source->h, "stop")) == NULL) + goto cleanup; + if ((*(void **) (&source->destroy) = dlsym(source->h, "destroy")) == NULL) + goto cleanup; + + if ((source->cfg = source->create(init)) == NULL) { + f2b_log_msg(log_error, "source create config failed"); + goto cleanup; + } + + /* try init */ + for (param = config->param; param != NULL; param = param->next) { + if (strcmp(param->name, SOURCE_LIBRARY_PARAM) == 0) + continue; + if (source->config(source->cfg, param->name, param->value)) + continue; + f2b_log_msg(log_warn, "param pair not accepted by source '%s': %s=%s", + config->name, param->name, param->value); + } + + if (errcb) + source->errcb(source->cfg, errcb); + + if (source->ready(source->cfg)) + return source; + + /* still not ready */ + f2b_log_msg(log_error, "source '%s' not fully configured", config->name); + + cleanup: + dlerr = dlerror(); + if (dlerr) + f2b_log_msg(log_error, "source load error: %s", dlerr); + if (source->h) { + if (source->cfg && source->destroy) + source->destroy(source->cfg); + dlclose(source->h); + } + free(source); + return NULL; +} + +void +f2b_source_destroy(f2b_source_t *source) { + assert(source != NULL); + source->destroy(source->cfg); + dlclose(source->h); + free(source); +} + +bool +f2b_source_next(f2b_source_t *source, char *buf, size_t bufsize, bool reset) { + assert(source != NULL); + return source->next(source->cfg, buf, bufsize, reset); +} + +#define SOURCE_CMD_ARG0(CMD, RETURNS) \ +RETURNS \ +f2b_source_ ## CMD(f2b_source_t *source) { \ + assert(source != NULL); \ + return source->CMD(source->cfg); \ +} + +SOURCE_CMD_ARG0(error, const char *) +SOURCE_CMD_ARG0(start, bool) +SOURCE_CMD_ARG0(stop, bool) +SOURCE_CMD_ARG0(ready, bool) diff --git a/src/source.h b/src/source.h new file mode 100644 index 0000000..2766f68 --- /dev/null +++ b/src/source.h @@ -0,0 +1,32 @@ +/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef F2B_SOURCE_H_ +#define F2B_SOURCE_H_ + +#include "config.h" +#include "log.h" + +typedef struct f2b_source_t { + void *h; + void *cfg; + void *(*create) (const char *init); + bool (*config) (void *cfg, const char *key, const char *value); + bool (*ready) (void *cfg); + char *(*error) (void *cfg); + void (*errcb) (void *cfg, void (*cb)(const char *errstr)); + bool (*start) (void *cfg); + bool (*next) (void *cfg, char *buf, size_t bufsize, bool reset); + bool (*stop) (void *cfg); + void (*destroy) (void *cfg); +} f2b_source_t; + +f2b_source_t * f2b_source_create (f2b_config_section_t *config, const char *init, void (*errcb)(const char *)); +void f2b_source_destroy (f2b_source_t *s); +bool f2b_source_next (f2b_source_t *s, char *buf, size_t bufsize, bool reset); +const char * f2b_source_error (f2b_source_t *s); + +#endif /* F2B_SOURCE_H_ */