summaryrefslogtreecommitdiff
path: root/src/module.c
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
committerAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
commit98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch)
treeebc6ec71f44bff8c42e4eefced61948623df02fc /src/module.c
parente6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff)
baresip 0.4.10
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/module.c b/src/module.c
new file mode 100644
index 0000000..12b3d13
--- /dev/null
+++ b/src/module.c
@@ -0,0 +1,156 @@
+/**
+ * @file module.c Module loading
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "core.h"
+
+
+struct modapp {
+ struct mod *mod;
+ struct le le;
+};
+
+
+static struct list modappl;
+
+
+static void modapp_destructor(void *arg)
+{
+ struct modapp *modapp = arg;
+ list_unlink(&modapp->le);
+ mem_deref(modapp->mod);
+}
+
+
+#ifdef STATIC
+
+/* Declared in static.c */
+extern const struct mod_export *mod_table[];
+
+static const struct mod_export *find_module(const struct pl *pl)
+{
+ struct pl name;
+ uint32_t i;
+
+ if (re_regex(pl->p, pl->l, "[^.]+.[^]*", &name, NULL))
+ name = *pl;
+
+ for (i=0; ; i++) {
+ const struct mod_export *me = mod_table[i];
+ if (!me)
+ return NULL;
+ if (0 == pl_strcasecmp(&name, me->name))
+ return me;
+ }
+
+ return NULL;
+}
+#endif
+
+
+static int load_module(struct mod **modp, const struct pl *modpath,
+ const struct pl *name)
+{
+ char file[256];
+ struct mod *m = NULL;
+ int err = 0;
+
+ if (!name)
+ return EINVAL;
+
+#ifdef STATIC
+ /* Try static first */
+ err = mod_add(&m, find_module(name));
+ if (!err)
+ goto out;
+#endif
+
+ /* Then dynamic */
+ if (re_snprintf(file, sizeof(file), "%r/%r", modpath, name) < 0) {
+ err = ENOMEM;
+ goto out;
+ }
+ err = mod_load(&m, file);
+ if (err)
+ goto out;
+
+ out:
+ if (err) {
+ warning("module %r: %m\n", name, err);
+ }
+ else if (modp)
+ *modp = m;
+
+ return err;
+}
+
+
+static int module_handler(const struct pl *val, void *arg)
+{
+ (void)load_module(NULL, arg, val);
+ return 0;
+}
+
+
+static int module_tmp_handler(const struct pl *val, void *arg)
+{
+ struct mod *mod = NULL;
+ (void)load_module(&mod, arg, val);
+ mem_deref(mod);
+ return 0;
+}
+
+
+static int module_app_handler(const struct pl *val, void *arg)
+{
+ struct modapp *modapp;
+
+ modapp = mem_zalloc(sizeof(*modapp), modapp_destructor);
+ if (!modapp)
+ return ENOMEM;
+
+ if (load_module(&modapp->mod, arg, val)) {
+ mem_deref(modapp);
+ return 0;
+ }
+
+ list_prepend(&modappl, &modapp->le, modapp);
+
+ return 0;
+}
+
+
+int module_init(const struct conf *conf)
+{
+ struct pl path;
+ int err;
+
+ if (!conf)
+ return EINVAL;
+
+ if (conf_get(conf, "module_path", &path))
+ pl_set_str(&path, ".");
+
+ err = conf_apply(conf, "module", module_handler, &path);
+ if (err)
+ return err;
+
+ err = conf_apply(conf, "module_tmp", module_tmp_handler, &path);
+ if (err)
+ return err;
+
+ err = conf_apply(conf, "module_app", module_app_handler, &path);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+
+void module_app_unload(void)
+{
+ list_flush(&modappl);
+}