- int len = dd->options_len;
- d->info = dd;
- d->options_block = store_get_perm(len, GET_UNTAINTED);
- memcpy(d->options_block, dd->options_block, len);
- for (int i = 0; i < *dd->options_count; i++)
- dd->options[i].type &= ~opt_set;
- return dd;
+ void * dl = dlopen(CS string_sprintf(LOOKUP_MODULE_DIR "/%s", fname), RTLD_NOW);
+ static driver_magics dm[] = {
+ { ROUTER_MAGIC, US"router" },
+ { TRANSPORT_MAGIC, US"transport" },
+ { AUTH_MAGIC, US"auth" },
+ };
+
+ if (!dl)
+ {
+ errormsg = dlerror();
+ log_write(0, LOG_MAIN|LOG_PANIC, "Error loading %s %s driver: %s\n",
+ d->driver_name, class, errormsg);
+ break;
+ }
+ (void) dlerror(); /* cf. comment in init_lookup_list() */
+
+ di = (driver_info *) dlsym(dl, CS string_sprintf("_%s_info", class));
+ if ((errormsg = dlerror()))
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s does not appear to be a %s module (%s)\n", fname, class, errormsg);
+ dlclose(dl);
+ break;
+ }
+ for(driver_magics * dmp = dm; dmp < dm + nelem(dm); dmp++)
+ if(Ustrcmp(dmp->class, class) == 0 && dmp->magic == di->dyn_magic)
+ {
+ add_driver_info(info_anchor, di, size_of_info);
+ DEBUG(D_any) debug_printf("Loaded %s %s\n", d->driver_name, class);
+ closedir(dd);
+ goto found;
+ }
+
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s module %s is not compatible with this version of Exim\n",
+ class, d->driver_name);
+ dlclose(dl);
+ break;