3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
14 typedef int (*MODULE_INIT_FN)(
17 typedef int (*MODULE_LOAD_FN)(
19 const char *filename);
20 typedef int (*MODULE_TERM_FN)(void);
23 struct module_regtable_t {
26 } module_regtable[] = {
27 { "null", load_null_module },
28 #ifdef SLAPD_EXTERNAL_EXTENSIONS
29 { "extension", load_extop_module },
34 typedef struct module_loaded_t {
35 struct module_loaded_t *next;
39 module_loaded_t *module_list = NULL;
41 static int module_unload (module_loaded_t *module);
44 static char ebuf[BUFSIZ];
47 int module_init (void)
50 const char *error = lt_dlerror();
52 strcpy( ebuf, error );
57 LDAP_LOG( SLAPD, CRIT,
58 "module_init: lt_dlinit failed: %s\n", error, 0, 0 );
60 Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
68 int module_kill (void)
70 /* unload all modules before shutdown */
71 while (module_list != NULL) {
72 module_unload(module_list);
76 const char *error = lt_dlerror();
78 strcpy( ebuf, error );
83 LDAP_LOG( SLAPD, CRIT, "module_kill: lt_dlexit failed: %s\n",
86 Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
94 int module_load(const char* file_name, int argc, char *argv[])
96 module_loaded_t *module = NULL;
99 MODULE_INIT_FN initialize;
103 #define file file_name
106 module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t));
107 if (module == NULL) {
109 LDAP_LOG( SLAPD, CRIT,
110 "module_load: (%s) out of memory.\n", file_name, 0, 0 );
112 Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
120 strcpy( file, file_name );
124 * The result of lt_dlerror(), when called, must be cached prior
125 * to calling Debug. This is because Debug is a macro that expands
126 * into multiple function calls.
128 if ((module->lib = lt_dlopenext(file)) == NULL) {
129 error = lt_dlerror();
131 strcpy( ebuf, error );
136 LDAP_LOG( SLAPD, CRIT,
137 "module_load: lt_dlopenext failed: (%s) %s.\n",
138 file_name, error, 0 );
140 Debug(LDAP_DEBUG_ANY, "lt_dlopenext failed: (%s) %s\n", file_name,
149 LDAP_LOG( SLAPD, INFO, "module_load: loaded module %s\n", file_name, 0, 0 );
151 Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
156 #pragma convlit(suspend)
158 if ((initialize = lt_dlsym(module->lib, "init_module")) == NULL) {
160 #pragma convlit(resume)
163 LDAP_LOG( SLAPD, ERR,
164 "module_load: module %s : no init_module() function found\n",
167 Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
171 lt_dlclose(module->lib);
176 /* The imported init_module() routine passes back the type of
177 * module (i.e., which part of slapd it should be hooked into)
178 * or -1 for error. If it passes back 0, then you get the
179 * old behavior (i.e., the library is loaded and not hooked
182 * It might be better if the conf file could specify the type
183 * of module. That way, a single module could support multiple
184 * type of hooks. This could be done by using something like:
186 * moduleload extension /usr/local/openldap/whatever.so
188 * then we'd search through module_regtable for a matching
189 * module type, and hook in there.
191 rc = initialize(argc, argv);
194 LDAP_LOG( SLAPD, ERR,
195 "module_load: module %s init_module() failed\n", file_name, 0, 0);
197 Debug(LDAP_DEBUG_CONFIG, "module %s: init_module() failed\n",
201 lt_dlclose(module->lib);
206 if (rc >= (int)(sizeof(module_regtable) / sizeof(struct module_regtable_t))
207 || module_regtable[rc].proc == NULL)
210 LDAP_LOG( SLAPD, ERR,
211 "module_load: module %s: unknown registration type (%d).\n",
214 Debug(LDAP_DEBUG_CONFIG, "module %s: unknown registration type (%d)\n",
218 module_unload(module);
222 rc = (module_regtable[rc].proc)(module, file_name);
225 LDAP_LOG( SLAPD, ERR,
226 "module_load: module %s:%s could not be registered.\n",
227 file_name, module_regtable[rc].type, 0 );
229 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module could not be registered\n",
230 file_name, module_regtable[rc].type, 0);
233 module_unload(module);
237 module->next = module_list;
238 module_list = module;
241 LDAP_LOG( SLAPD, INFO,
242 "module_load: module %s:%s registered\n", file_name,
243 module_regtable[rc].type, 0 );
245 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module registered\n",
246 file_name, module_regtable[rc].type, 0);
252 int module_path(const char *path)
259 return lt_dlsetsearchpath( path );
262 void *module_resolve (const void *module, const char *name)
269 if (module == NULL || name == NULL)
271 return(lt_dlsym(((module_loaded_t *)module)->lib, name));
274 static int module_unload (module_loaded_t *module)
276 module_loaded_t *mod;
277 MODULE_TERM_FN terminate;
279 if (module != NULL) {
280 /* remove module from tracking list */
281 if (module_list == module) {
282 module_list = module->next;
284 for (mod = module_list; mod; mod = mod->next) {
285 if (mod->next == module) {
286 mod->next = module->next;
292 /* call module's terminate routine, if present */
294 #pragma convlit(suspend)
296 if ((terminate = lt_dlsym(module->lib, "term_module"))) {
298 #pragma convlit(resume)
303 /* close the library and free the memory */
304 lt_dlclose(module->lib);
310 int load_null_module (const void *module, const char *file_name)
315 #ifdef SLAPD_EXTERNAL_EXTENSIONS
319 const char *file_name
322 SLAP_EXTOP_MAIN_FN *ext_main;
323 SLAP_EXTOP_GETOID_FN *ext_getoid;
327 ext_main = (SLAP_EXTOP_MAIN_FN *)module_resolve(module, "ext_main");
328 if (ext_main == NULL) {
332 ext_getoid = module_resolve(module, "ext_getoid");
333 if (ext_getoid == NULL) {
337 rc = (ext_getoid)(0, &oid, 256);
341 if (oid.bv_val == NULL || oid.bv_len == 0) {
345 rc = load_extop( &oid, ext_main );
348 #endif /* SLAPD_EXTERNAL_EXTENSIONS */
349 #endif /* SLAPD_MODULES */