From: Timo Kokkonen Date: Mon, 19 Nov 2012 15:31:18 +0000 (+0200) Subject: Introduce plugin manager X-Git-Url: http://git.itanic.dy.fi/?p=rrdd;a=commitdiff_plain;h=11d80cb5b7fc55765fddb94ab3780a4255c79066 Introduce plugin manager Plugin manager can load plugins at run time from libraries. It expects the plugin to contain one symbol, which contains plugin_info structure defined in plugin.h file. The .init function is executed from within the structure. Add -rdynamic compiler flag in order to make the existing symbols become visible to the dynamically loaded libraries. Signed-off-by: Timo Kokkonen --- diff --git a/Makefile b/Makefile index 0681fd7..db48947 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LD=ld CFLAGS=-Wall -O2 -g RRDD_OBJS= main.o process.o rrdtool.o parser.o string.o \ - debug.o config.o onewire_parser.o + debug.o config.o onewire_parser.o plugin_manager.o ALL_OBJS = $(RRDD_OBJS) ALL_DEBS = $(patsubst %.o,.%.o.d,$(ALL_OBJS)) @@ -21,7 +21,7 @@ endif all: rrdd rrdd: $(RRDD_OBJS) - $(QUIET_LINK)$(CC) -o rrdd $(RRDD_OBJS) -lconfig -lownet + $(QUIET_LINK)$(CC) -o rrdd $(RRDD_OBJS) -lconfig -lownet -ldl -rdynamic clean: rm -vf rrdd *~ *.o .*.d diff --git a/plugin.h b/plugin.h new file mode 100644 index 0000000..da22b4d --- /dev/null +++ b/plugin.h @@ -0,0 +1,14 @@ +#ifndef _PLUGIN_H +#define _PLUGIN_H + +typedef int (plugin_init_fn_t)(void); + +struct plugin_info { + /* Name of the plugin, used in debug prints */ + const char *name; + + /* This gets executed once the plugin is loaded */ + plugin_init_fn_t *init; +}; + +#endif diff --git a/plugin_manager.c b/plugin_manager.c new file mode 100644 index 0000000..a645f4e --- /dev/null +++ b/plugin_manager.c @@ -0,0 +1,39 @@ +#include + +#include "plugin_manager.h" +#include "plugin.h" +#include "debug.h" + +int load_plugin(const char *path) +{ + struct plugin_info *info; + void *handle; + int ret = -1; + + handle = dlopen(path, RTLD_NOW); + if (!handle) { + pr_err("Failed to load plugin %s: %s\n", path, dlerror()); + return -1; + } + + info = dlsym(handle, "plugin_info"); + if (!info) { + pr_err("Plugin %s does not contain plugin info\n", path); + goto out; + } + + if (!info->init) { + pr_err("Plugin info structure has NULL .init callback\n"); + goto out; + } + + ret = info->init(); + pr_info("Loading plugin %s %s\n", path, + ret ? "failed" : "succeeded"); + +out: + if (ret) + dlclose(handle); + + return ret; +} diff --git a/plugin_manager.h b/plugin_manager.h new file mode 100644 index 0000000..5d894b5 --- /dev/null +++ b/plugin_manager.h @@ -0,0 +1,6 @@ +#ifndef _PLUGIN_MANAGER_H +#define _PLUGIN_MANAGER_H + +int load_plugin(const char *path); + +#endif