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();
44 LDAP_LOG(( "module", LDAP_LEVEL_CRIT,
45 "module_init: lt_ldinit failed: %s\n", error ));
47 Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
55 int module_kill (void)
57 /* unload all modules before shutdown */
58 while (module_list != NULL) {
59 module_unload(module_list);
63 const char *error = lt_dlerror();
65 LDAP_LOG(( "module", LDAP_LEVEL_CRIT,
66 "module_kill: lt_dlexit failed: %s\n", error ));
68 Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
76 int module_load(const char* file_name, int argc, char *argv[])
78 module_loaded_t *module = NULL;
81 MODULE_INIT_FN initialize;
83 module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t));
86 LDAP_LOG(( "module", LDAP_LEVEL_CRIT,
87 "module_load: (%s) out of memory.\n", file_name ));
89 Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
97 * The result of lt_dlerror(), when called, must be cached prior
98 * to calling Debug. This is because Debug is a macro that expands
99 * into multiple function calls.
101 if ((module->lib = lt_dlopen(file_name)) == NULL) {
102 error = lt_dlerror();
104 LDAP_LOG(( "module", LDAP_LEVEL_CRIT,
105 "module_load: lt_dlopen failed: (%s) %s.\n",
108 Debug(LDAP_DEBUG_ANY, "lt_dlopen failed: (%s) %s\n", file_name,
117 LDAP_LOG(( "module", LDAP_LEVEL_INFO,
118 "module_load: loaded module %s\n", file_name ));
120 Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
124 if ((initialize = lt_dlsym(module->lib, "init_module")) == NULL) {
126 LDAP_LOG(( "module", LDAP_LEVEL_ERR,
127 "module_load: module %s : no init_module() function found\n",
130 Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
134 lt_dlclose(module->lib);
139 /* The imported init_module() routine passes back the type of
140 * module (i.e., which part of slapd it should be hooked into)
141 * or -1 for error. If it passes back 0, then you get the
142 * old behavior (i.e., the library is loaded and not hooked
145 * It might be better if the conf file could specify the type
146 * of module. That way, a single module could support multiple
147 * type of hooks. This could be done by using something like:
149 * moduleload extension /usr/local/openldap/whatever.so
151 * then we'd search through module_regtable for a matching
152 * module type, and hook in there.
154 rc = initialize(argc, argv);
157 LDAP_LOG(( "module", LDAP_LEVEL_ERR,
158 "module_load: module %s init_module() failed\n", file_name));
160 Debug(LDAP_DEBUG_CONFIG, "module %s: init_module() failed\n",
164 lt_dlclose(module->lib);
169 if (rc >= (sizeof(module_regtable) / sizeof(struct module_regtable_t))
170 || module_regtable[rc].proc == NULL)
173 LDAP_LOG(( "module", LDAP_LEVEL_ERR,
174 "module_load: module %s: unknown registration type (%d).\n", file_name));
176 Debug(LDAP_DEBUG_CONFIG, "module %s: unknown registration type (%d)\n",
180 module_unload(module);
184 rc = (module_regtable[rc].proc)(module, file_name);
187 LDAP_LOG(( "module", LDAP_LEVEL_ERR,
188 "module_load: module %s:%s could not be registered.\n",
189 file_name, module_regtable[rc].type ));
191 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module could not be registered\n",
192 file_name, module_regtable[rc].type, 0);
195 module_unload(module);
199 module->next = module_list;
200 module_list = module;
203 LDAP_LOG(( "module", LDAP_LEVEL_INFO,
204 "module_load: module %s:%s registered\n", file_name,
205 module_regtable[rc].type ));
207 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module registered\n",
208 file_name, module_regtable[rc].type, 0);
214 int module_path(const char *path)
216 return lt_dlsetsearchpath( path );
219 void *module_resolve (const void *module, const char *name)
221 if (module == NULL || name == NULL)
223 return(lt_dlsym(((module_loaded_t *)module)->lib, name));
226 static int module_unload (module_loaded_t *module)
228 module_loaded_t *mod;
229 MODULE_TERM_FN terminate;
231 if (module != NULL) {
232 /* remove module from tracking list */
233 if (module_list == module) {
234 module_list = module->next;
236 for (mod = module_list; mod; mod = mod->next) {
237 if (mod->next == module) {
238 mod->next = module->next;
244 /* call module's terminate routine, if present */
245 if (terminate = lt_dlsym(module->lib, "term_module")) {
249 /* close the library and free the memory */
250 lt_dlclose(module->lib);
256 int load_null_module (const void *module, const char *file_name)
261 #ifdef SLAPD_EXTERNAL_EXTENSIONS
265 const char *file_name
268 SLAP_EXTOP_MAIN_FN *ext_main;
269 int (*ext_getoid)(int index, char *oid, int blen);
273 ext_main = (SLAP_EXTOP_MAIN_FN *)module_resolve(module, "ext_main");
274 if (ext_main == NULL) {
278 ext_getoid = module_resolve(module, "ext_getoid");
279 if (ext_getoid == NULL) {
283 oid = ch_malloc(256);
284 rc = (ext_getoid)(0, oid, 256);
294 rc = load_extop( oid, ext_main );
298 #endif /* SLAPD_EXTERNAL_EXTENSIONS */
299 #endif /* SLAPD_MODULES */