2 * ion/ioncore/modules.c
4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
18 #include <libextl/readconfig.h>
22 #include "../version.h"
25 #ifndef CF_PRELOAD_MODULES
31 typedef void *dlhandle;
34 static Rb_node modules=NULL;
37 static dlhandle get_handle(const char *name)
42 nd=rb_find_key_n(modules, name, &found);
49 static const char *get_name(dlhandle handle)
53 rb_traverse(nd, modules){
55 return (const char *)(nd->k.key);
61 static Rb_node add_module(char *name, dlhandle handle)
63 return rb_insert(modules, name, handle);
70 /*{{{ Module symbol access */
73 static void *get_module_symbol(dlhandle handle,
74 const char *modulename,
80 p=scat(modulename, name);
92 static bool check_version(dlhandle handle, const char *modulename)
94 char *versionstr=(char*)get_module_symbol(handle, modulename,
98 return (strcmp(versionstr, ION_API_VERSION)==0);
102 static bool call_init(dlhandle handle, const char *modulename)
104 bool (*initfn)(void);
106 initfn=(bool (*)())get_module_symbol(handle, modulename, "_init");
115 static void call_deinit(dlhandle handle, const char *modulename)
117 void (*deinitfn)(void);
119 deinitfn=(void (*)())get_module_symbol(handle, modulename, "_deinit");
132 bool ioncore_init_module_support()
135 return (modules!=NULL);
139 static int try_load(const char *file, void *param)
141 dlhandle handle=NULL;
142 const char *slash, *dot;
146 if(access(file, F_OK)!=0)
147 return EXTL_TRYCONFIG_NOTFOUND;
149 slash=strrchr(file, '/');
150 dot=strrchr(file, '.');
158 warn(TR("Invalid module name."));
162 name=ALLOC_N(char, dot-slash+1);
166 strncpy(name, slash, dot-slash);
167 name[dot-slash]='\0';
169 if(get_handle(name)){
170 warn_obj(file, TR("The module is already loaded."));
174 handle=dlopen(file, RTLD_NOW|RTLD_GLOBAL);
177 warn_obj(file, "%s", dlerror());
182 return EXTL_TRYCONFIG_OK;
184 if(!check_version(handle, name)){
185 warn_obj(file, TR("Module version information not found or "
186 "version mismatch. Refusing to use."));
190 mod=add_module(name, handle);
195 if(!call_init(handle, name)){
196 warn_obj(file, TR("Unable to initialise module %s."), name);
201 return EXTL_TRYCONFIG_OK;
208 return EXTL_TRYCONFIG_LOAD_FAILED;
212 static bool do_load_module(const char *modname)
216 retval=extl_try_config(modname, NULL, (ExtlTryConfigFn*)try_load,
219 if(retval==EXTL_TRYCONFIG_NOTFOUND)
220 warn(TR("Unable to find '%s' on search path."), modname);
222 return (retval==EXTL_TRYCONFIG_OK);
232 static void do_unload_module(Rb_node mod)
234 char *name=(char*)mod->k.key;
235 dlhandle handle=mod->v.val;
237 call_deinit(handle, name);
244 void ioncore_unload_modules()
248 rb_traverse(mod, modules){
249 do_unload_module(mod);
260 /*{{{ Static module support */
263 static bool call_init(WStaticModuleInfo *handle)
265 if(handle->init!=NULL)
266 return handle->init();
271 static void call_deinit(WStaticModuleInfo *handle)
273 if(handle->deinit!=NULL)
278 extern WStaticModuleInfo ioncore_static_modules[];
281 static bool do_load_module(const char *name)
283 WStaticModuleInfo *mod;
285 for(mod=ioncore_static_modules; mod->name!=NULL; mod++){
286 if(strcmp(mod->name, name)==0)
291 warn_obj(name, TR("Unknown module."));
299 warn_obj(name, TR("Unable to initialise module."));
309 void ioncore_unload_modules()
311 WStaticModuleInfo *mod;
313 for(mod=ioncore_static_modules; mod->name!=NULL; mod++){
322 bool ioncore_init_module_support()
338 * Attempt to load a C-side module.
341 bool ioncore_load_module(const char *modname)
344 warn(TR("No module to load given."));
347 return do_load_module(modname);