extern void* dllplugin(const char* lib, const char* name, const char* ver, unsigned long rel, unsigned long* cur, int flags, char* path, size_t size) { void* dll; int err; int hit; Dllscan_t* dls; Dllent_t* dle; err = hit = 0; for (;;) { if (dls = dllsopen(lib, name, ver)) { while (dle = dllsread(dls)) { hit = 1; #if 0 again: #endif if (dll = dllopen(dle->path, flags|RTLD_GLOBAL|RTLD_PARENT)) { if (!dllcheck(dll, dle->path, rel, cur)) { err = state.error; dlclose(dll); dll = 0; continue; } if (path && size) strlcpy(path, dle->path, size); break; } else { #if 0 /* * dlopen() should load implicit libraries * this code does that * but it doesn't help on galadriel */ char* s; char* e; if ((s = dllerror(1)) && (e = strchr(s, ':'))) { *e = 0; error(1, "AHA %s implicit", s); dll = dllplugin(lib, s, 0, 0, 0, flags, path, size); *e = ':'; if (dll) { error(1, "AHA implicit %s => %s", s, path); goto again; } } #endif errorf("dll", NiL, 1, "dllplugin: %s dlopen failed: %s", dle->path, dllerror(1)); err = state.error; } } dllsclose(dls); } if (hit) { if (!dll) state.error = err; return dll; } if (!lib) break; lib = 0; } if (dll = dllopen(name, flags)) { if (!dllcheck(dll, name, rel, cur)) { dlclose(dll); dll = 0; } else if (path && size) strlcpy(path, name, size); } return dll; }
char * module_load(const char *filename, const char *symbname, int (*shouldload)(void *symb, void *misc, char **err), void *misc, void **dll, void **symb) { dlltype intdll = NULL; void * intsym = NULL; char * interr = NULL; if (dll) *dll = NULL; if (symb) *symb = NULL; /* Open the module library */ #ifdef WIN32 /* NOTE: DONT_RESOLVE_DLL_REFERENCES is evil. Don't use this in your own * code. However, our design pattern avoids all the issues surrounding a * more general use of this evil flag. */ intdll = LoadLibraryEx(filename, NULL, DONT_RESOLVE_DLL_REFERENCES); #else /* WIN32 */ intdll = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); #endif /* WIN32 */ if (!intdll) return dllerror(); /* Get the module symbol */ #ifdef WIN32 intsym = (void *) GetProcAddress(intdll, symbname); #else /* WIN32 */ intsym = dlsym(intdll, symbname); #endif /* WIN32 */ if (!intsym) { module_close(intdll); return dllerror(); } /* Figure out whether or not to load this module */ if (!shouldload(intsym, misc, &interr)) { module_close(intdll); return interr; } /* Re-open the module */ module_close(intdll); #ifdef WIN32 intdll = LoadLibrary(filename); #else /* WIN32 */ intdll = dlopen(filename, RTLD_NOW | RTLD_LOCAL); #endif /* WIN32 */ if (!intdll) { return dllerror(); } /* Get the symbol again */ #ifdef WIN32 intsym = (void *) GetProcAddress(intdll, symbname); #else /* WIN32 */ intsym = dlsym(intdll, symbname); #endif /* WIN32 */ if (!intsym) { module_close(intdll); return dllerror(); } if (dll) *dll = intdll; if (symb) *symb = intsym; return NULL; }