extern void* dllplug(const char* lib, const char* name, const char* ver, int flags, char* path, size_t size) { void* dll; int hit; Dllscan_t* dls; Dllent_t* dle; hit = 0; for (;;) { if (dls = dllsopen(lib, name, ver)) { while (dle = dllsread(dls)) { hit = 1; if (dll = dllopen(dle->path, flags|RTLD_GLOBAL|RTLD_PARENT)) { if (path && size) strncopy(path, dle->path, size); break; } else errorf("dll", NiL, 1, "%s: dlopen failed: %s", dle->path, dlerror()); } dllsclose(dls); } if (hit) return dll; if (!lib) break; lib = 0; } if ((dll = dllopen(name, flags)) && dll && path && size) strncopy(path, name, size); return dll; }
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; }
int b_dlls(int argc, char** argv, Shbltin_t* context) { int i; int r; int flags; int only; unsigned long ver; char** syms; char* arg[3]; void* dll; void* sym; Dllscan_t* dls; Dllent_t* dle; Dllinfo_t* dli; cmdinit(argc, argv, context, ERROR_CATALOG, 0); flags = 0; only = 0; for (;;) { switch (optget(argv, usage)) { case 0: break; case 'b': flags |= LIST_BASE; continue; case 'c': only = 1; continue; case 'i': flags |= LIST_INFO; continue; case 'l': flags |= LIST_LONG; continue; case 'p': flags |= LIST_PATH; continue; case ':': error(2, "%s", opt_info.arg); continue; case '?': error(ERROR_usage(2), "%s", opt_info.arg); continue; } break; } argv += opt_info.index; if (error_info.errors) error(ERROR_usage(2), "%s", optusage(NiL)); r = 0; if (flags & LIST_INFO) { if (!(dli = dllinfo())) error(2, "cannot determine native dll info"); sfprintf(sfstdout, "sibling=(%s", dli->sibling[0]); for (i = 1; dli->sibling[i]; i++) sfprintf(sfstdout, " %s", dli->sibling[i]); sfprintf(sfstdout, ") env=%s prefix=%s suffix=%s flags=", dli->env, dli->prefix, dli->suffix); i = 0; if (dli->flags & DLL_INFO_PREVER) { i = 1; sfprintf(sfstdout, "PREVER"); } if (dli->flags & DLL_INFO_DOTVER) { if (i) sfputc(sfstdout, '|'); sfprintf(sfstdout, "DOTVER"); } sfputc(sfstdout, '\n'); } else if (!(flags & (LIST_BASE|LIST_PATH))) flags |= LIST_BASE|LIST_PATH; if (flags &= (LIST_BASE|LIST_PATH|LIST_LONG)) { for (i = 0; i < elementsof(arg); i++) if (arg[i] = *argv) argv++; if (only && !*argv) error(ERROR_usage(2), "%s", optusage(NiL)); r = 1; for (;;) { if (dls = dllsopen(arg[0], arg[1], arg[2])) { while (dle = dllsread(dls)) { r = 0; if (!only) { if (!(flags & LIST_LONG)) dll = 0; else if (dll = dlopen(dle->path, RTLD_LAZY)) ver = dllversion(dll, NiL); else ver = 0; switch (flags) { case LIST_BASE: sfprintf(sfstdout, "%s\n", dle->name); break; case LIST_BASE|LIST_LONG: sfprintf(sfstdout, "%14s %08lu\n", dle->name, ver); break; case LIST_PATH|LIST_LONG: sfprintf(sfstdout, "%08lu %s\n", ver, dle->path); break; case LIST_PATH: sfprintf(sfstdout, "%s\n", dle->path); break; case LIST_BASE|LIST_PATH: sfprintf(sfstdout, "%14s %s\n", dle->name, dle->path); break; default: sfprintf(sfstdout, "%14s %08lu %s\n", dle->name, ver, dle->path); break; } if (*(syms = argv)) { if (dll || (dll = dlopen(dle->path, RTLD_LAZY))) { do { sfprintf(sfstdout, " %14s ", *syms); if (sym = dlllook(dll, *syms)) sfprintf(sfstdout, "%p\n", sym); else sfprintf(sfstdout, "%s\n", dlerror()); } while (*++syms); dlclose(dll); } else sfprintf(sfstdout, " %s\n", dlerror()); } } else if (dll = dlopen(dle->path, RTLD_LAZY)) { i = 1; for (syms = argv; *syms; syms++) if (sym = dlllook(dll, *syms)) { if (i) { i = 0; switch (flags) { case LIST_BASE: sfprintf(sfstdout, "%s\n", dle->name); break; case LIST_PATH: sfprintf(sfstdout, "%s\n", dle->path); break; default: sfprintf(sfstdout, "%14s %s\n", dle->name, dle->path); break; } } sfprintf(sfstdout, " %14s %p\n", *syms, sym); } dlclose(dll); } } dllsclose(dls); } if (!r || !arg[0] || streq(arg[0], "-") || !arg[1] || streq(arg[1], "-")) break; arg[0] = 0; } } return r || error_info.errors; }