]> git.itanic.dy.fi Git - rrdd/commitdiff
Introduce plugin manager
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Mon, 19 Nov 2012 15:31:18 +0000 (17:31 +0200)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Mon, 19 Nov 2012 15:43:55 +0000 (17:43 +0200)
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 <timo.t.kokkonen@iki.fi>
Makefile
plugin.h [new file with mode: 0644]
plugin_manager.c [new file with mode: 0644]
plugin_manager.h [new file with mode: 0644]

index 0681fd77ae852a90c8c97f21b3aabd78c95d2aa1..db48947d2952d7fead3e7337693af5d8cf728c37 100644 (file)
--- 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 (file)
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 (file)
index 0000000..a645f4e
--- /dev/null
@@ -0,0 +1,39 @@
+#include <dlfcn.h>
+
+#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 (file)
index 0000000..5d894b5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PLUGIN_MANAGER_H
+#define _PLUGIN_MANAGER_H
+
+int load_plugin(const char *path);
+
+#endif