27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
29 #include <libxml/xinclude.h>
31 #include <yaz/yaz-util.h>
33 #include <yaz/snprintf.h>
34 #include <yaz/tpath.h>
35 #include <yaz/xml_include.h>
37 #include <sys/types.h>
65 xsltStylesheetPtr
xsp;
69 static char *
xml_context(
const xmlNode *ptr,
char *res,
size_t len)
71 xmlAttr *attr = ptr->properties;
75 for (; attr; attr = attr->next)
77 size_t l = strlen((
const char *) attr->name);
81 memcpy(res + off, attr->name, l);
84 while (ptr && ptr->type == XML_ELEMENT_NODE)
86 size_t l = strlen((
const char *) ptr->name);
91 memcpy(res + off, ptr->name, l);
101 const char *service_id)
104 NMEM
nmem = nmem_create();
127 service->
id = service_id ? nmem_strdup(
nmem, service_id) : 0;
178 NMEM nmem = service->
nmem;
181 || field_id < 0 || !(field_id < service->num_metadata))
185 assert(nmem && md &&
name);
200 md->
rank = nmem_strdup_null(nmem,
rank);
217 NMEM nmem = service->
nmem;
220 || field_id < 0 || !(field_id < service->num_sortkeys))
225 assert(nmem && sk &&
name);
262 char full_path[1024];
263 if (yaz_filepath_resolve(src, config->
path,
264 wrbuf_len(config->
confdir) > 0 ?
265 wrbuf_cstr(config->
confdir) :
".",
268 wrbuf_puts(w, full_path);
272 yaz_log(YLOG_WARN,
"File not found: fname=%s path=%s base=%s", src,
287 yaz_mutex_destroy(&service->
mutex);
288 nmem_destroy(service->
nmem);
299 int *md_node,
int *sk_node)
307 int sortkey_offset = 0;
308 xmlChar *xml_name = 0;
309 xmlChar *xml_brief = 0;
310 xmlChar *xml_sortkey = 0;
311 xmlChar *xml_merge = 0;
312 xmlChar *xml_type = 0;
313 xmlChar *xml_termlist = 0;
314 xmlChar *xml_rank = 0;
315 xmlChar *xml_setting = 0;
316 xmlChar *xml_mergekey = 0;
317 xmlChar *xml_limitmap = 0;
318 xmlChar *xml_limitcluster = 0;
319 xmlChar *xml_icu_chain = 0;
320 xmlChar *xml_icurule = 0;
322 struct _xmlAttr *attr;
326 for (attr = n->properties; attr; attr = attr->next)
328 if (!xmlStrcmp(attr->name, BAD_CAST
"name") &&
329 attr->children && attr->children->type == XML_TEXT_NODE)
330 xml_name = attr->children->content;
331 else if (!xmlStrcmp(attr->name, BAD_CAST
"brief") &&
332 attr->children && attr->children->type == XML_TEXT_NODE)
333 xml_brief = attr->children->content;
334 else if (!xmlStrcmp(attr->name, BAD_CAST
"sortkey") &&
335 attr->children && attr->children->type == XML_TEXT_NODE)
336 xml_sortkey = attr->children->content;
337 else if (!xmlStrcmp(attr->name, BAD_CAST
"merge") &&
338 attr->children && attr->children->type == XML_TEXT_NODE)
339 xml_merge = attr->children->content;
340 else if (!xmlStrcmp(attr->name, BAD_CAST
"type") &&
341 attr->children && attr->children->type == XML_TEXT_NODE)
342 xml_type = attr->children->content;
343 else if (!xmlStrcmp(attr->name, BAD_CAST
"termlist") &&
344 attr->children && attr->children->type == XML_TEXT_NODE)
345 xml_termlist = attr->children->content;
346 else if (!xmlStrcmp(attr->name, BAD_CAST
"rank") &&
347 attr->children && attr->children->type == XML_TEXT_NODE)
348 xml_rank = attr->children->content;
349 else if (!xmlStrcmp(attr->name, BAD_CAST
"setting") &&
350 attr->children && attr->children->type == XML_TEXT_NODE)
351 xml_setting = attr->children->content;
352 else if (!xmlStrcmp(attr->name, BAD_CAST
"mergekey") &&
353 attr->children && attr->children->type == XML_TEXT_NODE)
354 xml_mergekey = attr->children->content;
355 else if (!xmlStrcmp(attr->name, BAD_CAST
"facetrule") &&
356 attr->children && attr->children->type == XML_TEXT_NODE)
357 xml_icu_chain = attr->children->content;
358 else if (!xmlStrcmp(attr->name, BAD_CAST
"limitmap") &&
359 attr->children && attr->children->type == XML_TEXT_NODE)
360 xml_limitmap = attr->children->content;
361 else if (!xmlStrcmp(attr->name, BAD_CAST
"limitcluster") &&
362 attr->children && attr->children->type == XML_TEXT_NODE)
363 xml_limitcluster = attr->children->content;
364 else if (!xmlStrcmp(attr->name, BAD_CAST
"icurule") &&
365 attr->children && attr->children->type == XML_TEXT_NODE)
366 xml_icurule = attr->children->content;
369 yaz_log(YLOG_FATAL,
"Unknown metadata attribute '%s'", attr->name);
377 yaz_log(YLOG_FATAL,
"Must specify name in metadata element");
382 if (!strcmp((
const char *) xml_brief,
"yes"))
384 else if (strcmp((
const char *) xml_brief,
"no"))
386 yaz_log(YLOG_FATAL,
"metadata/brief must be yes or no");
393 if (!strcmp((
const char *) xml_termlist,
"yes"))
395 else if (strcmp((
const char *) xml_termlist,
"no"))
397 yaz_log(YLOG_FATAL,
"metadata/termlist must be yes or no");
404 if (!strcmp((
const char *) xml_type,
"generic"))
406 else if (!strcmp((
const char *) xml_type,
"year"))
408 else if (!strcmp((
const char *) xml_type,
"date"))
410 else if (!strcmp((
const char *) xml_type,
"float"))
415 "Unknown value for metadata/type: %s", xml_type);
422 if (!strcmp((
const char *) xml_merge,
"no"))
424 else if (!strcmp((
const char *) xml_merge,
"unique"))
426 else if (!strcmp((
const char *) xml_merge,
"longest"))
428 else if (!strcmp((
const char *) xml_merge,
"range"))
430 else if (!strcmp((
const char *) xml_merge,
"all"))
432 else if (!strcmp((
const char *) xml_merge,
"first"))
437 "Unknown value for metadata/merge: %s", xml_merge);
444 if (!strcmp((
const char *) xml_setting,
"no"))
446 else if (!strcmp((
const char *) xml_setting,
"postproc"))
448 else if (!strcmp((
const char *) xml_setting,
"parameter"))
453 "Unknown value for metadata/setting: %s", xml_setting);
459 if (xml_sortkey && strcmp((
const char *) xml_sortkey,
"no"))
465 "Can't specify sortkey on a non-merged field");
468 if (!strcmp((
const char *) xml_sortkey,
"yes"))
470 if (!strcmp((
const char *) xml_sortkey,
"numeric"))
472 else if (!strcmp((
const char *) xml_sortkey,
"skiparticle"))
479 "skiparticle only supported for type=generic: %s",
487 "Unknown sortkey in metadata element: %s",
491 sortkey_offset = *sk_node;
494 (
const char *) xml_name, sk_type);
502 if (!strcmp((
const char *) xml_mergekey,
"required"))
504 else if (!strcmp((
const char *) xml_mergekey,
"optional"))
506 else if (!strcmp((
const char *) xml_mergekey,
"no"))
510 yaz_log(YLOG_FATAL,
"Unknown value for mergekey: %s", xml_mergekey);
517 (
const char *) xml_name,
520 (
const char *) xml_rank, sortkey_offset,
522 (
const char *) xml_icu_chain,
523 (
const char *) xml_limitmap,
524 (
const char *) xml_limitcluster,
525 (
const char *) xml_icurule
534 xmlChar *sortkey = xmlGetProp(n, (xmlChar *)
"sortkey");
537 if (sortkey && strcmp((
const char *) sortkey,
"no"))
545 const char *service_id)
554 int got_settings = 0;
557 for (n = node->children; n; n = n->next)
558 if (n->type == XML_ELEMENT_NODE && !strcmp((
const char *)
559 n->name,
"metadata"))
564 for (m = n->children; m; m = m->next)
566 if (m->type == XML_ELEMENT_NODE &&
567 !strcmp((
const char *) m->name,
"metadata"))
577 for (n = node->children; n; n = n->next)
579 if (n->type != XML_ELEMENT_NODE)
581 if (!strcmp((
const char *) n->name,
"timeout"))
583 xmlChar *src = xmlGetProp(n, (xmlChar *)
"session");
590 yaz_log(YLOG_FATAL,
"session timeout out of range");
594 src = xmlGetProp(n, (xmlChar *)
"z3950_operation");
601 yaz_log(YLOG_FATAL,
"Z39.50 operation timeout out of range");
605 src = xmlGetProp(n, (xmlChar *)
"z3950_session");
612 yaz_log(YLOG_FATAL,
"Z39.50 session timeout out of range");
617 else if (!strcmp((
const char *) n->name,
"ccldirective"))
623 name = (
char *) xmlGetProp(n, (xmlChar *)
"name");
626 yaz_log(YLOG_FATAL,
"ccldirective: missing @name");
629 value = (
char *) xmlGetProp(n, (xmlChar *)
"value");
633 yaz_log(YLOG_FATAL,
"ccldirective: missing @value");
640 else if (!strcmp((
const char *) n->name,
"settings"))
642 else if (!strcmp((
const char *) n->name,
"icu_chain"))
648 yaz_log(YLOG_FATAL,
"ICU chain definition error");
652 else if (!strcmp((
const char *) n->name,
"relevance")
653 || !strcmp((
const char *) n->name,
"sort")
654 || !strcmp((
const char *) n->name,
"mergekey")
655 || !strcmp((
const char *) n->name,
"facet"))
661 (
const char *) n->name))
663 yaz_log(YLOG_FATAL,
"ICU chain definition error");
667 else if (!strcmp((
const char *) n->name, (
const char *)
"metadata"))
672 for (m = n->children; m; m = m->next)
673 if ((!strcmp((
const char *) m->name, (
const char *)
"metadata")))
681 else if (!strcmp((
const char *) n->name, (
const char *)
"xslt"))
686 else if (!strcmp((
const char *) n->name,
"rank"))
688 char *
rank_cluster = (
char *) xmlGetProp(n, (xmlChar *)
"cluster");
689 char *
rank_debug = (
char *) xmlGetProp(n, (xmlChar *)
"debug");
690 char *
rank_follow = (
char *) xmlGetProp(n, (xmlChar *)
"follow");
691 char *
rank_lead = (
char *) xmlGetProp(n, (xmlChar *)
"lead");
692 char *
rank_length= (
char *) xmlGetProp(n, (xmlChar *)
"length");
701 yaz_log(YLOG_FATAL,
"service: rank@cluster boolean");
713 yaz_log(YLOG_FATAL,
"service: rank@debug boolean");
735 yaz_log(YLOG_FATAL,
"service: rank@length linear|log|none");
745 else if (!strcmp((
const char *) n->name,
"sort-default"))
747 char *
default_sort = (
char *) xmlGetProp(n, (xmlChar *)
"field");
750 service->default_sort = nmem_strdup(service->nmem,
default_sort);
751 yaz_log(YLOG_LOG,
"service %s: default sort order configured to: %s",
756 yaz_log(YLOG_FATAL,
"default sort order is invalid: %s",
default_sort);
764 yaz_log(YLOG_FATAL,
"Bad element: %s . Context: %s", n->name,
774 for (pass = 1; pass <= 2; pass++)
776 for (n = node->children; n; n = n->next)
778 if (n->type != XML_ELEMENT_NODE)
780 if (!strcmp((
const char *) n->name,
"settings"))
783 xmlChar *src = xmlGetProp(n, (xmlChar *)
"src");
786 WRBUF w = wrbuf_alloc();
804 xmlBufferPtr buf = xmlBufferCreate();
805 xmlNodeDump(buf, node->doc, node, 0, 0);
807 nmem_strdupn(service->nmem, (
const char *) buf->content, buf->use);
830 yaz_log(YLOG_WARN,
"server '%s' has no settings", s->
id ? s->
id :
"unnamed");
859 assert(service->
mutex == 0);
866 NMEM nmem, xmlNode *node)
870 xmlChar *
server_id = xmlGetProp(node, (xmlChar *)
"id");
892 for (n = node->children; n; n = n->next)
894 if (n->type != XML_ELEMENT_NODE)
896 if (!strcmp((
const char *) n->name,
"listen"))
898 xmlChar *
port = xmlGetProp(n, (xmlChar *)
"port");
899 xmlChar *
host = xmlGetProp(n, (xmlChar *)
"host");
902 server->
port = nmem_strdup(nmem, (
const char *)
port);
904 server->
host = nmem_strdup(nmem, (
const char *)
host);
909 else if (!strcmp((
const char *) n->name,
"proxy"))
911 xmlChar *
port = xmlGetProp(n, (xmlChar *)
"port");
912 xmlChar *
host = xmlGetProp(n, (xmlChar *)
"host");
913 xmlChar *
myurl = xmlGetProp(n, (xmlChar *)
"myurl");
919 server->
myurl = nmem_strdup(nmem, (
const char *)
myurl);
924 else if (!strcmp((
const char *) n->name,
"settings"))
926 xmlChar *src = xmlGetProp(n, (xmlChar *)
"src");
930 yaz_log(YLOG_FATAL,
"Missing src attribute for settings");
936 yaz_log(YLOG_FATAL,
"Can't repeat 'settings'");
945 else if (!strcmp((
const char *) n->name,
"icu_chain"))
951 yaz_log(YLOG_FATAL,
"ICU chain definition error");
955 else if (!strcmp((
const char *) n->name,
"relevance")
956 || !strcmp((
const char *) n->name,
"sort")
957 || !strcmp((
const char *) n->name,
"mergekey")
958 || !strcmp((
const char *) n->name,
"facet"))
963 (
const char *) n->name))
965 yaz_log(YLOG_FATAL,
"ICU chain definition error");
969 else if (!strcmp((
const char *) n->name,
"service"))
971 char *service_id = (
char *)
972 xmlGetProp(n, (xmlChar *)
"id");
975 for (; *sp; sp = &(*sp)->
next)
976 if ((*sp)->id && service_id &&
977 0 == strcmp((*sp)->id, service_id))
979 yaz_log(YLOG_FATAL,
"Duplicate service: %s", service_id);
982 else if (!(*sp)->id && !service_id)
984 yaz_log(YLOG_FATAL,
"Duplicate unnamed service");
1005 yaz_log(YLOG_FATAL,
"Bad element: %s", n->name);
1011 yaz_log(YLOG_FATAL,
"No listening port given");
1025 WRBUF w = wrbuf_alloc();
1032 const char *service_id)
1035 for (; s; s = s->
next)
1036 if (s->
id && service_id && 0 == strcmp(s->
id, service_id))
1038 else if (!s->
id && !service_id)
1055 wrbuf_puts(w,
" <metadata");
1057 wrbuf_puts(w,
" name=\"");
1058 wrbuf_xmlputs(w, md->
name);
1059 wrbuf_puts(w,
"\"");
1062 wrbuf_puts(w,
" brief=\"yes\"");
1065 wrbuf_puts(w,
" termlist=\"yes\"");
1068 wrbuf_puts(w,
" rank=\"");
1069 wrbuf_xmlputs(w, md->
rank);
1070 wrbuf_puts(w,
"\"");
1073 wrbuf_puts(w,
" sortkey=\"");
1077 wrbuf_puts(w,
"relevance");
1080 wrbuf_puts(w,
"skiparticle");
1083 wrbuf_puts(w,
"position");
1086 wrbuf_puts(w,
"retrieval");
1089 wrbuf_puts(w,
"yes");
1092 wrbuf_puts(w,
"\"");
1100 wrbuf_puts(w,
" type=\"year\"");
1103 wrbuf_puts(w,
" type=\"date\"");
1106 wrbuf_puts(w,
" type=\"float\"");
1116 wrbuf_puts(w,
" merge=\"unique\"");
1119 wrbuf_puts(w,
" merge=\"longest\"");
1122 wrbuf_puts(w,
" merge=\"range\"");
1125 wrbuf_puts(w,
" merge=\"all\"");
1128 wrbuf_puts(w,
" merge=\"first\"");
1136 wrbuf_puts(w,
" mergekey=\"optional\"");
1139 wrbuf_puts(w,
" mergekey=\"required\"");
1142 wrbuf_puts(w,
" />\n");
1153 wrbuf_puts(w,
" <databases>\n");
1157 wrbuf_puts(w,
" <database");
1160 wrbuf_puts(w,
" id=\"");
1161 wrbuf_printf(w,
"%s", db->
id);
1162 wrbuf_puts(w,
"\"");
1164 wrbuf_puts(w,
">\n");
1168 for (; s; s = s->
next)
1170 wrbuf_puts(w,
" <setting name=\"");
1171 wrbuf_xmlputs(w, s->
name);
1172 wrbuf_puts(w,
"\"");
1173 wrbuf_puts(w,
" value=\"");
1174 wrbuf_xmlputs(w, s->
value);
1175 wrbuf_puts(w,
"\"");
1176 wrbuf_puts(w,
" />\n");
1179 wrbuf_puts(w,
" </database>\n");
1181 wrbuf_puts(w,
" </databases>\n");
1190 wrbuf_puts(w,
" <services>\n");
1191 for (; s; s = s->
next)
1193 wrbuf_puts(w,
" <service");
1196 wrbuf_puts(w,
" id=\"");
1197 wrbuf_xmlputs(w, s->
id);
1198 wrbuf_puts(w,
"\"");
1200 wrbuf_puts(w,
">\n");
1206 for (; S; S = S->
next)
1208 wrbuf_puts(w,
" <setting name=\"");
1209 wrbuf_xmlputs(w, S->
name);
1210 wrbuf_puts(w,
"\"");
1211 wrbuf_puts(w,
" value=\"");
1212 wrbuf_xmlputs(w, S->
value);
1213 wrbuf_puts(w,
"\"");
1216 wrbuf_puts(w,
" target=\"");
1217 wrbuf_xmlputs(w, S->
target);
1218 wrbuf_puts(w,
"\"");
1220 wrbuf_puts(w,
" />\n");
1226 wrbuf_puts(w,
" </service>\n");
1228 wrbuf_puts(w,
" </services>\n");
1235 for (n = root->children; n; n = n->next)
1237 if (n->type != XML_ELEMENT_NODE)
1239 if (!strcmp((
const char *) n->name,
"server"))
1247 else if (!strcmp((
const char *) n->name,
"threads"))
1249 xmlChar *number = xmlGetProp(n, (xmlChar *)
"number");
1256 else if (!strcmp((
const char *) n->name,
"sockets"))
1258 xmlChar *number = xmlGetProp(n, (xmlChar *)
"max");
1265 else if (!strcmp((
const char *) n->name,
"file"))
1267 xmlChar *path = xmlGetProp(n, (xmlChar *)
"path");
1274 else if (!strcmp((
const char *) n->name,
"targetprofiles"))
1276 yaz_log(YLOG_FATAL,
"targetprofiles unsupported here. Must be part of service");
1282 yaz_log(YLOG_FATAL,
"Bad element: %s", n->name);
1291 xmlDoc *doc = xmlReadFile(fname,
1294 + XML_PARSE_NSCLEAN + XML_PARSE_NONET);
1298 NMEM
nmem = nmem_create();
1301 xmlSubstituteEntitiesDefault(1);
1302 xmlLoadExtDtdDefaultValue = 1;
1305 yaz_log(YLOG_FATAL,
"Failed to read %s", fname);
1311 r = xmlXIncludeProcess(doc);
1314 yaz_log(YLOG_FATAL,
"XInclude processing failed");
1320 config->
path = nmem_strdup(
nmem,
".");
1325 config->
confdir = wrbuf_alloc();
1326 if ((p = strrchr(fname,
1334 int len = p - fname;
1335 wrbuf_write(config->
confdir, fname, len);
1337 wrbuf_puts(config->
confdir,
"");
1339 n = xmlDocGetRootElement(doc);
1340 r = yaz_xml_include_simple(n, wrbuf_cstr(config->
confdir));
1345 yaz_log(YLOG_LOG,
"Configuration %s after include processing",
1347 xmlDocDumpMemory(doc, &buf_out, &len_out);
1348 yaz_log(YLOG_LOG,
"%.*s", len_out, buf_out);
1407 for (;s ; s = s->
next)
1409 assert(s->
mutex == 0);
1418 const char *listener_override,
1419 const char *record_fname)
1430 if (listener_override)
1432 const char *cp = strrchr(listener_override,
':');
1435 ser->
host = nmem_strdupn(conf->
nmem, listener_override,
1436 cp - listener_override);
1437 ser->
port = nmem_strdup(conf->
nmem, cp + 1);
1442 ser->
port = nmem_strdup(conf->
nmem, listener_override);
1444 listener_override = 0;
int pp2_charset_fact_define(pp2_charset_fact_t pft, xmlNode *xml_node, const char *id)
pp2_charset_fact_t pp2_charset_fact_create(void)
void pp2_charset_fact_incref(pp2_charset_fact_t pft)
void pp2_charset_fact_destroy(pp2_charset_fact_t pft)
void iochan_man_events(iochan_man_t man)
void iochan_man_destroy(iochan_man_t *mp)
iochan_man_t iochan_man_create(int no_threads, int max_sockets)
void http_set_proxyaddr(const char *host, struct conf_server *server)
int http_init(struct conf_server *server, const char *record_fname)
void http_close_server(struct conf_server *server)
void http_mutex_init(struct conf_server *server)
void http_server_destroy(http_server_t hs)
int pazpar2_decref(int *ref, YAZ_MUTEX mutex)
void pazpar2_incref(int *ref, YAZ_MUTEX mutex)
MUTEX protect ref counts.
static void info_service_databases(struct conf_service *service, WRBUF w)
struct conf_service * locate_service(struct conf_server *server, const char *service_id)
void config_destroy(struct conf_config *config)
int config_start_listeners(struct conf_config *conf, const char *listener_override, const char *record_fname)
struct conf_config * config_create(const char *fname)
static int inherit_server_settings(struct conf_service *s)
void info_services(struct conf_server *server, WRBUF w)
static struct conf_server * server_create(struct conf_config *config, NMEM nmem, xmlNode *node)
void service_destroy(struct conf_service *service)
static int parse_metadata(struct conf_service *service, xmlNode *n, int *md_node, int *sk_node)
WRBUF conf_get_fname(struct conf_config *config, const char *fname)
static int parse_config(struct conf_config *config, xmlNode *root)
static struct conf_metadata * conf_service_add_metadata(struct conf_service *service, int field_id, const char *name, enum conf_metadata_type type, enum conf_metadata_merge merge, enum conf_setting_type setting, int brief, int termlist, const char *rank, int sortkey_offset, enum conf_metadata_mergekey mt, const char *facetrule, const char *limitmap, const char *limitcluster, const char *icurule)
static void info_service_metadata(struct conf_service *service, WRBUF w)
struct conf_service * service_init(struct conf_server *server, int num_metadata, int num_sortkeys, const char *service_id)
static struct conf_sortkey * conf_service_add_sortkey(struct conf_service *service, int field_id, const char *name, enum conf_metadata_type type)
static struct conf_service * service_create_static(struct conf_server *server, xmlNode *node, const char *service_id)
static void conf_dir_path(struct conf_config *config, WRBUF w, const char *src)
void config_stop_listeners(struct conf_config *conf)
struct conf_service * service_create(struct conf_server *server, xmlNode *node)
void config_process_events(struct conf_config *conf)
int conf_service_sortkey_field_id(struct conf_service *service, const char *name)
void server_destroy(struct conf_server *server)
static void count_metadata(xmlNode *n, int *num_metadata, int *num_sortkeys)
void service_incref(struct conf_service *service)
static char * xml_context(const xmlNode *ptr, char *res, size_t len)
int conf_service_metadata_field_id(struct conf_service *service, const char *name)
@ Metadata_type_relevance
@ Metadata_type_retrieval
@ Metadata_type_skiparticle
@ Metadata_mergekey_required
@ Metadata_mergekey_optional
@ Metadata_setting_parameter
@ Metadata_setting_postproc
void pazpar2_mutex_create(YAZ_MUTEX *p, const char *name)
int service_xslt_config(struct conf_service *service, xmlNode *n)
void service_xslt_destroy(struct conf_service *service)
int settings_read_node(struct conf_service *service, xmlNode *n, int pass)
void init_settings(struct conf_service *service)
int settings_read_file(struct conf_service *service, const char *path, int pass)
struct conf_server * servers
struct conf_config * config
http_server_t http_server
struct conf_server * next
pp2_charset_fact_t charsets
struct conf_service * service
int z3950_operation_timeout
pp2_charset_fact_t charsets
struct setting_dictionary * dictionary
struct conf_sortkey * sortkeys
struct conf_server * server
int z3950_session_timeout
struct service_xslt * xslt_list
struct conf_metadata * metadata
struct database * databases
struct conf_service * next
struct settings_array * settings
enum conf_metadata_type type
struct setting ** settings
struct service_xslt * next
struct setting ** settings