/* Return the contents of the first item in the global loader list with a matching NAME after removing it from that list. If there was no match, return NULL; if there is an error, return NULL and set an error for lt_dlerror; do not set an error if only resident modules need this loader; in either case, the loader list is not changed if NULL is returned. */ lt_dlvtable * lt_dlloader_remove (const char *name) { const lt_dlvtable * vtable = lt_dlloader_find (name); static const char id_string[] = "lt_dlloader_remove"; lt_dlinterface_id iface; lt_dlhandle handle = 0; int in_use = 0; int in_use_by_resident = 0; if (!vtable) { LT__SETERROR (INVALID_LOADER); return 0; } /* Fail if there are any open modules which use this loader. */ iface = lt_dlinterface_register (id_string, NULL); while ((handle = lt_dlhandle_iterate (iface, handle))) { lt_dlhandle cur = handle; if (cur->vtable == vtable) { in_use = 1; if (lt_dlisresident (handle)) in_use_by_resident = 1; } } lt_dlinterface_free (iface); if (in_use) { if (!in_use_by_resident) LT__SETERROR (REMOVE_LOADER); return 0; } /* Call the loader finalisation function. */ if (vtable && vtable->dlloader_exit) { if ((*vtable->dlloader_exit) (vtable->dlloader_data) != 0) { /* If there is an exit function, and it returns non-zero then it must set an error, and we will not remove it from the list. */ return 0; } } /* If we got this far, remove the loader from our global list. */ return (lt_dlvtable *) slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) name)); }
void pa_ltdl_init(void) { #ifdef PA_BIND_NOW const lt_dlvtable *dlopen_loader; #endif pa_assert_se(lt_dlinit() == 0); #ifdef PA_BIND_NOW /* Already initialised */ if (bindnow_loader) return; if (!(dlopen_loader = lt_dlloader_find((char*) "lt_dlopen"))) { pa_log_warn(_("Failed to find original lt_dlopen loader.")); return; } if (!(bindnow_loader = malloc(sizeof(lt_dlvtable)))) { pa_log_error(_("Failed to allocate new dl loader.")); return; } memcpy(bindnow_loader, dlopen_loader, sizeof(*bindnow_loader)); bindnow_loader->name = "bind-now-loader"; bindnow_loader->module_open = bind_now_open; bindnow_loader->module_close = bind_now_close; bindnow_loader->find_sym = bind_now_find_sym; bindnow_loader->priority = LT_DLLOADER_PREPEND; /* Add our BIND_NOW loader as the default module loader. */ if (lt_dlloader_add(bindnow_loader) != 0) { pa_log_warn(_("Failed to add bind-now-loader.")); free(bindnow_loader); bindnow_loader = NULL; } #endif }