+typedef int (*MODULE_INIT_FN)(
+ int argc,
+ char *argv[]);
+typedef int (*MODULE_LOAD_FN)(
+ const void *module,
+ const char *filename);
+typedef int (*MODULE_TERM_FN)(void);
+
+
+struct module_regtable_t {
+ char *type;
+ MODULE_LOAD_FN proc;
+} module_regtable[] = {
+ { "null", load_null_module },
+#ifdef SLAPD_EXTERNAL_EXTENSIONS
+ { "extension", load_extop_module },
+#endif
+ { NULL, NULL }
+};
+
+typedef struct module_loaded_t {
+ struct module_loaded_t *next;
+ lt_dlhandle lib;
+ char name[1];
+} module_loaded_t;
+
+module_loaded_t *module_list = NULL;
+
+static int module_int_unload (module_loaded_t *module);
+
+#ifdef HAVE_EBCDIC
+static char ebuf[BUFSIZ];
+#endif
+
+int module_init (void)
+{
+ if (lt_dlinit()) {
+ const char *error = lt_dlerror();
+#ifdef HAVE_EBCDIC
+ strcpy( ebuf, error );
+ __etoa( ebuf );
+ error = ebuf;
+#endif
+ Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
+
+ return -1;
+ }
+
+ return module_path( LDAP_MODULEDIR );
+}
+
+int module_kill (void)
+{
+ /* unload all modules before shutdown */
+ while (module_list != NULL) {
+ module_int_unload(module_list);
+ }
+
+ if (lt_dlexit()) {
+ const char *error = lt_dlerror();
+#ifdef HAVE_EBCDIC
+ strcpy( ebuf, error );
+ __etoa( ebuf );
+ error = ebuf;
+#endif
+ Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
+
+ return -1;
+ }
+ return 0;
+}
+
+void * module_handle( const char *file_name )
+{
+ module_loaded_t *module;
+
+ for ( module = module_list; module; module= module->next ) {
+ if ( !strcmp( module->name, file_name )) {
+ return module;
+ }
+ }
+ return NULL;
+}
+
+int module_unload( const char *file_name )
+{
+ module_loaded_t *module;
+
+ module = module_handle( file_name );
+ if ( module ) {
+ module_int_unload( module );
+ return 0;
+ }
+ return -1; /* not found */
+}
+
+int module_load(const char* file_name, int argc, char *argv[])
+{
+ module_loaded_t *module = NULL;
+ const char *error;
+ int rc;
+ MODULE_INIT_FN initialize;
+#ifdef HAVE_EBCDIC
+#define file ebuf
+#else
+#define file file_name
+#endif
+
+ module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t) +
+ strlen(file_name));
+ if (module == NULL) {
+ Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
+ 0, 0);
+
+ return -1;
+ }
+ strcpy( module->name, file_name );
+
+#ifdef HAVE_EBCDIC
+ strcpy( file, file_name );
+ __atoe( file );
+#endif
+ /*
+ * The result of lt_dlerror(), when called, must be cached prior
+ * to calling Debug. This is because Debug is a macro that expands
+ * into multiple function calls.
+ */
+ if ((module->lib = lt_dlopenext(file)) == NULL) {
+ error = lt_dlerror();
+#ifdef HAVE_EBCDIC
+ strcpy( ebuf, error );
+ __etoa( ebuf );
+ error = ebuf;
+#endif
+ Debug(LDAP_DEBUG_ANY, "lt_dlopenext failed: (%s) %s\n", file_name,
+ error, 0);