2 * ion/ioncore/modules.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
15 #include <libextl/readconfig.h>
19 #include "../version.h"
22 #ifndef CF_PRELOAD_MODULES
28 typedef void *dlhandle;
31 static Rb_node modules=NULL;
34 static dlhandle get_handle(const char *name)
39 nd=rb_find_key_n(modules, name, &found);
46 static const char *get_name(dlhandle handle)
50 rb_traverse(nd, modules){
52 return (const char *)(nd->k.key);
58 static Rb_node add_module(char *name, dlhandle handle)
60 return rb_insert(modules, name, handle);
67 /*{{{ Module symbol access */
70 static void *get_module_symbol(dlhandle handle,
71 const char *modulename,
77 p=scat(modulename, name);
89 static bool check_version(dlhandle handle, const char *modulename)
91 char *versionstr=(char*)get_module_symbol(handle, modulename,
95 return (strcmp(versionstr, ION_API_VERSION)==0);
99 static bool call_init(dlhandle handle, const char *modulename)
101 bool (*initfn)(void);
103 initfn=(bool (*)())get_module_symbol(handle, modulename, "_init");
112 static void call_deinit(dlhandle handle, const char *modulename)
114 void (*deinitfn)(void);
116 deinitfn=(void (*)())get_module_symbol(handle, modulename, "_deinit");
129 bool ioncore_init_module_support()
132 return (modules!=NULL);
136 static int try_load(const char *file, void *param)
138 dlhandle handle=NULL;
139 const char *slash, *dot;
143 if(access(file, F_OK)!=0)
144 return EXTL_TRYCONFIG_NOTFOUND;
146 slash=strrchr(file, '/');
147 dot=strrchr(file, '.');
155 warn(TR("Invalid module name."));
159 name=ALLOC_N(char, dot-slash+1);
163 strncpy(name, slash, dot-slash);
164 name[dot-slash]='\0';
166 if(get_handle(name)){
167 warn_obj(file, TR("The module is already loaded."));
171 handle=dlopen(file, RTLD_NOW|RTLD_GLOBAL);
174 warn_obj(file, "%s", dlerror());
179 return EXTL_TRYCONFIG_OK;
181 if(!check_version(handle, name)){
182 warn_obj(file, TR("Module version information not found or "
183 "version mismatch. Refusing to use."));
187 mod=add_module(name, handle);
192 if(!call_init(handle, name)){
193 warn_obj(file, TR("Unable to initialise module %s."), name);
198 return EXTL_TRYCONFIG_OK;
205 return EXTL_TRYCONFIG_LOAD_FAILED;
209 static bool do_load_module(const char *modname)
213 retval=extl_try_config(modname, NULL, (ExtlTryConfigFn*)try_load,
216 if(retval==EXTL_TRYCONFIG_NOTFOUND)
217 warn(TR("Unable to find '%s' on search path."), modname);
219 return (retval==EXTL_TRYCONFIG_OK);
229 static void do_unload_module(Rb_node mod)
231 char *name=(char*)mod->k.key;
232 dlhandle handle=mod->v.val;
234 call_deinit(handle, name);
241 void ioncore_unload_modules()
245 rb_traverse(mod, modules){
246 do_unload_module(mod);
257 /*{{{ Static module support */
260 static bool call_init(WStaticModuleInfo *handle)
262 if(handle->init!=NULL)
263 return handle->init();
268 static void call_deinit(WStaticModuleInfo *handle)
270 if(handle->deinit!=NULL)
275 extern WStaticModuleInfo ioncore_static_modules[];
278 static bool do_load_module(const char *name)
280 WStaticModuleInfo *mod;
282 for(mod=ioncore_static_modules; mod->name!=NULL; mod++){
283 if(strcmp(mod->name, name)==0)
288 warn_obj(name, TR("Unknown module."));
296 warn_obj(name, TR("Unable to initialise module."));
306 void ioncore_unload_modules()
308 WStaticModuleInfo *mod;
310 for(mod=ioncore_static_modules; mod->name!=NULL; mod++){
319 bool ioncore_init_module_support()
335 * Attempt to load a C-side module.
338 bool ioncore_load_module(const char *modname)
341 warn(TR("No module to load given."));
344 return do_load_module(modname);