Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / modules.c
blob63595ad8ed2f594b8012f35fe6a614cac377ecc8
1 /*
2 * ion/modules.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #ifndef CF_NO_MODULE_SUPPORT
10 #include <dlfcn.h>
11 #include <string.h>
12 #include <ctype.h>
14 #include "common.h"
15 #include "modules.h"
18 INTRSTRUCT(Module)
20 DECLSTRUCT(Module){
21 void *handle;
22 char *name;
23 Module *next;
26 static Module *modules=NULL, *last_module=NULL;
27 static size_t longest_name=0;
30 /*{{{ Loading and initialization code */
33 static bool call_init(void *handle, char *name)
35 char *p=scat(name, "_init");
36 bool (*initfn)(void);
38 if(p==NULL){
39 warn_err();
40 return FALSE;
43 initfn=(bool (*)())dlsym(handle, p);
45 free(p);
47 if(initfn==NULL)
48 return TRUE;
50 return initfn();
54 bool load_module(const char *fname)
56 void *handle;
57 Module *m;
58 const char *p;
59 char *n;
60 size_t l;
62 handle=dlopen(fname, RTLD_LAZY);
64 if(handle==NULL){
65 warn_obj(fname, "%s", dlerror());
66 return FALSE;
69 /* Get the module name without directory or extension */
71 p=strrchr(fname, '/');
73 if(p!=NULL)
74 fname=p+1;
76 for(p=fname; *p!='\0'; p++){
77 if(!isalnum(*p) && *p!='_')
78 break;
81 n=ALLOC_N(char, p-fname);
83 if(n==NULL){
84 warn_err();
85 goto err1;
88 memcpy(n, fname, p-fname);
89 n[p-fname]='\0';
91 if(!call_init(handle, n))
92 goto err2;
94 /* Allocate space for module info */
96 m=ALLOC(Module);
98 if(m==NULL){
99 warn_err();
100 goto err2;
103 m->name=n;
104 m->handle=handle;
105 m->next=NULL;
107 if(last_module==NULL){
108 modules=last_module=m;
109 }else{
110 last_module->next=m;
111 last_module=m;
114 l=strlen(n);
116 if(l>longest_name)
117 longest_name=l;
119 return TRUE;
121 err2:
122 free(n);
123 err1:
124 dlclose(handle);
125 return FALSE;
129 /*}}}*/
132 /*{{{ Deinit */
135 static void call_deinit(void *handle, char *name)
137 char *p=scat(name, "_deinit");
138 void (*deinitfn)(void);
140 if(p==NULL){
141 warn_err();
142 return;
145 deinitfn=(void (*)())dlsym(handle, p);
147 free(p);
149 if(deinitfn!=NULL)
150 deinitfn();
154 static void do_unload_module(Module *m)
156 call_deinit(m->handle, m->name);
158 dlclose(m->handle);
159 if(m->name!=NULL)
160 free(m->name);
161 free(m);
165 void unload_modules()
167 Module *m, *next;
169 for(m=modules; m!=NULL; m=next){
170 next=m->next;
171 do_unload_module(m);
173 modules=NULL;
174 last_module=NULL;
175 longest_name=0;
179 /*}}}*/
182 /*{{{ Hooks and iterative symbol lookup */
185 static char *symtmp=NULL;
186 static Module *cmod=NULL;
189 static void *get_sym(const Module *m, const char *sym)
191 sprintf(symtmp, "%s_%s", m->name, sym);
192 return dlsym(m->handle, symtmp);
196 void *miter_begin(const char *sym)
198 cmod=NULL;
200 if(modules==NULL)
201 return NULL;
203 symtmp=ALLOC_N(char, strlen(sym)+longest_name+1+1);
205 if(symtmp==NULL){
206 warn_err();
207 return NULL;
210 cmod=modules;
212 return miter_next(sym);
216 void *miter_next(const char *sym)
218 void *r;
221 if(cmod==NULL)
222 return NULL;
224 r=get_sym(cmod, sym);
225 cmod=cmod->next;
226 }while(r==NULL);
228 return r;
232 void miter_end()
234 if(symtmp!=NULL){
235 free(symtmp);
236 symtmp=NULL;
241 void call_hooks(const char *hook)
243 void (*fn)();
245 for(fn=(void (*)())miter_begin(hook);
246 fn!=NULL;
247 fn=(void (*)())miter_next(hook)){
249 fn();
252 miter_end();
256 void call_hooks_p(const char *hook, void *p)
258 void (*fn)(void *);
260 for(fn=(void (*)(void *))miter_begin(hook);
261 fn!=NULL;
262 fn=(void (*)(void *))miter_next(hook)){
264 fn(p);
267 miter_end();
271 /*}}}*/
274 #else /* CF_MODULE_SUPPORT */
277 #include "common.h"
280 /*{{{ Dummy functions for systems without sufficient dynamic
281 * linking support
284 bool load_module(const char *name)
286 warn_obj(name, "Unabled to load: module support not enabled.");
287 return FALSE;
291 void unload_modules()
297 void call_hooks(const char *hook)
303 void call_hooks_p(const char *hook, void *p)
309 void *miter_begin(const char *sym)
311 return NULL;
315 void *miter_next(const char *sym)
317 return NULL;
321 void miter_end()
327 /*}}}*/
330 #endif