20#define _(String) gettext (String)
51static char * dlerrordup (
char *errormsg)
53 char *error = (
char *) lt_dlerror ();
54 if (error && !errormsg)
59static uint8_t modmgr_error(
const char* contextname)
63 errormsg = dlerrordup (errormsg);
64 if (
NULL != errormsg) {
65 fprintf(stderr,
"%s: %s\n",contextname,errormsg);
73static void modmgr_init_real();
75static void modmgr_init_noop()
77 DBG_MSG(
"modmgr already initialized.");
81static void (*modmgr_init_ptr)() = modmgr_init_real;
84static void modmgr_atexit()
86 DBG_MSG(
"Validate that module list is empty.");
91 if (0!=lt_dlexit ()) {
92 modmgr_error(
"lt_dlexit");
98static void modmgr_init_real()
103 DBG_MSG(
"LTDL initialization");
104 if (0 != lt_dlinit ())
105 modmgr_error(
"lt_dlinit");
108 DBG_MSG(
"Module list initialization");
110 if (
NULL == modules ) {
111 fprintf(stderr,
_(
"Critical: Module manager lacks RAM (OOM) to initialize.\n"));
117 DBG_MSG(
"Register an atexit healthcheck and cleanup fonction");
118 atexit(modmgr_atexit);
121 modmgr_init_ptr = modmgr_init_noop;
133 result = lt_dlsetsearchpath (path);
135 modmgr_error(
"lt_dlsetsearchpath");
136 DBG_PRINTF(
"search path = %s",lt_dlgetsearchpath());
149 if ((
NULL==path)||(0==path[0])) {
150 fprintf(stderr,
_(
"Module manager can not add a null or empty path.\n"));
152 result = lt_dladdsearchdir (path);
154 modmgr_error(
"lt_dladdsearchdir");
156 DBG_PRINTF(
"search path = %s",lt_dlgetsearchpath());
169 if ((
NULL==path)||(0==path[0])) {
170 fprintf(stderr,
_(
"Module manager can not insert a null or empty path.\n"));
172 result = lt_dlinsertsearchdir (before,path);
174 modmgr_error(
"lt_dlinsertsearchdir");
176 DBG_PRINTF(
"search path = %s",lt_dlgetsearchpath());
187 return lt_dlgetsearchpath();
201 if ((
NULL==modfile)||(0==modfile[0])) {
202 fprintf(stderr,
_(
"Module manager can not load a null or empty modfile.\n"));
207 if (
NULL == module ) {
209 fprintf(stderr,
_(
"Module manager lacks RAM (OOM) to create a module structure for %s.\n"),modfile);
214 module->
handle = lt_dlopenext (modfile);
216 modmgr_error(
"lt_dlopenext");
217 fprintf(stderr,
_(
"Module manager can not load %s.\n"),modfile);
224 const lt_dlinfo *li = lt_dlgetinfo(module->
handle);
225 if (0!=modmgr_error(
"lt_dlgetinfo")) {
226 DBG_MSG(
"lt_dlgetinfo failed");
229 DBG_PRINTF (
"ltinfo: filename = %s ", li->filename);
230 DBG_PRINTF (
"ltinfo: name(ref_count) = %s(%d)", li->name, li->ref_count);
236 while ((it)&&(it->handle!=module->
handle))
247 DBG_PRINTF(
"Module (%p) not yet loaded, keep and initialize",module->
handle);
251 *(
void**)(&l_onLoad) = lt_dlsym (module->
handle,
"onLoad");
254 if (0!=modmgr_error(
"lt_dlsym")) {
256 fprintf(stderr,
_(
"Module manager can not find the entry point (onLoad) not found (%s).\n"),modfile);
258 if (0!=lt_dlclose(module->
handle)) {
259 modmgr_error(
"lt_dlclose");
261 fprintf(stderr,
_(
"Critical: Module manager can not unload partially loaded invalid module (%s).\n"),modfile);
270 DBG_PRINTF(
"Module (%p) entry point found (%p), initializing",module->
handle, l_onLoad);
273 fprintf(stderr,
_(
"Invalid module(%s): entry point (onLoad) did not return module info.\n"),modfile);
279 DBG_PRINTF (
"modinfo: name (version) = %s (v%d.%d.%d)",
288 DBG_PRINTF (
"modinfo: author (email) = %s (%s)",
298 module->
next = modules;
310 uint8_t (*l_onUnload)();
317 fprintf(stderr,
_(
"Module manager can not unload a null module.\n"));
324 while ((it)&&(module!=it)) {
334 li = lt_dlgetinfo(module->
handle);
335 if (0!=modmgr_error(
"lt_dlgetinfo")) {
336 DBG_MSG(
"lt_dlgetinfo failed");
337 fprintf(stderr,
_(
"Critical: Module manager can not get module counter before unload.\n"));
341 li->filename, li->name,
344 if (1==li->ref_count) {
345 DBG_MSG(
"Last module usage : call onUnLoad");
346 *(
void**)(&l_onUnload) = lt_dlsym (it->
handle,
"onUnload");
347 if (0!=modmgr_error(
"lt_dlsym")) {
348 fprintf(stderr,
_(
"Module manager can not find the module exit point (onUnload).\n"));
353 result = l_onUnload();
356 fprintf(stderr,
_(
"Module manager received an error i(%d) from the module exit point (onUnload).\n"),result);
361 if (
NULL!=prevmodule)
366 if (0!=lt_dlclose(module->
handle))
367 modmgr_error(
"lt_dlclose");
370 DBG_MSG(
"Module still used, do not call onUnLoad");
372 if (0!=lt_dlclose(module->
handle))
373 modmgr_error(
"lt_dlclose");
388 fprintf(stderr,
_(
"--- Module list : BEGIN ------------------------------\n"));
393 "ltinfo = %s (%s:%d), "
394 "name (version) = %s (v%d.%d.%d), "
397 "author (email) = %s (%s), "
399 lt_dlgetinfo(it->
handle)->filename,
400 lt_dlgetinfo(it->
handle)->name,
401 lt_dlgetinfo(it->
handle)->ref_count,
415 fprintf(stderr,
_(
"--- Module list : END --------------------------------\n"));
425 DBG_PRINTF(
"module=%p, Symbol=%s",module,szSymbol);
428 fprintf(stderr,
_(
"Module manager can not resolve a symbol from a null module.\n"));
432 if ((
NULL==szSymbol)||(0==szSymbol[0])) {
433 fprintf(stderr,
_(
"Module manager can not resolve a null or empty symbol name.\n"));
439 while ((it)&&(it!=module))
444 pSymbol = lt_dlsym (it->
handle, szSymbol);
445 if (0!=modmgr_error(
"lt_dlsym")) {
#define DBG_TRACE
Checkpoint on stderr.
#define DBG_PRINTF(p_Format,...)
Log a timestamped debugging message on stderr.
#define ASSERT(condition)
Assertion check macro.
#define DBG_MSG(msg)
Checkpoint on stderr with a static message.
Tracks memory allocation and leaks when compiled without NDEBUG.
#define malloc(size)
Same syntaxt and same behavior than regular malloc function, with memory leaks tracking.
#define strdup(chaine)
Same syntaxt and same behavior than regular strdup function, with memory leaks tracking.
#define free(ptr)
Same syntaxt and same behavior than regular free function, with memory leaks tracking.
int modmgr_setpath(const char *path)
Reset and initialize the modules search path.
void * modmgr_getsymbol(const modmgr_module_t module, const char *szSymbol)
Resolve a module symbol pointer.
int modmgr_insertpath(const char *before, const char *path)
Insert (with higher prio) a path before the specified one (from the current search path)
void modmgr_list()
Output the list of modules.
modmgr_module_t modmgr_load(const char *modfile)
Load a module, initialize it, add it to the list and return an opaque handle.
int modmgr_addpath(const char *path)
Add a path at the end (lowest prio) of the search path.
void modmgr_unload(modmgr_module_t module)
Decrement the usage counter, if last usage, remove from the module list and call onUnload.
const char * modmgr_getpath()
Get a read-only pointer on the current search path.
struct modules_s modules_t
Module list item structure.
const char * moduleAuthor
const uint8_t modulePatch
const uint8_t moduleMinor
const uint8_t moduleMajor
const char * moduleLicense
Module list item structure.