Better diagnostics. Default is, that only one database selected when
[egate.git] / kernel / main.c
1 /* Gateway kernel
2  * Europagate, 1995
3  *
4  * $Log: main.c,v $
5  * Revision 1.10  1995/03/01 14:32:25  adam
6  * Better diagnostics. Default is, that only one database selected when
7  * several are known.
8  *
9  * Revision 1.9  1995/02/23  08:32:17  adam
10  * Changed header.
11  *
12  * Revision 1.7  1995/02/22  15:22:33  adam
13  * Much more checking of run-time state. Show command never retrieves
14  * more records than indicated by the previous search request. Help
15  * command available. The maximum number of records retrieved can be
16  * controlled now.
17  *
18  * Revision 1.6  1995/02/22  08:51:34  adam
19  * Output function can be customized in fml, which is used to print
20  * the reply to reply_fd.
21  *
22  * Revision 1.5  1995/02/20  21:16:20  adam
23  * FML support. Bug fixes. Profile for drewdb.
24  *
25  * Revision 1.4  1995/02/17  17:06:16  adam
26  * Minor changes.
27  *
28  * Revision 1.3  1995/02/16  18:35:09  adam
29  * First use of Zdist library. Search requests are supported.
30  * Present requests are not supported yet.
31  *
32  * Revision 1.2  1995/02/16  13:21:00  adam
33  * Organization of resource files for targets and conversion
34  * language implemented.
35  *
36  * Revision 1.1  1995/02/15  17:45:29  adam
37  * First version of email gateway kernel. Email requests are read
38  * from stdin. The output is transferred to an MTA if 'From' is
39  * found in the header - or stdout if absent. No Z39.50 client is used.
40  *
41  */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <assert.h>
47
48 #include "kernel.h"
49
50 FILE *reply_fd = stdout;
51
52 struct gw_kernel_info info;
53
54 int main (int argc, char **argv)
55 {
56     info.kernel_res = NULL;
57     info.default_res = "default.res";
58     info.override_res = NULL;
59     *info.target = 0;
60     info.lang = NULL;
61     info.bibset = NULL;
62     info.zass = NULL;
63     info.override_portno = NULL;
64     info.override_hostname = NULL;
65     info.databases = NULL;
66     info.database = NULL;
67 #if USE_FML
68     info.fml = NULL;
69 #endif
70     info.sets = NULL;
71
72     gw_log_init (*argv);
73     info.kernel_res = gw_res_init ();
74     while (--argc > 0)
75     {
76         if (**++argv == '-')
77         {
78             switch (argv[0][1])
79             {
80             case 'd':
81                 gw_log_level (GW_LOG_ALL);
82                 break;
83             case 't':
84                 if (argv[0][2])
85                     strcpy (info.target, argv[0]+2);
86                 else if (argc > 0)
87                 {
88                     --argc;
89                     strcpy (info.target, *++argv);
90                 }
91                 else
92                 {
93                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing target name");
94                     exit (1);
95                 }
96                 break;
97             case 'l':
98                 if (argv[0][2])
99                     info.lang = argv[0]+2;
100                 else if (argc > 0)
101                 {
102                     --argc;
103                     info.lang = *++argv;
104                 }
105                 else
106                 {
107                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing language name");
108                     exit (1);
109                 }
110                 break;
111             case 'o':
112                 if (argv[0][2])
113                     info.override_res = argv[0]+2;
114                 else if (argc > 0)
115                 {
116                     --argc;
117                     info.override_res = *++argv;
118                 }
119                 else
120                 {
121                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing language name");
122                     exit (1);
123                 }
124                 break;
125             case 'p':
126                 if (argv[0][2])
127                     info.override_portno = argv[0]+2;
128                 else if (argc > 0)
129                 {
130                     --argc;
131                     info.override_portno = *++argv;
132                 }
133                 else
134                 {
135                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing portno");
136                     exit (1);
137                 }
138                 break;
139             case 'h':
140                 if (argv[0][2])
141                     info.override_hostname = argv[0]+2;
142                 else if (argc > 0)
143                 {
144                     --argc;
145                     info.override_hostname = *++argv;
146                 }
147                 else
148                 {
149                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing hostname");
150                     exit (1);
151                 }
152                 break;
153             case 'g':
154                 if (argv[0][2])
155                     gw_log_file (GW_LOG_ALL, argv[0]+2);
156                 else if (argc > 0)
157                 {
158                     --argc;
159                     gw_log_file (GW_LOG_ALL, *++argv);
160                 }
161                 else
162                 {
163                     gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing log filename");
164                     exit (1);
165                 }
166                 break;
167             default:
168                 gw_log (GW_LOG_FATAL, KERNEL_LOG, "unknown option %s", *argv);
169                 exit (1);
170             }
171         }
172         else
173             info.default_res = *argv;
174     }
175     read_kernel_res ();
176     urp (stdin);
177     return 0;
178 }
179
180 struct gw_user_set *user_set_add (const char *name, int hits)
181 {
182     struct gw_user_set *s;
183
184     s = malloc (sizeof (*s));
185     assert (s);
186
187     s->name = gw_strdup (name);
188     s->hits = hits;
189     s->prev = info.sets;
190     info.sets = s;
191     return s;
192 }
193
194 void user_set_init (void)
195 {
196     struct gw_user_set *s, *s1;
197
198     for (s = info.sets; s; s = s1)
199     {
200         free (s->name);
201         s1 = s->prev;
202         free (s);
203     }
204     info.sets = NULL;
205 }
206
207 struct gw_user_set *user_set_search (const char *name)
208 {
209     struct gw_user_set *s;
210
211     if (!name)
212         return info.sets;
213     for (s = info.sets; s; s = s->prev)
214         if (!strcmp (s->name, name))
215             return s;
216     return NULL;
217 }
218
219 #if USE_FML
220 static void fml_inf_write (int ch)
221 {
222     putc (ch, reply_fd);
223 }
224 static FILE *fml_inf;
225
226 static int fml_inf_read (void)
227 {
228     return getc (fml_inf);
229 }
230 #endif
231
232 void read_kernel_res (void)
233 {
234     char path_prefix[128];
235     char fname[160];
236     const char *v;
237     char *cp;
238     char resource_name[256];
239
240     user_set_init ();
241
242     if (info.bibset)
243         ccl_qual_rm (&info.bibset);
244     info.bibset = ccl_qual_mk ();
245
246     if (info.kernel_res)
247         gw_res_close (info.kernel_res);
248     info.kernel_res = gw_res_init ();
249
250     gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, default %s",
251             info.default_res);
252     if (*info.target)
253         gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, target %s",
254                 info.target);
255     if (info.lang)
256         gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, lang %s",
257                 info.lang);
258
259     if (gw_res_merge (info.kernel_res, info.default_res))
260     {
261         gw_log (GW_LOG_WARN, KERNEL_LOG, "Couldn't read resource file %s",
262                 info.default_res);
263         return;
264     }
265     strcpy (path_prefix, gw_res_get (info.kernel_res, "gw.path", "."));
266     
267     if (*info.target)
268     {
269         sprintf (resource_name, "gw.target.%s", info.target);
270         v = gw_res_get (info.kernel_res, resource_name, NULL);
271         if (v)
272         {
273             sprintf (fname, "%s/%s", path_prefix, v);
274             gw_res_merge (info.kernel_res, fname);
275         }
276     }
277     if (info.lang)
278     {
279         sprintf (resource_name, "gw.lang.%s", info.lang);
280         v = gw_res_get (info.kernel_res, resource_name, NULL);
281         if (v)
282         {
283             sprintf (fname, "%s/%s", path_prefix, v);
284             gw_res_merge (info.kernel_res, fname);
285         }
286     }
287     if (info.override_res)
288     {
289         sprintf (fname, "%s/%s", path_prefix, info.override_res);
290         gw_res_merge (info.kernel_res, fname);        
291     }
292     v = gw_res_get (info.kernel_res, "gw.bibset", NULL);
293     if (v)
294     {
295         FILE *bib_inf;
296
297         sprintf (fname, "%s/%s", path_prefix, v);
298         bib_inf = fopen (fname, "r");
299         if (!bib_inf)
300             gw_log (GW_LOG_WARN, KERNEL_LOG, "cannot open %s", fname);
301         else
302         {
303             gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading bib file %s", fname);
304             ccl_qual_file (info.bibset, bib_inf);
305             fclose (bib_inf);
306         }
307     }
308     sprintf (resource_name, "gw.target.%s", info.target);
309     if (*info.target && ! gw_res_get (info.kernel_res, resource_name, NULL))
310     {
311         /* target is there, and there is no sub-resource for it... */
312         char *split;
313
314         if ((split = strchr (info.target, ':')))
315             *split++ = '\0';
316         strncpy (info.hostname, info.target, sizeof(info.hostname)-1);
317         if (split)
318             info.port = atoi (split);
319         else
320             info.port = atoi (gw_res_get
321                               (info.kernel_res, "gw.portno", "210"));
322     }
323     else
324     {
325         strncpy (info.hostname, gw_res_get (info.kernel_res,
326                                             "gw.hostname", "localhost"),
327                  sizeof(info.hostname)-1);
328         info.port = atoi (gw_res_get (info.kernel_res,
329                                       "gw.portno", "210"));
330     }
331     if (info.databases)
332         free (info.databases);
333     if (info.database)
334         free (info.database);
335     v = gw_res_get (info.kernel_res, "gw.databases", "");
336     info.databases = gw_strdup (v);
337     for (cp = info.databases; (cp = strchr (cp, ' ')); cp++)
338         *cp = ',';
339     v = gw_res_get (info.kernel_res, "gw.database", "");
340     if (*v == '\0' && *info.databases)
341     {
342         int len;
343         cp = strchr (info.databases, ',');
344         
345         len = cp ? (cp-info.databases) : strlen (info.databases);
346         info.database = malloc (len+1);
347         assert (info.database);
348         memcpy (info.database, info.databases, len);
349         info.database[len] = '\0';
350     }
351     else
352     {
353         info.database = gw_strdup (v);
354         for (cp = info.database; (cp = strchr (cp, ' ')); cp++)
355             *cp = ',';
356     }
357     if (info.override_portno)
358         info.port = atoi (info.override_portno);
359     if (info.override_hostname)
360         strncpy (info.hostname, info.override_hostname,
361                  sizeof(info.hostname)-1);
362 #if USE_FML
363     if (!info.fml)
364     {
365         v = gw_res_get (info.kernel_res, "gw.fml", "default.fml");    
366         sprintf (fname, "%s/%s", path_prefix, v);
367         fml_inf = fopen (fname, "r");
368         if (!fml_inf)
369             gw_log (GW_LOG_WARN, KERNEL_LOG,
370                     "cannot open fml script %s", fname);
371         else
372         {
373             info.fml = fml_open ();
374             info.fml->read_func = fml_inf_read;
375             info.fml->write_func = fml_inf_write;
376             fml_preprocess (info.fml);
377             fml_exec (info.fml);
378             fclose (fml_inf);
379         }
380     }
381 #endif
382 }