Alex 'AdUser' Z
8 years ago
3 changed files with 146 additions and 1 deletions
@ -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) |
@ -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_ */ |
Loading…
Reference in new issue