2 * Copyright (c) 1995, the EUROPAGATE consortium (see below).
4 * The EUROPAGATE consortium members are:
6 * University College Dublin
7 * Danmarks Teknologiske Videnscenter
8 * An Chomhairle Leabharlanna
9 * Consejo Superior de Investigaciones Cientificas
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation, in whole or in part, for any purpose, is hereby granted,
15 * 1. This copyright and permission notice appear in all copies of the
16 * software and its documentation. Notices of copyright or attribution
17 * which appear at the beginning of any file must remain unchanged.
19 * 2. The names of EUROPAGATE or the project partners may not be used to
20 * endorse or promote products derived from this software without specific
21 * prior written permission.
23 * 3. Users of this software (implementors and gateway operators) agree to
24 * inform the EUROPAGATE consortium of their use of the software. This
25 * information will be used to evaluate the EUROPAGATE project and the
26 * software, and to plan further developments. The consortium may use
27 * the information in later publications.
29 * 4. Users of this software agree to make their best efforts, when
30 * documenting their use of the software, to acknowledge the EUROPAGATE
31 * consortium, and the role played by the software in their work.
33 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34 * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36 * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37 * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38 * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39 * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40 * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41 * USE OR PERFORMANCE OF THIS SOFTWARE.
44 /* Gateway kernel - Main
48 * Revision 1.25 1995/05/16 09:40:42 adam
49 * LICENSE. Setting of CCL token names (and/or/not/set) in read_kernel_res.
51 * Revision 1.24 1995/05/04 10:40:07 adam
52 * More work on Def-settings.
54 * Revision 1.23 1995/05/03 16:34:18 adam
55 * CCL def command, i.e. user definitions - saved as resource files.
57 * Revision 1.22 1995/05/03 07:37:39 adam
58 * CCL commands stop/continue implemented. New functions gw_res_{int,bool}
59 * are used when possible.
61 * Revision 1.21 1995/05/01 16:26:56 adam
62 * More work on resource monitor.
64 * Revision 1.20 1995/05/01 12:43:32 adam
65 * First work on resource monitor program.
67 * Revision 1.19 1995/04/19 16:01:58 adam
68 * Some hacks to get the FIFO communication work!! Isn't reliable.
69 * Resource gw.account added - default account info.
71 * Revision 1.18 1995/04/19 13:19:09 adam
72 * New command: account - for authentication.
74 * Revision 1.17 1995/04/19 10:46:18 adam
75 * Persistency works much better now. New command: status - history-like
77 * Revision 1.16 1995/04/19 07:31:07 adam
78 * First work on Z39.50 persistence.
80 * Revision 1.15 1995/04/17 09:34:30 adam
81 * Timeout (idletime) adjustable. Minor changes in kernel.
83 * Revision 1.14 1995/03/28 11:42:34 adam
84 * First use of string-queue utility.
86 * Revision 1.13 1995/03/28 08:01:25 adam
87 * FIFO existence is used to test for a running kernel.
89 * Revision 1.12 1995/03/27 12:51:05 adam
90 * New log level in use: GW_LOG_ERRNO.
92 * Revision 1.11 1995/03/27 08:24:02 adam
93 * First use of gip interface and gw-db.
94 * First work on eti program.
96 * Revision 1.10 1995/03/01 14:32:25 adam
97 * Better diagnostics. Default is, that only one database selected when
100 * Revision 1.9 1995/02/23 08:32:17 adam
103 * Revision 1.7 1995/02/22 15:22:33 adam
104 * Much more checking of run-time state. Show command never retrieves
105 * more records than indicated by the previous search request. Help
106 * command available. The maximum number of records retrieved can be
109 * Revision 1.6 1995/02/22 08:51:34 adam
110 * Output function can be customized in fml, which is used to print
111 * the reply to reply_fd.
113 * Revision 1.5 1995/02/20 21:16:20 adam
114 * FML support. Bug fixes. Profile for drewdb.
116 * Revision 1.4 1995/02/17 17:06:16 adam
119 * Revision 1.3 1995/02/16 18:35:09 adam
120 * First use of Zdist library. Search requests are supported.
121 * Present requests are not supported yet.
123 * Revision 1.2 1995/02/16 13:21:00 adam
124 * Organization of resource files for targets and conversion
125 * language implemented.
127 * Revision 1.1 1995/02/15 17:45:29 adam
128 * First version of email gateway kernel. Email requests are read
129 * from stdin. The output is transferred to an MTA if 'From' is
130 * found in the header - or stdout if absent. No Z39.50 client is used.
139 #include <sys/types.h>
140 #include <sys/time.h>
144 #include <strqueue.h>
147 FILE *reply_fd = stdout;
149 struct gw_kernel_info info;
151 static void kernel_events (struct str_queue *queue)
153 char fifo_client_name[1024];
154 char fifo_server_name[1024];
161 int continuation = 0;
165 persist_flag = gw_res_bool (info.kernel_res, "gw.persist", 0);
166 timeout = gw_res_int (info.kernel_res, "gw.timeout", 600);
167 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "event loop");
169 sprintf (fifo_client_name, "fifo.c.%d", info.userid);
170 sprintf (fifo_server_name, "fifo.s.%d", info.userid);
172 gip = gips_initialize (fifo_server_name);
173 gips_open (gip, fifo_client_name);
174 gip_fd = gip_infileno (gip);
175 extra_fd = open (fifo_server_name, O_WRONLY);
180 FD_SET (gip_fd, &set_r);
184 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "IPC select");
185 r = select (gip_fd+1, &set_r, NULL, NULL, &tv);
188 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, KERNEL_LOG, "select");
193 gw_log (GW_LOG_STAT, KERNEL_LOG, "Timeout after %d seconds",
195 if (info.zass && persist_flag)
196 save_p_state (info.userid);
199 if (FD_ISSET (gip_fd, &set_r))
201 char command[128], *cp;
203 if (!(lgets (command, 127, gip_fd)))
205 gw_log (GW_LOG_WARN, KERNEL_LOG, "Unexpected close");
208 if ((cp = strchr (command, '\n')))
210 gw_log (GW_LOG_STAT, KERNEL_LOG, "IPC: %s", command);
211 if (!strcmp (command, "mail"))
213 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Incoming mail");
214 while (lgets (line_buf, sizeof(line_buf)-1, gip_fd))
215 str_queue_enq (queue, line_buf);
216 urp_start (continuation, queue);
217 if (persist_flag && !continuation)
218 load_p_state (info.userid);
219 r = urp_command (queue);
220 if (r == 1) /* stop? */
222 info.zass = NULL; /* delete association */
223 *info.target = 0; /* indicate no target */
224 read_kernel_res(); /* reread resources */
226 del_p_state (info.userid); /* remove persist file */
229 while (str_queue_deq (queue, 0, 0))
232 else if (!strcmp (command, "stop"))
234 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "stop");
239 gw_log (GW_LOG_WARN, KERNEL_LOG, "Unknown IPC: %s", command);
248 unlink (fifo_client_name);
249 unlink (fifo_server_name);
252 int main (int argc, char **argv)
254 struct str_queue *queue;
256 info.kernel_res = NULL;
257 info.default_res = "default.res";
258 info.override_res = NULL;
264 info.override_portno = NULL;
265 info.override_hostname = NULL;
266 info.databases = NULL;
267 info.database = NULL;
276 info.kernel_res = gw_res_init ();
284 fprintf (stderr, "kernel [option..] [resource]\n");
285 fprintf (stderr, "If no resource file is given");
286 fprintf (stderr, " default.res is used\n");
287 fprintf (stderr, "Options:\n");
288 fprintf (stderr, " -d Enable debugging log\n");
289 fprintf (stderr, " -t target Open target immediately\n");
290 fprintf (stderr, " -g lang Set language\n");
291 fprintf (stderr, " -o resource Override with resource\n");
292 fprintf (stderr, " -h host Override host\n");
293 fprintf (stderr, " -p port Override port\n");
294 fprintf (stderr, " -l log Set Log file\n");
295 fprintf (stderr, " -i id Set IPC userid\n");
298 gw_log_level (GW_LOG_ALL & ~RES_DEBUG);
301 gw_log_level (GW_LOG_ALL);
305 strcpy (info.target, argv[0]+2);
309 strcpy (info.target, *++argv);
313 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing target name");
319 info.lang = argv[0]+2;
327 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing language name");
333 info.override_res = argv[0]+2;
337 info.override_res = *++argv;
341 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing override name");
347 info.override_portno = argv[0]+2;
351 info.override_portno = *++argv;
355 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing portno");
361 info.override_hostname = argv[0]+2;
365 info.override_hostname = *++argv;
369 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing hostname");
375 gw_log_file (GW_LOG_ALL, argv[0]+2);
379 gw_log_file (GW_LOG_ALL, *++argv);
383 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing log filename");
389 info.userid = atoi (argv[0]+2);
393 info.userid = atoi (*++argv);
397 gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing user id");
402 gw_log (GW_LOG_FATAL, KERNEL_LOG, "unknown option %s", *argv);
407 info.default_res = *argv;
409 if (!(queue = str_queue_mk ()))
411 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, KERNEL_LOG, "str_queue_mk");
414 if (info.userid != -1)
417 kernel_events (queue);
423 while (lgets (line_buf, sizeof(line_buf)-1, 0))
424 str_queue_enq (queue, line_buf);
425 urp_start (0, queue);
432 struct gw_user_set *user_set_add (const char *name, int hits,
433 const char *database,
434 struct ccl_rpn_node *rpn,
436 const char *search_str)
438 struct gw_user_set *s;
440 s = malloc (sizeof (*s));
443 s->name = gw_strdup (name);
445 s->database = gw_strdup (database);
447 s->present_flag = present_flag;
448 s->search_str = gw_strdup (search_str);
454 void user_set_init (void)
456 struct gw_user_set *s, *s1;
458 for (s = info.sets; s; s = s1)
462 ccl_rpn_delete (s->rpn);
469 struct gw_user_set *user_set_search (const char *name)
471 struct gw_user_set *s;
475 for (s = info.sets; s; s = s->prev)
476 if (!strcmp (s->name, name))
482 static void fml_inf_write (int ch)
486 static FILE *fml_inf;
488 static int fml_inf_read (void)
490 return getc (fml_inf);
494 void read_kernel_res (void)
496 char path_prefix[128];
500 char resource_name[256];
505 ccl_qual_rm (&info.bibset);
506 info.bibset = ccl_qual_mk ();
509 gw_res_close (info.kernel_res);
510 info.kernel_res = gw_res_init ();
512 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, default %s",
515 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, target %s",
518 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, lang %s",
521 /* read default resources. These should exist */
522 if (gw_res_merge (info.kernel_res, info.default_res))
524 gw_log (GW_LOG_WARN, KERNEL_LOG, "Couldn't read resource file %s",
528 strcpy (path_prefix, gw_res_get (info.kernel_res, "gw.path", "."));
530 /* fetch target definitions (if defined at all) */
533 sprintf (resource_name, "gw.target.%s", info.target);
534 v = gw_res_get (info.kernel_res, resource_name, NULL);
537 sprintf (fname, "%s/%s", path_prefix, v);
538 gw_res_merge (info.kernel_res, fname);
541 /* fetch user definitions (if user-id is specified) */
542 if (info.userid >= 0)
544 sprintf (fname, "%s/user.%d.r", path_prefix, info.userid);
545 gw_res_merge (info.kernel_res, fname);
547 /* fetch language definitions (if specified at all) */
548 v = gw_res_get (info.kernel_res, "gw.language", info.lang);
551 sprintf (resource_name, "gw.lang.%s", v);
552 v = gw_res_get (info.kernel_res, resource_name, NULL);
555 sprintf (fname, "%s/%s", path_prefix, v);
556 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Reading language resources %s",
558 gw_res_merge (info.kernel_res, fname);
561 /* fetch overriding resources from file (if specified) */
562 if (info.override_res)
564 sprintf (fname, "%s/%s", path_prefix, info.override_res);
565 gw_res_merge (info.kernel_res, fname);
568 /* read bibset definition for ccl */
569 v = gw_res_get (info.kernel_res, "gw.bibset", NULL);
574 sprintf (fname, "%s/%s", path_prefix, v);
575 bib_inf = fopen (fname, "r");
577 gw_log (GW_LOG_WARN, KERNEL_LOG, "cannot open %s", fname);
580 gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading bib file %s", fname);
581 ccl_qual_file (info.bibset, bib_inf);
586 /* determine host name and port no */
587 sprintf (resource_name, "gw.target.%s", info.target);
588 if (*info.target && ! gw_res_get (info.kernel_res, resource_name, NULL))
590 /* target is specified, and there is no sub-resource for it... */
593 if ((split = strchr (info.target, ':')))
595 memcpy (info.hostname, info.target, split-info.target);
596 info.hostname[split-info.target] = '\0';
597 info.port = atoi (split+1);
601 strcpy (info.hostname, info.target);
602 info.port = gw_res_int (info.kernel_res, "gw.portno", 210);
606 { /* resources gw.hostname and gw.portno will be used */
607 strncpy (info.hostname, gw_res_get (info.kernel_res,
608 "gw.hostname", "localhost"),
609 sizeof(info.hostname)-1);
610 info.port = gw_res_int (info.kernel_res, "gw.portno", 210);
611 strcpy (info.account, gw_res_get (info.kernel_res, "gw.account", ""));
613 /* set info.databases (all available databases for target) */
614 /* set info.database (first database for target) */
616 free (info.databases);
618 free (info.database);
619 v = gw_res_get (info.kernel_res, "gw.databases", "");
620 info.databases = gw_strdup (v);
621 for (cp = info.databases; (cp = strchr (cp, ' ')); cp++)
623 v = gw_res_get (info.kernel_res, "gw.database", "");
624 if (*v == '\0' && *info.databases)
627 cp = strchr (info.databases, ',');
629 len = cp ? (cp-info.databases) : strlen (info.databases);
630 info.database = malloc (len+1);
631 assert (info.database);
632 memcpy (info.database, info.databases, len);
633 info.database[len] = '\0';
637 info.database = gw_strdup (v);
638 for (cp = info.database; (cp = strchr (cp, ' ')); cp++)
642 /* the port no can be explicitly overridden by a command line option */
643 if (info.override_portno)
644 info.port = atoi (info.override_portno);
646 /* the hostname can be explicitly overridden by a command line option */
647 if (info.override_hostname)
648 strncpy (info.hostname, info.override_hostname,
649 sizeof(info.hostname)-1);
651 ccl_token_and = gw_res_get (info.kernel_res, "ccl.token.and", "and");
652 ccl_token_or = gw_res_get (info.kernel_res, "ccl.token.or", "or");
653 ccl_token_not = gw_res_get (info.kernel_res, "ccl.token.not", "not");
654 ccl_token_set = gw_res_get (info.kernel_res, "ccl.token.set", "set");
656 /* determine if more than one result-set names is supported */
657 if (gw_res_bool (info.kernel_res, "gw.result.set", 1))
664 v = gw_res_get (info.kernel_res, "gw.fml", "default.fml");
665 sprintf (fname, "%s/%s", path_prefix, v);
666 fml_inf = fopen (fname, "r");
668 gw_log (GW_LOG_WARN, KERNEL_LOG,
669 "cannot open fml script %s", fname);
672 info.fml = fml_open ();
673 info.fml->read_func = fml_inf_read;
674 info.fml->write_func = fml_inf_write;
675 fml_preprocess (info.fml);