]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
missing
authorTimo Sirainen <tss@iki.fi>
Wed, 14 May 2003 18:23:40 +0000 (21:23 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 14 May 2003 18:23:40 +0000 (21:23 +0300)
--HG--
branch : HEAD

src/lib/module-dir.c [new file with mode: 0644]
src/lib/module-dir.h [new file with mode: 0644]

diff --git a/src/lib/module-dir.c b/src/lib/module-dir.c
new file mode 100644 (file)
index 0000000..4a58d8f
--- /dev/null
@@ -0,0 +1,131 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+#include "module-dir.h"
+
+#ifdef HAVE_MODULES
+
+#include <unistd.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+static void *get_symbol(const char *path, void *handle, const char *symbol)
+{
+       const char *error;
+       void *ret;
+
+       /* get our init func */
+       ret = dlsym(handle, symbol);
+
+       error = dlerror();
+       if (error != NULL) {
+               i_error("module %s: dlsym(%s) failed: %s", path, symbol, error);
+               ret = NULL;
+       }
+
+       return ret;
+}
+
+static struct module *module_load(const char *path, const char *name)
+{
+       void *handle;
+       void (*init)(void);
+       void (*deinit)(void);
+       struct module *module;
+
+       handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
+       if (handle == NULL) {
+               i_error("dlopen(%s) failed: %s", path, dlerror());
+               return NULL;
+       }
+
+       /* get our init func */
+       init = get_symbol(path, handle, t_strconcat(name, "_init", NULL));
+       deinit = init == NULL ? NULL :
+               get_symbol(path, handle, t_strconcat(name, "_deinit", NULL));
+
+       if (init == NULL || deinit == NULL) {
+               (void)dlclose(handle);
+               return NULL;
+       }
+
+       init();
+
+       module = i_new(struct module, 1);
+       module->handle = handle;
+       module->deinit = deinit;
+       return module;
+}
+
+struct module *module_dir_load(const char *dir)
+{
+       DIR *dirp;
+       struct dirent *d;
+       const char *name, *path, *p;
+       struct module *modules, *module;
+
+       dirp = opendir(dir);
+       if (dirp == NULL) {
+               i_error("opendir(%s) failed: %m", dir);
+               return NULL;
+       }
+
+       modules = NULL;
+       while ((d = readdir(dirp)) != NULL) {
+               name = d->d_name;
+
+               if (name[0] == '.')
+                       continue;
+
+               p = strstr(name, ".so");
+               if (p == NULL || strlen(p) != 3)
+                       continue;
+
+               if (strncmp(name, "lib", 3) == 0)
+                       name += 3;
+
+               t_push();
+               name = t_strdup_until(d->d_name, p);
+               path = t_strconcat(dir, "/", d->d_name, NULL);
+               module = module_load(path, name);
+               t_pop();
+
+               if (module != NULL) {
+                       module->next = modules;
+                       modules = module;
+               }
+       }
+
+       if (closedir(dirp) < 0)
+               i_error("closedir(%s) failed: %m", dir);
+
+       return modules;
+}
+
+void module_dir_unload(struct module *modules)
+{
+       struct module *next;
+
+       while (modules != NULL) {
+               next = modules->next;
+               modules->deinit();
+               if (dlclose(modules->handle) != 0)
+                       i_error("dlclose() failed: %m");
+               i_free(modules);
+               modules = next;
+       }
+}
+
+#else
+
+struct module *module_dir_load(const char *dir __attr_unused__)
+{
+       i_error("Dynamically loadable module support not built in");
+       return NULL;
+}
+
+void module_dir_unload(struct module *modules __attr_unused__)
+{
+}
+
+#endif
diff --git a/src/lib/module-dir.h b/src/lib/module-dir.h
new file mode 100644 (file)
index 0000000..53b293c
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __MODULE_DIR_H
+#define __MODULE_DIR_H
+
+struct module {
+       void *handle;
+       void (*deinit)(void);
+
+        struct module *next;
+};
+
+/* Load all modules in given directory. */
+struct module *module_dir_load(const char *dir);
+/* Unload all modules */
+void module_dir_unload(struct module *modules);
+
+#endif