10 typedef int (*MODULE_INIT_FN)(
13 typedef int (*MODULE_LOAD_FN)(
15 const char *filename);
16 typedef int (*MODULE_TERM_FN)(void);
19 struct module_regtable_t {
22 } module_regtable[] = {
23 { "null", load_null_module },
24 #ifdef SLAPD_EXTERNAL_EXTENSIONS
25 { "extension", load_extop_module },
30 typedef struct module_loaded_t {
31 struct module_loaded_t *next;
35 module_loaded_t *module_list = NULL;
37 static int module_unload (module_loaded_t *module);
39 int module_init (void)
42 const char *error = lt_dlerror();
43 Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
49 int module_kill (void)
51 /* unload all modules before shutdown */
52 while (module_list != NULL) {
53 module_unload(module_list);
57 const char *error = lt_dlerror();
58 Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
64 int module_load(const char* file_name, int argc, char *argv[])
66 module_loaded_t *module = NULL;
69 MODULE_INIT_FN initialize;
71 module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t));
73 Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
79 * The result of lt_dlerror(), when called, must be cached prior
80 * to calling Debug. This is because Debug is a macro that expands
81 * into multiple function calls.
83 if ((module->lib = lt_dlopen(file_name)) == NULL) {
85 Debug(LDAP_DEBUG_ANY, "lt_dlopen failed: (%s) %s\n", file_name,
91 Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
93 if ((initialize = lt_dlsym(module->lib, "init_module")) == NULL) {
94 Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
96 lt_dlclose(module->lib);
101 /* The imported init_module() routine passes back the type of
102 * module (i.e., which part of slapd it should be hooked into)
103 * or -1 for error. If it passes back 0, then you get the
104 * old behavior (i.e., the library is loaded and not hooked
107 * It might be better if the conf file could specify the type
108 * of module. That way, a single module could support multiple
109 * type of hooks. This could be done by using something like:
111 * moduleload extension /usr/local/openldap/whatever.so
113 * then we'd search through module_regtable for a matching
114 * module type, and hook in there.
116 rc = initialize(argc, argv);
118 Debug(LDAP_DEBUG_CONFIG, "module %s: init_module() failed\n",
120 lt_dlclose(module->lib);
125 if (rc >= (sizeof(module_regtable) / sizeof(struct module_regtable_t))
126 || module_regtable[rc].proc == NULL)
128 Debug(LDAP_DEBUG_CONFIG, "module %s: unknown registration type (%d)\n",
130 module_unload(module);
134 rc = (module_regtable[rc].proc)(module, file_name);
136 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module could not be registered\n",
137 file_name, module_regtable[rc].type, 0);
138 module_unload(module);
142 module->next = module_list;
143 module_list = module;
145 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module registered\n",
146 file_name, module_regtable[rc].type, 0);
150 int module_path(const char *path)
152 return lt_dlsetsearchpath( path );
155 void *module_resolve (const void *module, const char *name)
157 if (module == NULL || name == NULL)
159 return(lt_dlsym(((module_loaded_t *)module)->lib, name));
162 static int module_unload (module_loaded_t *module)
164 module_loaded_t *mod;
165 MODULE_TERM_FN terminate;
167 if (module != NULL) {
168 /* remove module from tracking list */
169 if (module_list == module) {
170 module_list = module->next;
172 for (mod = module_list; mod; mod = mod->next) {
173 if (mod->next == module) {
174 mod->next = module->next;
180 /* call module's terminate routine, if present */
181 if (terminate = lt_dlsym(module->lib, "term_module")) {
185 /* close the library and free the memory */
186 lt_dlclose(module->lib);
192 int load_null_module (const void *module, const char *file_name)
197 #ifdef SLAPD_EXTERNAL_EXTENSIONS
201 const char *file_name
204 SLAP_EXTOP_MAIN_FN ext_main;
205 int (*ext_getoid)(int index, char *oid, int blen);
209 ext_main = (SLAP_EXTOP_MAIN_FN)module_resolve(module, "ext_main");
210 if (ext_main == NULL) {
214 ext_getoid = module_resolve(module, "ext_getoid");
215 if (ext_getoid == NULL) {
219 oid = ch_malloc(256);
220 rc = (ext_getoid)(0, oid, 256);
230 rc = load_extop( oid, ext_main );
234 #endif /* SLAPD_EXTERNAL_EXTENSIONS */
235 #endif /* SLAPD_MODULES */