Build main libidzebra-2.0.la. Bug #620.
[idzebra-moved-to-github.git] / index / recctrl.c
1 /* $Id: recctrl.c,v 1.1 2006-07-03 14:27:09 adam Exp $
2    Copyright (C) 1995-2006
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24 #include <stdio.h>
25 #include <assert.h>
26 #include <string.h>
27 #if HAVE_DLFCN_H
28 #include <dlfcn.h>
29 #endif
30
31 #include <direntz.h>
32 #include <idzebra/util.h>
33 #include <idzebra/recctrl.h>
34
35 struct recTypeClass {
36     RecType recType;
37     struct recTypeClass *next;
38     void *module_handle;
39 };
40
41 struct recTypeInstance {
42     RecType recType;
43     struct recTypeInstance *next;
44     int init_flag;
45     void *clientData;
46 };
47
48 struct recTypes {
49     data1_handle dh;
50     struct recTypeInstance *entries;
51 };
52
53 static void recTypeClass_add (struct recTypeClass **rts, RecType *rt,
54                               NMEM nmem, void *module_handle);
55
56
57 RecTypeClass recTypeClass_create (Res res, NMEM nmem)
58 {
59     struct recTypeClass *rts = 0;
60
61 #ifdef IDZEBRA_STATIC_GRS_SGML
62     if (1)
63     {
64         extern RecType idzebra_filter_grs_sgml[];
65         recTypeClass_add (&rts, idzebra_filter_grs_sgml, nmem, 0);
66     }
67 #endif
68
69 #ifdef IDZEBRA_STATIC_TEXT
70     if (1)
71     {
72         extern RecType idzebra_filter_text[];
73         recTypeClass_add (&rts, idzebra_filter_text, nmem, 0);
74     }
75 #endif
76
77 #ifdef IDZEBRA_STATIC_GRS_XML
78 #if HAVE_EXPAT_H
79     if (1)
80     {
81         extern RecType idzebra_filter_grs_xml[];
82         recTypeClass_add (&rts, idzebra_filter_grs_xml, nmem, 0);
83     }
84 #endif
85 #endif
86
87 #ifdef IDZEBRA_STATIC_GRS_REGX
88     if (1)
89     {
90         extern RecType idzebra_filter_grs_regx[];
91         recTypeClass_add (&rts, idzebra_filter_grs_regx, nmem, 0);
92     }
93 #endif
94
95 #ifdef IDZEBRA_STATIC_GRS_MARC
96     if (1)
97     {
98         extern RecType idzebra_filter_grs_marc[];
99         recTypeClass_add (&rts, idzebra_filter_grs_marc, nmem, 0);
100     }
101 #endif
102
103 #ifdef IDZEBRA_STATIC_SAFARI
104     if (1)
105     {
106         extern RecType idzebra_filter_safari[];
107         recTypeClass_add (&rts, idzebra_filter_safari, nmem, 0);
108     }
109 #endif
110
111 #ifdef IDZEBRA_STATIC_ALVIS
112 #if HAVE_XSLT
113     if (1)
114     {
115         extern RecType idzebra_filter_alvis[];
116         recTypeClass_add (&rts, idzebra_filter_alvis, nmem, 0);
117     }
118 #endif
119 #endif
120
121     return rts;
122 }
123
124 void recTypeClass_load_modules(RecTypeClass *rts, NMEM nmem,
125                                const char *module_path)
126 {
127 #if HAVE_DLFCN_H
128     if (module_path)
129     {
130         DIR *dir = opendir(module_path);
131         yaz_log(YLOG_LOG, "searching filters in %s", module_path);
132         if (dir)
133         {
134             struct dirent *de;
135
136             while ((de = readdir(dir)))
137             {
138                 size_t dlen = strlen(de->d_name);
139                 if (dlen >= 5 &&
140                     !memcmp(de->d_name, "mod-", 4) &&
141                     !strcmp(de->d_name + dlen - 3, ".so"))
142                 {
143                     void *mod_p, *fl;
144                     char fname[FILENAME_MAX*2+1];
145                     sprintf(fname, "%.*s/%.*s",
146                             FILENAME_MAX, module_path,
147                             FILENAME_MAX, de->d_name);
148                     mod_p = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
149                     if (mod_p && (fl = dlsym(mod_p, "idzebra_filter")))
150                     {
151                         yaz_log(YLOG_LOG, "Loaded filter module %s", fname);
152                         recTypeClass_add(rts, fl, nmem, mod_p);
153                     }
154                     else if (mod_p)
155                     {
156                         const char *err = dlerror();
157                         yaz_log(YLOG_WARN, "dlsym failed %s %s",
158                                 fname, err ? err : "none");
159                         dlclose(mod_p);
160                     }
161                     else
162                     {
163                         const char *err = dlerror();
164                         yaz_log(YLOG_WARN, "dlopen failed %s %s",
165                                 fname, err ? err : "none");
166                         
167                     }
168                 }
169             }
170             closedir(dir);
171         }
172     }
173 #endif
174 }
175
176 static void recTypeClass_add(struct recTypeClass **rts, RecType *rt,
177                              NMEM nmem, void *module_handle)
178 {
179     while (*rt)
180     {
181         struct recTypeClass *r = (struct recTypeClass *)
182             nmem_malloc (nmem, sizeof(*r));
183         
184         r->next = *rts;
185         *rts = r;
186
187         yaz_log(YLOG_LOG, "Adding filter %s", (*rt)->name);
188         r->module_handle = module_handle;
189         module_handle = 0; /* so that we only store module_handle once */
190         r->recType = *rt;
191
192         rt++;
193     }
194 }
195
196 void recTypeClass_info(RecTypeClass rtc, void *cd,
197                        void (*cb)(void *cd, const char *s))
198 {
199     for (; rtc; rtc = rtc->next)
200         (*cb)(cd, rtc->recType->name);
201 }
202
203 void recTypeClass_destroy(RecTypeClass rtc)
204 {
205     for (; rtc; rtc = rtc->next)
206     {
207 #if HAVE_DLFCN_H
208         if (rtc->module_handle)
209             dlclose(rtc->module_handle);
210 #endif
211     }
212 }
213
214 RecTypes recTypes_init(RecTypeClass rtc, data1_handle dh)
215 {
216     RecTypes rts = (RecTypes) nmem_malloc(data1_nmem_get(dh), sizeof(*rts));
217
218     struct recTypeInstance **rti = &rts->entries;
219     
220     rts->dh = dh;
221
222     for (; rtc; rtc = rtc->next)
223     {
224         *rti = nmem_malloc(data1_nmem_get(dh), sizeof(**rti));
225         (*rti)->recType = rtc->recType;
226         (*rti)->init_flag = 0;
227         rti = &(*rti)->next;
228     }
229     *rti = 0;
230     return rts;
231 }
232
233 void recTypes_destroy (RecTypes rts)
234 {
235     struct recTypeInstance *rti;
236
237     for (rti = rts->entries; rti; rti = rti->next)
238     {
239         if (rti->init_flag)
240             (*(rti->recType)->destroy)(rti->clientData);
241     }
242 }
243
244 RecType recType_byName (RecTypes rts, Res res, const char *name,
245                         void **clientDataP)
246 {
247     struct recTypeInstance *rti;
248
249     for (rti = rts->entries; rti; rti = rti->next)
250     {
251         size_t slen = strlen(rti->recType->name);
252         if (!strncmp (rti->recType->name, name, slen)
253             && (name[slen] == '\0' || name[slen] == '.'))
254         {
255             if (!rti->init_flag)
256             {
257                 rti->init_flag = 1;
258                 rti->clientData =
259                     (*(rti->recType)->init)(res, rti->recType);
260             }
261             *clientDataP = rti->clientData;
262             if (name[slen])
263                 slen++;  /* skip . */
264
265             if (rti->recType->config)
266             {
267                 if ((*(rti->recType)->config)
268                     (rti->clientData, res, name+slen) != ZEBRA_OK)
269                     return 0;
270             }
271             return rti->recType;
272         }
273     }
274     return 0;
275 }
276
277 /*
278  * Local variables:
279  * c-basic-offset: 4
280  * indent-tabs-mode: nil
281  * End:
282  * vim: shiftwidth=4 tabstop=8 expandtab
283  */
284