#include "xgl.h"
#include "xglmodule.h"
#ifdef XGL_MODULAR
#include <dlfcn.h>
#define SYM(ptr, name) { (void **) &(ptr), (name) }
void *
xglLoadModule (const char *name,
int flag)
{
ModuleVersionProcPtr moduleVersion;
ModuleInitProcPtr moduleInit;
void *handle = 0;
char *module;
xglSymbolRec mSym[] = {
SYM (moduleVersion, "moduleVersion"),
SYM (moduleInit, "moduleInit")
};
module = malloc (strlen (XGL_MODULE_PATH "/lib.so") + strlen (name) + 1);
if (!module)
return 0;
sprintf (module, XGL_MODULE_PATH "/lib%s.so", name);
handle = dlopen (module, flag);
if (handle)
{
if (xglLookupSymbols (handle, mSym, sizeof (mSym) / sizeof (mSym[0])))
{
const char *version;
version = (*moduleVersion) ();
if (strcmp (VERSION, version) == 0)
{
if (!(*moduleInit) (module))
{
dlclose (handle);
handle = 0;
}
}
else
{
ErrorF ("Module version mismatch. "
"%s is %s Xserver is" VERSION "\n",
module, version);
dlclose (handle);
handle = 0;
}
}
else
{
dlclose (handle);
handle = 0;
}
}
else
ErrorF ("dlopen: %s\n", dlerror ());
free (module);
return handle;
}
void
xglUnloadModule (void *handle)
{
dlclose (handle);
}
Bool
xglLookupSymbols (void *handle,
xglSymbolPtr sym,
int nSym)
{
void *symbol;
char *error;
int i;
dlerror ();
for (i = 0; i < nSym; i++)
{
symbol = dlsym (handle, sym[i].name);
if (!symbol)
{
error = dlerror ();
if (error != 0)
ErrorF ("dlsym: %s: %s\n", sym[i].name, error);
return FALSE;
}
*(sym[i].ptr) = symbol;
}
return TRUE;
}
#endif