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