removing the XSLT filter from the build, only keeping the ALVIS filter
[idzebra-moved-to-github.git] / recctrl / recctrl.c
1 /* $Id: recctrl.c,v 1.26 2006-05-31 16:11:58 marc 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_GRS_CSV
104     if (1)
105     {
106         extern RecType idzebra_filter_grs_csv[];
107         recTypeClass_add (&rts, idzebra_filter_grs_csv, nmem, 0);
108     }
109 #endif
110
111 #ifdef IDZEBRA_STATIC_GRS_DANBIB
112     if (1)
113     {
114         extern RecType idzebra_filter_grs_danbib[];
115         recTypeClass_add (&rts, idzebra_filter_grs_danbib, nmem, 0);
116     }
117 #endif
118
119 #ifdef IDZEBRA_STATIC_SAFARI
120     if (1)
121     {
122         extern RecType idzebra_filter_safari[];
123         recTypeClass_add (&rts, idzebra_filter_safari, nmem, 0);
124     }
125 #endif
126
127 #ifdef IDZEBRA_STATIC_ALVIS
128 #if HAVE_XSLT
129     if (1)
130     {
131         extern RecType idzebra_filter_alvis[];
132         recTypeClass_add (&rts, idzebra_filter_alvis, nmem, 0);
133     }
134 #endif
135 #endif
136
137
138 #ifdef IDZEBRA_STATIC_XSLT
139 #if HAVE_XSLT
140     if (0)
141     {
142         extern RecType idzebra_filter_xslt[];
143         recTypeClass_add (&rts, idzebra_filter_xslt, nmem, 0);
144     }
145 #endif
146 #endif
147
148     return rts;
149 }
150
151 void recTypeClass_load_modules(RecTypeClass *rts, NMEM nmem,
152                                const char *module_path)
153 {
154 #if HAVE_DLFCN_H
155     if (module_path)
156     {
157         DIR *dir = opendir(module_path);
158         yaz_log(YLOG_LOG, "searching filters in %s", module_path);
159         if (dir)
160         {
161             struct dirent *de;
162
163             while ((de = readdir(dir)))
164             {
165                 size_t dlen = strlen(de->d_name);
166                 if (dlen >= 5 &&
167                     !memcmp(de->d_name, "mod-", 4) &&
168                     !strcmp(de->d_name + dlen - 3, ".so"))
169                 {
170                     void *mod_p, *fl;
171                     char fname[FILENAME_MAX*2+1];
172                     sprintf(fname, "%.*s/%.*s",
173                             FILENAME_MAX, module_path,
174                             FILENAME_MAX, de->d_name);
175                     mod_p = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
176                     if (mod_p && (fl = dlsym(mod_p, "idzebra_filter")))
177                     {
178                         yaz_log(YLOG_LOG, "Loaded filter module %s", fname);
179                         recTypeClass_add(rts, fl, nmem, mod_p);
180                     }
181                     else if (mod_p)
182                     {
183                         const char *err = dlerror();
184                         yaz_log(YLOG_WARN, "dlsym failed %s %s",
185                                 fname, err ? err : "none");
186                         dlclose(mod_p);
187                     }
188                     else
189                     {
190                         const char *err = dlerror();
191                         yaz_log(YLOG_WARN, "dlopen failed %s %s",
192                                 fname, err ? err : "none");
193                         
194                     }
195                 }
196             }
197             closedir(dir);
198         }
199     }
200 #endif
201 }
202
203 static void recTypeClass_add(struct recTypeClass **rts, RecType *rt,
204                              NMEM nmem, void *module_handle)
205 {
206     while (*rt)
207     {
208         struct recTypeClass *r = (struct recTypeClass *)
209             nmem_malloc (nmem, sizeof(*r));
210         
211         r->next = *rts;
212         *rts = r;
213
214         yaz_log(YLOG_LOG, "Adding filter %s", (*rt)->name);
215         r->module_handle = module_handle;
216         module_handle = 0; /* so that we only store module_handle once */
217         r->recType = *rt;
218
219         rt++;
220     }
221 }
222
223 void recTypeClass_info(RecTypeClass rtc, void *cd,
224                        void (*cb)(void *cd, const char *s))
225 {
226     for (; rtc; rtc = rtc->next)
227         (*cb)(cd, rtc->recType->name);
228 }
229
230 void recTypeClass_destroy(RecTypeClass rtc)
231 {
232     for (; rtc; rtc = rtc->next)
233     {
234 #if HAVE_DLFCN_H
235         if (rtc->module_handle)
236             dlclose(rtc->module_handle);
237 #endif
238     }
239 }
240
241 RecTypes recTypes_init(RecTypeClass rtc, data1_handle dh)
242 {
243     RecTypes rts = (RecTypes) nmem_malloc(data1_nmem_get(dh), sizeof(*rts));
244
245     struct recTypeInstance **rti = &rts->entries;
246     
247     rts->dh = dh;
248
249     for (; rtc; rtc = rtc->next)
250     {
251         *rti = nmem_malloc(data1_nmem_get(dh), sizeof(**rti));
252         (*rti)->recType = rtc->recType;
253         (*rti)->init_flag = 0;
254         rti = &(*rti)->next;
255     }
256     *rti = 0;
257     return rts;
258 }
259
260 void recTypes_destroy (RecTypes rts)
261 {
262     struct recTypeInstance *rti;
263
264     for (rti = rts->entries; rti; rti = rti->next)
265     {
266         if (rti->init_flag)
267             (*(rti->recType)->destroy)(rti->clientData);
268     }
269 }
270
271 RecType recType_byName (RecTypes rts, Res res, const char *name,
272                         void **clientDataP)
273 {
274     struct recTypeInstance *rti;
275
276     for (rti = rts->entries; rti; rti = rti->next)
277     {
278         size_t slen = strlen(rti->recType->name);
279         if (!strncmp (rti->recType->name, name, slen)
280             && (name[slen] == '\0' || name[slen] == '.'))
281         {
282             if (!rti->init_flag)
283             {
284                 rti->init_flag = 1;
285                 rti->clientData =
286                     (*(rti->recType)->init)(res, rti->recType);
287             }
288             *clientDataP = rti->clientData;
289             if (name[slen])
290                 slen++;  /* skip . */
291
292             if (rti->recType->config)
293             {
294                 if ((*(rti->recType)->config)
295                     (rti->clientData, res, name+slen) != ZEBRA_OK)
296                     return 0;
297             }
298             return rti->recType;
299         }
300     }
301     return 0;
302 }
303
304 /*
305  * Local variables:
306  * c-basic-offset: 4
307  * indent-tabs-mode: nil
308  * End:
309  * vim: shiftwidth=4 tabstop=8 expandtab
310  */
311