summaryrefslogtreecommitdiffstats
path: root/src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/module.c b/src/module.c
new file mode 100644
index 00000000..bcd0b6c0
--- /dev/null
+++ b/src/module.c
@@ -0,0 +1,98 @@
+#include <stdlib.h>
+#include <assert.h>
+
+#include "module.h"
+
+struct module* module_load(struct core *c, const char *name, const char *argument) {
+ struct module *m = NULL;
+
+ assert(c && name);
+
+ m = malloc(sizeof(struct module));
+ assert(m);
+
+ if (!(m->dl = lt_dlopenext(name)))
+ goto fail;
+
+ if (!(m->init = lt_dlsym(m->dl, "module_init")))
+ goto fail;
+
+ if (!(m->done = lt_dlsym(m->dl, "module_done")))
+ goto fail;
+
+ m->name = strdup(name);
+ m->argument = argument ? strdup(argument) : NULL;
+ m->userdata = NULL;
+
+ assert(m->init);
+ if (m->init(c, m) < 0)
+ goto fail;
+
+ if (!c->modules)
+ c->modules = idxset_new(NULL, NULL);
+
+ assert(c->modules);
+ r = idxset_put(c->modules, m, &m->index);
+ assert(r >= 0 && m->index != IDXSET_INVALID);
+ return m;
+
+fail:
+ if (m) {
+ if (m->dl)
+ lt_dlclose(m->dl);
+
+ free(m);
+ }
+
+ return NULL;
+}
+
+static void module_free(struct module *m) {
+ assert(m && m->done);
+ m->done(c, m);
+
+ lt_dlcose(m->dl);
+ free(m->name);
+ free(m->argument);
+ free(m);
+}
+
+void module_unload(struct core *c, struct module *m) {
+ struct module *m;
+ assert(c && index != IDXSET_INVALID);
+
+ assert(c->modules);
+ if (!(m = idxset_remove_by_data(c->modules, m, NULL)))
+ return;
+
+ module_free(m);
+}
+
+void module_unload_by_index(struct core *c, guint32_t index) {
+ struct module *m;
+ assert(c && index != IDXSET_INVALID);
+
+ assert(c->modules);
+ if (!(m = idxset_remove_by_index(c->modules, index)))
+ return;
+
+ module_free(m);
+}
+
+
+void free_callback(void *p, void *userdata) {
+ struct module *m = p;
+ assert(m);
+ module_free(m);
+}
+
+void module_unload_all(struct core *c) {
+ assert(c);
+
+ if (!c->modules)
+ return;
+
+ idxset_free(c->modules, free_callback, NULL);
+ c->modules = NULL;
+}
+