+ struct recTypeClass *rts = 0;
+ const char *module_path = res_get_def(res, "modulePath",
+ DEFAULT_MODULE_PATH);
+
+ extern RecType idzebra_filter_grs_sgml[];
+ recTypeClass_add (&rts, idzebra_filter_grs_sgml, nmem, 0);
+#ifdef IDZEBRA_STATIC_TEXT
+ extern RecType idzebra_filter_text[];
+ recTypeClass_add (&rts, idzebra_filter_text, nmem, 0);
+#endif
+#ifdef IDZEBRA_STATIC_GRS_XML
+#if HAVE_EXPAT_H
+ extern RecType idzebra_filter_grs_xml[];
+ recTypeClass_add (&rts, idzebra_filter_grs_xml, nmem, 0);
+#endif
+#endif
+#ifdef IDZEBRA_STATIC_GRS_REGX
+ extern RecType idzebra_filter_grs_regx[];
+ recTypeClass_add (&rts, idzebra_filter_grs_regx, nmem, 0);
+#endif
+#ifdef IDZEBRA_STATIC_GRS_MARC
+ extern RecType idzebra_filter_grs_marc[];
+ recTypeClass_add (&rts, idzebra_filter_grs_marc, nmem, 0);
+#endif
+#ifdef IDZEBRA_STATIC_GRS_DANBIB
+ extern RecType idzebra_filter_grs_danbib[];
+ recTypeClass_add (&rts, idzebra_filter_grs_danbib, nmem, 0);
+#endif
+
+ if (module_path)
+ {
+ DIR *dir = opendir(module_path);
+ yaz_log(LOG_LOG, "searching filters in %s", module_path);
+ if (dir)
+ {
+ struct dirent *de;
+
+ while ((de = readdir(dir)))
+ {
+ size_t dlen = strlen(de->d_name);
+ if ((de->d_type == DT_REG || de->d_type == DT_LNK)
+ && dlen >= 5 &&
+ !memcmp(de->d_name, "mod-", 4) &&
+ !strcmp(de->d_name + dlen - 3, ".so"))
+ {
+ void *mod_p, *fl;
+ char fname[FILENAME_MAX*2+1];
+ sprintf(fname, "%.*s/%.*s",
+ FILENAME_MAX, module_path,
+ FILENAME_MAX, de->d_name);
+ mod_p = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
+ if (mod_p && (fl = dlsym(mod_p, "idzebra_filter")))
+ {
+ yaz_log(LOG_LOG, "Loaded filter module %s", fname);
+ recTypeClass_add(&rts, fl, nmem, mod_p);
+ }
+ else if (mod_p)
+ {
+ const char *err = dlerror();
+ yaz_log(LOG_WARN, "dlsym failed %s %s",
+ fname, err ? err : "none");
+ dlclose(mod_p);
+ }
+ else
+ {
+ const char *err = dlerror();
+ yaz_log(LOG_WARN, "dlopen failed %s %s",
+ fname, err ? err : "none");
+
+ }
+ }
+ }
+ closedir(dir);
+ }
+ }
+ return rts;
+}