]> git.sur5r.net Git - openldap/blob - servers/slapd/module.c
Fix C errors
[openldap] / servers / slapd / module.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17 #include <stdio.h>
18 #include "slap.h"
19
20 #ifdef SLAPD_MODULES
21
22 #include <ltdl.h>
23
24 typedef int (*MODULE_INIT_FN)(
25         int argc,
26         char *argv[]);
27 typedef int (*MODULE_LOAD_FN)(
28         const void *module,
29         const char *filename);
30 typedef int (*MODULE_TERM_FN)(void);
31
32
33 struct module_regtable_t {
34         char *type;
35         MODULE_LOAD_FN proc;
36 } module_regtable[] = {
37                 { "null", load_null_module },
38 #ifdef SLAPD_EXTERNAL_EXTENSIONS
39                 { "extension", load_extop_module },
40 #endif
41                 { NULL, NULL }
42 };
43
44 typedef struct module_loaded_t {
45         struct module_loaded_t *next;
46         lt_dlhandle lib;
47         char name[1];
48 } module_loaded_t;
49
50 module_loaded_t *module_list = NULL;
51
52 static int module_int_unload (module_loaded_t *module);
53
54 #ifdef HAVE_EBCDIC
55 static char ebuf[BUFSIZ];
56 #endif
57
58 int module_init (void)
59 {
60         if (lt_dlinit()) {
61                 const char *error = lt_dlerror();
62 #ifdef HAVE_EBCDIC
63                 strcpy( ebuf, error );
64                 __etoa( ebuf );
65                 error = ebuf;
66 #endif
67                 Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
68
69                 return -1;
70         }
71         return 0;
72 }
73
74 int module_kill (void)
75 {
76         /* unload all modules before shutdown */
77         while (module_list != NULL) {
78                 module_int_unload(module_list);
79         }
80
81         if (lt_dlexit()) {
82                 const char *error = lt_dlerror();
83 #ifdef HAVE_EBCDIC
84                 strcpy( ebuf, error );
85                 __etoa( ebuf );
86                 error = ebuf;
87 #endif
88                 Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
89
90                 return -1;
91         }
92         return 0;
93 }
94
95 void * module_handle( const char *file_name )
96 {
97         module_loaded_t *module;
98
99         for ( module = module_list; module; module= module->next ) {
100                 if ( !strcmp( module->name, file_name )) {
101                         return module;
102                 }
103         }
104         return NULL;
105 }
106
107 int module_unload( const char *file_name )
108 {
109         module_loaded_t *module;
110
111         module = module_handle( file_name );
112         if ( module ) {
113                 module_int_unload( module );
114                 return 0;
115         }
116         return -1;      /* not found */
117 }
118
119 int module_load(const char* file_name, int argc, char *argv[])
120 {
121         module_loaded_t *module = NULL;
122         const char *error;
123         int rc;
124         MODULE_INIT_FN initialize;
125 #ifdef HAVE_EBCDIC
126 #define file    ebuf
127 #else
128 #define file    file_name
129 #endif
130
131         module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t) +
132                 strlen(file_name));
133         if (module == NULL) {
134                 Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
135                         0, 0);
136
137                 return -1;
138         }
139         strcpy( module->name, file_name );
140
141 #ifdef HAVE_EBCDIC
142         strcpy( file, file_name );
143         __atoe( file );
144 #endif
145         /*
146          * The result of lt_dlerror(), when called, must be cached prior
147          * to calling Debug. This is because Debug is a macro that expands
148          * into multiple function calls.
149          */
150         if ((module->lib = lt_dlopenext(file)) == NULL) {
151                 error = lt_dlerror();
152 #ifdef HAVE_EBCDIC
153                 strcpy( ebuf, error );
154                 __etoa( ebuf );
155                 error = ebuf;
156 #endif
157                 Debug(LDAP_DEBUG_ANY, "lt_dlopenext failed: (%s) %s\n", file_name,
158                         error, 0);
159
160                 ch_free(module);
161                 return -1;
162         }
163
164         Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
165
166    
167 #ifdef HAVE_EBCDIC
168 #pragma convlit(suspend)
169 #endif
170         if ((initialize = lt_dlsym(module->lib, "init_module")) == NULL) {
171 #ifdef HAVE_EBCDIC
172 #pragma convlit(resume)
173 #endif
174                 Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
175                         file_name, 0, 0);
176
177                 lt_dlclose(module->lib);
178                 ch_free(module);
179                 return -1;
180         }
181
182         /* The imported init_module() routine passes back the type of
183          * module (i.e., which part of slapd it should be hooked into)
184          * or -1 for error.  If it passes back 0, then you get the 
185          * old behavior (i.e., the library is loaded and not hooked
186          * into anything).
187          *
188          * It might be better if the conf file could specify the type
189          * of module.  That way, a single module could support multiple
190          * type of hooks. This could be done by using something like:
191          *
192          *    moduleload extension /usr/local/openldap/whatever.so
193          *
194          * then we'd search through module_regtable for a matching
195          * module type, and hook in there.
196          */
197         rc = initialize(argc, argv);
198         if (rc == -1) {
199                 Debug(LDAP_DEBUG_CONFIG, "module %s: init_module() failed\n",
200                         file_name, 0, 0);
201
202                 lt_dlclose(module->lib);
203                 ch_free(module);
204                 return rc;
205         }
206
207         if (rc >= (int)(sizeof(module_regtable) / sizeof(struct module_regtable_t))
208                 || module_regtable[rc].proc == NULL)
209         {
210                 Debug(LDAP_DEBUG_CONFIG, "module %s: unknown registration type (%d)\n",
211                         file_name, rc, 0);
212
213                 module_int_unload(module);
214                 return -1;
215         }
216
217         rc = (module_regtable[rc].proc)(module, file_name);
218         if (rc != 0) {
219                 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module could not be registered\n",
220                         file_name, module_regtable[rc].type, 0);
221
222                 module_int_unload(module);
223                 return rc;
224         }
225
226         module->next = module_list;
227         module_list = module;
228
229         Debug(LDAP_DEBUG_CONFIG, "module %s: %s module registered\n",
230                 file_name, module_regtable[rc].type, 0);
231
232         return 0;
233 }
234
235 int module_path(const char *path)
236 {
237 #ifdef HAVE_EBCDIC
238         strcpy(ebuf, path);
239         __atoe(ebuf);
240         path = ebuf;
241 #endif
242         return lt_dlsetsearchpath( path );
243 }
244
245 void *module_resolve (const void *module, const char *name)
246 {
247 #ifdef HAVE_EBCDIC
248         strcpy(ebuf, name);
249         __atoe(ebuf);
250         name = ebuf;
251 #endif
252         if (module == NULL || name == NULL)
253                 return(NULL);
254         return(lt_dlsym(((module_loaded_t *)module)->lib, name));
255 }
256
257 static int module_int_unload (module_loaded_t *module)
258 {
259         module_loaded_t *mod;
260         MODULE_TERM_FN terminate;
261
262         if (module != NULL) {
263                 /* remove module from tracking list */
264                 if (module_list == module) {
265                         module_list = module->next;
266                 } else {
267                         for (mod = module_list; mod; mod = mod->next) {
268                                 if (mod->next == module) {
269                                         mod->next = module->next;
270                                         break;
271                                 }
272                         }
273                 }
274
275                 /* call module's terminate routine, if present */
276 #ifdef HAVE_EBCDIC
277 #pragma convlit(suspend)
278 #endif
279                 if ((terminate = lt_dlsym(module->lib, "term_module"))) {
280 #ifdef HAVE_EBCDIC
281 #pragma convlit(resume)
282 #endif
283                         terminate();
284                 }
285
286                 /* close the library and free the memory */
287                 lt_dlclose(module->lib);
288                 ch_free(module);
289         }
290         return 0;
291 }
292
293 int load_null_module (const void *module, const char *file_name)
294 {
295         return 0;
296 }
297
298 #ifdef SLAPD_EXTERNAL_EXTENSIONS
299 int
300 load_extop_module (
301         const void *module,
302         const char *file_name
303 )
304 {
305         SLAP_EXTOP_MAIN_FN *ext_main;
306         SLAP_EXTOP_GETOID_FN *ext_getoid;
307         struct berval oid;
308         int rc;
309
310         ext_main = (SLAP_EXTOP_MAIN_FN *)module_resolve(module, "ext_main");
311         if (ext_main == NULL) {
312                 return(-1);
313         }
314
315         ext_getoid = module_resolve(module, "ext_getoid");
316         if (ext_getoid == NULL) {
317                 return(-1);
318         }
319
320         rc = (ext_getoid)(0, &oid, 256);
321         if (rc != 0) {
322                 return(rc);
323         }
324         if (oid.bv_val == NULL || oid.bv_len == 0) {
325                 return(-1);
326         }
327
328         /* FIXME: this is broken, and no longer needed, 
329          * as a module can call load_extop() itself... */
330         rc = load_extop( &oid, ext_main );
331         return rc;
332 }
333 #endif /* SLAPD_EXTERNAL_EXTENSIONS */
334 #endif /* SLAPD_MODULES */
335