* Europagate, 1995
*
* $Log: main.c,v $
- * Revision 1.1 1995/02/15 17:45:29 adam
+ * Revision 1.12 1995/03/27 12:51:05 adam
+ * New log level in use: GW_LOG_ERRNO.
+ *
+ * Revision 1.11 1995/03/27 08:24:02 adam
+ * First use of gip interface and gw-db.
+ * First work on eti program.
+ *
+ * Revision 1.10 1995/03/01 14:32:25 adam
+ * Better diagnostics. Default is, that only one database selected when
+ * several are known.
+ *
+ * Revision 1.9 1995/02/23 08:32:17 adam
+ * Changed header.
+ *
+ * Revision 1.7 1995/02/22 15:22:33 adam
+ * Much more checking of run-time state. Show command never retrieves
+ * more records than indicated by the previous search request. Help
+ * command available. The maximum number of records retrieved can be
+ * controlled now.
+ *
+ * Revision 1.6 1995/02/22 08:51:34 adam
+ * Output function can be customized in fml, which is used to print
+ * the reply to reply_fd.
+ *
+ * Revision 1.5 1995/02/20 21:16:20 adam
+ * FML support. Bug fixes. Profile for drewdb.
+ *
+ * Revision 1.4 1995/02/17 17:06:16 adam
+ * Minor changes.
+ *
+ * Revision 1.3 1995/02/16 18:35:09 adam
+ * First use of Zdist library. Search requests are supported.
+ * Present requests are not supported yet.
+ *
+ * Revision 1.2 1995/02/16 13:21:00 adam
+ * Organization of resource files for targets and conversion
+ * language implemented.
+ *
+ * Revision 1.1 1995/02/15 17:45:29 adam
* First version of email gateway kernel. Email requests are read
* from stdin. The output is transferred to an MTA if 'From' is
* found in the header - or stdout if absent. No Z39.50 client is used.
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <gip.h>
#include "kernel.h"
-GwRes kernel_res;
-CCL_bibset bibset;
FILE *reply_fd = stdout;
+struct gw_kernel_info info;
+
+static void mk_active (int userid)
+{
+ char active_name[1024];
+ char pid_buf[30];
+ int fd;
+
+ sprintf (active_name, "kernel.pid.%d", userid);
+ fd = open (active_name, O_WRONLY|O_CREAT, 0666);
+ if (fd == -1)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, "Cannot create %s", active_name);
+ exit (1);
+ }
+ sprintf (pid_buf, "%ld", (long) getpid());
+ write (fd, pid_buf, strlen(pid_buf));
+ close (fd);
+}
+
+static void rm_active (int userid)
+{
+ char active_name[1024];
+
+ sprintf (active_name, "kernel.pid.%d", userid);
+ unlink (active_name);
+}
+
+static void kernel_events (int userid)
+{
+ char fifo_client_name[1024];
+ char fifo_server_name[1024];
+ GIP gip;
+ fd_set set_r;
+ int r, gip_fd;
+ struct timeval tv;
+
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "kernel event loop");
+
+ sprintf (fifo_client_name, "fifo.c.%d", userid);
+ sprintf (fifo_server_name, "fifo.s.%d", userid);
+
+ gip = gips_initialize (fifo_server_name);
+ gips_open (gip, fifo_client_name);
+ gip_fd = gip_infileno (gip);
+
+ while (1)
+ {
+ FD_ZERO (&set_r);
+ FD_SET (gip_fd, &set_r);
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "IPC select");
+ r = select (gip_fd+1, &set_r, NULL, NULL, &tv);
+ if (r == -1)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, KERNEL_LOG, "select");
+ exit (1);
+ }
+ if (r == 0)
+ {
+ gw_log (GW_LOG_STAT, KERNEL_LOG, "Timeout");
+ break;
+ }
+ if (FD_ISSET (gip_fd, &set_r))
+ {
+ char command[128], *cp;
+
+ if (!(lgets (command, 127, gip_fd)))
+ break;
+ if ((cp = strchr (command, '\n')))
+ *cp = '\0';
+ gw_log (GW_LOG_STAT, KERNEL_LOG, "IPC: %s", command);
+ if (!strcmp (command, "mail"))
+ {
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Incoming mail...\n");
+ urp (gip_fd);
+ }
+ else if (!strcmp (command, "stop"))
+ {
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "stop");
+ break;
+ }
+ else
+ {
+ gw_log (GW_LOG_WARN, KERNEL_LOG, "Unknown IPC: %s", command);
+ }
+ }
+ }
+ gips_close (gip);
+ gips_destroy (gip);
+}
+
int main (int argc, char **argv)
{
- char *bib_fname;
- FILE *bib_inf;
+ int userid = -1;
+
+ info.kernel_res = NULL;
+ info.default_res = "default.res";
+ info.override_res = NULL;
+ *info.target = 0;
+ info.lang = NULL;
+ info.bibset = NULL;
+ info.zass = NULL;
+ info.override_portno = NULL;
+ info.override_hostname = NULL;
+ info.databases = NULL;
+ info.database = NULL;
+#if USE_FML
+ info.fml = NULL;
+#endif
+ info.sets = NULL;
gw_log_init (*argv);
- kernel_res = gw_res_init ();
- bibset = ccl_qual_mk ();
+ info.kernel_res = gw_res_init ();
while (--argc > 0)
{
if (**++argv == '-')
{
switch (argv[0][1])
{
- case 'b':
+ case 'H':
+ fprintf (stderr, "kernel [option..] [resource]\n");
+ fprintf (stderr, "If no resource file is given");
+ fprintf (stderr, " default.res is used\n");
+ fprintf (stderr, "Options:\n");
+ fprintf (stderr, " -d Enable debugging log\n");
+ fprintf (stderr, " -t target Open target immediately\n");
+ fprintf (stderr, " -l lang Set language\n");
+ fprintf (stderr, " -o resource Override with resource\n");
+ fprintf (stderr, " -h host Override host\n");
+ fprintf (stderr, " -p port Override port\n");
+ fprintf (stderr, " -g log Set Log file\n");
+ fprintf (stderr, " -i id Set IPC userid\n");
+ exit (1);
+ case 'd':
+ gw_log_level (GW_LOG_ALL);
+ break;
+ case 't':
+ if (argv[0][2])
+ strcpy (info.target, argv[0]+2);
+ else if (argc > 0)
+ {
+ --argc;
+ strcpy (info.target, *++argv);
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing target name");
+ exit (1);
+ }
+ break;
+ case 'l':
+ if (argv[0][2])
+ info.lang = argv[0]+2;
+ else if (argc > 0)
+ {
+ --argc;
+ info.lang = *++argv;
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing language name");
+ exit (1);
+ }
+ break;
+ case 'o':
if (argv[0][2])
- bib_fname = argv[0]+2;
+ info.override_res = argv[0]+2;
else if (argc > 0)
{
--argc;
- bib_fname = *++argv;
+ info.override_res = *++argv;
}
else
{
- gw_log (GW_LOG_FATAL, "main", "missing bib filename");
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing override name");
exit (1);
}
- bib_inf = fopen (bib_fname, "r");
- if (!bib_inf)
+ break;
+ case 'p':
+ if (argv[0][2])
+ info.override_portno = argv[0]+2;
+ else if (argc > 0)
+ {
+ --argc;
+ info.override_portno = *++argv;
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing portno");
+ exit (1);
+ }
+ break;
+ case 'h':
+ if (argv[0][2])
+ info.override_hostname = argv[0]+2;
+ else if (argc > 0)
+ {
+ --argc;
+ info.override_hostname = *++argv;
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing hostname");
+ exit (1);
+ }
+ break;
+ case 'g':
+ if (argv[0][2])
+ gw_log_file (GW_LOG_ALL, argv[0]+2);
+ else if (argc > 0)
+ {
+ --argc;
+ gw_log_file (GW_LOG_ALL, *++argv);
+ }
+ else
{
- gw_log (GW_LOG_FATAL, "main", "cannot open %s", bib_fname);
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing log filename");
exit (1);
}
- ccl_qual_file (bibset, bib_inf);
- fclose (bib_inf);
break;
+ case 'i':
+ if (argv[0][2])
+ userid = atoi (argv[0]+2);
+ else if (argc > 0)
+ {
+ --argc;
+ userid = atoi (*++argv);
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing user id");
+ exit (1);
+ }
+ break;
default:
- gw_log (GW_LOG_FATAL, "main", "unknown option %s", *argv);
+ gw_log (GW_LOG_FATAL, KERNEL_LOG, "unknown option %s", *argv);
exit (1);
}
}
else
+ info.default_res = *argv;
+ }
+ read_kernel_res ();
+ if (userid != -1)
+ {
+ mk_active (userid);
+ kernel_events (userid);
+ rm_active (userid);
+ }
+ else
+ urp (0);
+ return 0;
+}
+
+struct gw_user_set *user_set_add (const char *name, int hits)
+{
+ struct gw_user_set *s;
+
+ s = malloc (sizeof (*s));
+ assert (s);
+
+ s->name = gw_strdup (name);
+ s->hits = hits;
+ s->prev = info.sets;
+ info.sets = s;
+ return s;
+}
+
+void user_set_init (void)
+{
+ struct gw_user_set *s, *s1;
+
+ for (s = info.sets; s; s = s1)
+ {
+ free (s->name);
+ s1 = s->prev;
+ free (s);
+ }
+ info.sets = NULL;
+}
+
+struct gw_user_set *user_set_search (const char *name)
+{
+ struct gw_user_set *s;
+
+ if (!name)
+ return info.sets;
+ for (s = info.sets; s; s = s->prev)
+ if (!strcmp (s->name, name))
+ return s;
+ return NULL;
+}
+
+#if USE_FML
+static void fml_inf_write (int ch)
+{
+ putc (ch, reply_fd);
+}
+static FILE *fml_inf;
+
+static int fml_inf_read (void)
+{
+ return getc (fml_inf);
+}
+#endif
+
+void read_kernel_res (void)
+{
+ char path_prefix[128];
+ char fname[160];
+ const char *v;
+ char *cp;
+ char resource_name[256];
+
+ user_set_init ();
+
+ if (info.bibset)
+ ccl_qual_rm (&info.bibset);
+ info.bibset = ccl_qual_mk ();
+
+ if (info.kernel_res)
+ gw_res_close (info.kernel_res);
+ info.kernel_res = gw_res_init ();
+
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, default %s",
+ info.default_res);
+ if (*info.target)
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, target %s",
+ info.target);
+ if (info.lang)
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading kernel resource, lang %s",
+ info.lang);
+
+ if (gw_res_merge (info.kernel_res, info.default_res))
+ {
+ gw_log (GW_LOG_WARN, KERNEL_LOG, "Couldn't read resource file %s",
+ info.default_res);
+ return;
+ }
+ strcpy (path_prefix, gw_res_get (info.kernel_res, "gw.path", "."));
+
+ if (*info.target)
+ {
+ sprintf (resource_name, "gw.target.%s", info.target);
+ v = gw_res_get (info.kernel_res, resource_name, NULL);
+ if (v)
+ {
+ sprintf (fname, "%s/%s", path_prefix, v);
+ gw_res_merge (info.kernel_res, fname);
+ }
+ }
+ if (info.lang)
+ {
+ sprintf (resource_name, "gw.lang.%s", info.lang);
+ v = gw_res_get (info.kernel_res, resource_name, NULL);
+ if (v)
+ {
+ sprintf (fname, "%s/%s", path_prefix, v);
+ gw_res_merge (info.kernel_res, fname);
+ }
+ }
+ if (info.override_res)
+ {
+ sprintf (fname, "%s/%s", path_prefix, info.override_res);
+ gw_res_merge (info.kernel_res, fname);
+ }
+ v = gw_res_get (info.kernel_res, "gw.bibset", NULL);
+ if (v)
+ {
+ FILE *bib_inf;
+
+ sprintf (fname, "%s/%s", path_prefix, v);
+ bib_inf = fopen (fname, "r");
+ if (!bib_inf)
+ gw_log (GW_LOG_WARN, KERNEL_LOG, "cannot open %s", fname);
+ else
{
- int r;
- r = gw_res_merge (kernel_res, *argv);
- if (r)
- {
- gw_log (GW_LOG_FATAL, "main", "failed to read resource "
- "file %s", *argv);
- exit (1);
- }
+ gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reading bib file %s", fname);
+ ccl_qual_file (info.bibset, bib_inf);
+ fclose (bib_inf);
}
}
- urp (stdin);
- return 0;
+ sprintf (resource_name, "gw.target.%s", info.target);
+ if (*info.target && ! gw_res_get (info.kernel_res, resource_name, NULL))
+ {
+ /* target is there, and there is no sub-resource for it... */
+ char *split;
+
+ if ((split = strchr (info.target, ':')))
+ *split++ = '\0';
+ strncpy (info.hostname, info.target, sizeof(info.hostname)-1);
+ if (split)
+ info.port = atoi (split);
+ else
+ info.port = atoi (gw_res_get
+ (info.kernel_res, "gw.portno", "210"));
+ }
+ else
+ {
+ strncpy (info.hostname, gw_res_get (info.kernel_res,
+ "gw.hostname", "localhost"),
+ sizeof(info.hostname)-1);
+ info.port = atoi (gw_res_get (info.kernel_res,
+ "gw.portno", "210"));
+ }
+ if (info.databases)
+ free (info.databases);
+ if (info.database)
+ free (info.database);
+ v = gw_res_get (info.kernel_res, "gw.databases", "");
+ info.databases = gw_strdup (v);
+ for (cp = info.databases; (cp = strchr (cp, ' ')); cp++)
+ *cp = ',';
+ v = gw_res_get (info.kernel_res, "gw.database", "");
+ if (*v == '\0' && *info.databases)
+ {
+ int len;
+ cp = strchr (info.databases, ',');
+
+ len = cp ? (cp-info.databases) : strlen (info.databases);
+ info.database = malloc (len+1);
+ assert (info.database);
+ memcpy (info.database, info.databases, len);
+ info.database[len] = '\0';
+ }
+ else
+ {
+ info.database = gw_strdup (v);
+ for (cp = info.database; (cp = strchr (cp, ' ')); cp++)
+ *cp = ',';
+ }
+ if (info.override_portno)
+ info.port = atoi (info.override_portno);
+ if (info.override_hostname)
+ strncpy (info.hostname, info.override_hostname,
+ sizeof(info.hostname)-1);
+#if USE_FML
+ if (!info.fml)
+ {
+ v = gw_res_get (info.kernel_res, "gw.fml", "default.fml");
+ sprintf (fname, "%s/%s", path_prefix, v);
+ fml_inf = fopen (fname, "r");
+ if (!fml_inf)
+ gw_log (GW_LOG_WARN, KERNEL_LOG,
+ "cannot open fml script %s", fname);
+ else
+ {
+ info.fml = fml_open ();
+ info.fml->read_func = fml_inf_read;
+ info.fml->write_func = fml_inf_write;
+ fml_preprocess (info.fml);
+ fml_exec (info.fml);
+ fclose (fml_inf);
+ }
+ }
+#endif
}