First work on eti program.
# Europagate, 1995
#
# $Log: Makefile,v $
-# Revision 1.11 1995/03/03 17:19:09 adam
+# Revision 1.12 1995/03/27 08:23:57 adam
+# First use of gip interface and gw-db.
+# First work on eti program.
+#
+# Revision 1.11 1995/03/03 17:19:09 adam
# Smarter presentation. Bug fix in email header interpretation.
#
# Revision 1.10 1995/03/01 14:32:24 adam
INCLUDE=-I../include
CFLAGS=-g -Wall
-TPROG1=kernel
-O=main.o urp.o ttyemit.o
CPP=$(CC) -E
+DEFS=$(INCLUDE) -DUSE_FML=1
USELIBS1=../lib/ccl.a ../lib/fml.a ../lib/libzass.a ../lib/libres+log.a \
../lib/util.a $(ZLIB) $(REGEXOBJ)
-DEFS=$(INCLUDE) -DUSE_FML=1
-all: $(TPROG1)
+PROG1=kernel
+O1=main.o urp.o ttyemit.o
+
+PROG2=eti
+O2=eti.o
+
+all: $(PROG1) $(PROG2)
+
+$(PROG1): $(O1) $(USELIBS1)
+ $(CC) $(CFLAGS) -o $(PROG1) $(O1) $(USELIBS1) $(NETLIB)
-$(TPROG1): $(O) $(USELIBS1)
- $(CC) $(CFLAGS) -o $(TPROG1) $(O) $(USELIBS1) $(NETLIB)
+$(PROG2): $(O2) $(USELIBS1)
+ $(CC) $(CFLAGS) -o $(PROG2) $(O2) $(USELIBS1) $(NETLIB)
.c.o:
$(CC) -c $(DEFS) $(CFLAGS) $<
clean:
- rm -f *.log *.[oa] $(TPROG1) $(TPROG2) core mon.out gmon.out errlist *~
+ rm -f *.log *.[oa] $(PROG1) $(PROG2)
+ rm -f core mon.out gmon.out errlist *~ fifo.*
depend: depend2
# Email gateway - general kernel resources
-# $Id: default.res,v 1.13 1995/03/03 17:19:11 adam Exp $
+# $Id: default.res,v 1.14 1995/03/27 08:23:59 adam Exp $
#
# Important directories, programs, etc.
gw.reply.mta: /usr/lib/sendmail
# Help messages
gw.help.target: Command:\n
- \ttarget host[:port]\n
+ \ttarget <host>[:<port>]\n
\n
The target command selects exactly one target <host>. The <host>
is a normal internet domain hostname. The optional <port> argument
specifies the port number to use. Normally, this does not need to be
specified.
\n
-gw.help.database: Command:\n
- \tbase base1 base2 ...\n
+gw.help.base: Command:\n
+ \tbase <base>1 <base>2 ...\n
\n
The base command selects one or more databases. However, some
targets do not allow the selection of more than one database.
\n
gw.help.find: Command:\n
- \tfind query\n\n
+ \tfind <query>\n\n
The find command issues a search request based on the specified
<query>. A query consists of one or more <search-element>s separated
- by boolean operators <bool-operator>, i.e.:\n\n
+ by boolean operators <bool-operator>, i.e.:\n
\tquery = search-element bool-operator search-element ...\n\n
There are three boolean operators (| means or):\n
\tbool-operator = and | or | not\n\n
A search-element has three forms. The first and simplest is
when it consists of one or more search-terms as in:\n
- \tsearch-element = search-term ...\n\n
+ \t<search-element> = <search-term> ...\n\n
In the second form, qualifiers are specified:\n
- \tsearch-element = qualifier relation search-term ...\n\n
+ \t<search-element> = <qualifier> <relation> <search-term> ...\n\n
A qualifier directs the search to a specified index register. The
relation is:\n
- \trelation = > | < | >= | <= | = | <>\n\n
+ \t<relation> = > | < | >= | <= | = | <>\n\n
The third type of <search-element> is the result-set reference:\n
- \tsearch-element = s = name\n\n
+ \t<search-element> = s=<name>\n\n
Parentheses may be used to create recursive definitions.\n\n
Some examples, may be in order:\n
\tfind network\n
This query consists of one <search-element>, which in turn consists of
- one <search-term>. The query search for the token "network".\n\n
+ one <search-term>. The query searches for the word "network".\n\n
\tfind computer network\n
This is the same as above, but there are two search terms. The
phrase "computer network" is searched.\n\n
- \tfind ti=computer and au=knuth or donald
+ \tfind ti=computer and au=knuth or donald\n
There are three <search-element>s. The first and second <search-element>
use qualifiers; the last one doesn't. The search is equivalent to:\n
\tfind (ti=computer and au=knuth) or donald\n
Note: The result-set reference faclility is unavailable at the moment.
\n
gw.help.show: Command:\n
- \tshow show-spec ...\n\n
+ \tshow <show-spec> ...\n\n
The show command retrieves records. A <show-spec> is a combination
of record position specifications and a presentation format
specification. A show command with no <show-spec> retrieves
10 records and displays them in the full format. A show-spec
of the form:\n
- \tf = type\n
+ \tf = <type>\n
sets the the format to <type>. Currently, there are three formats:
0 - full, 1 - medium, 2 compact format. Record positions can
be specified by the form:\n
- \tp = from - to\n
+ \tp = <from> - <to>\n
Here <from> and <to> are two integers specifying the record
positions.\n
Example:\n
--- /dev/null
+/* Gateway kernel
+ * Europagate, 1995
+ *
+ * $Log: eti.c,v $
+ * Revision 1.1 1995/03/27 08:24:00 adam
+ * First use of gip interface and gw-db.
+ * First work on eti program.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <gw-log.h>
+#include <gw-db.h>
+#include <gip.h>
+
+#define LINE_MAX 1024
+static char line_buf[LINE_MAX+1];
+
+static char *module = "eti";
+
+static int email_header (FILE *inf, char *from_str, char *subject_str)
+{
+ *from_str = '\0';
+ *subject_str = '\0';
+ while (fgets (line_buf, LINE_MAX, inf))
+ {
+ if (line_buf[0] == '\n')
+ return 0;
+ if (strncmp (line_buf, "From ", 5) == 0)
+ sscanf (line_buf+4, "%s", from_str);
+ if (strncmp (line_buf, "Subject: ", 9) == 0 &&
+ sscanf (line_buf+9, "%s", subject_str+1) == 1)
+ strcpy (subject_str, line_buf+9);
+ }
+ return 1;
+}
+
+static int kernel_active (int id)
+{
+ char active_name[1024];
+ int fd;
+
+ sprintf (active_name, "kernel.pid.%d", id);
+ fd = open (active_name, O_RDONLY);
+ if (fd == -1)
+ return 0;
+ close (fd);
+ return 1;
+}
+
+int main (int argc, char **argv)
+{
+ char from_str[LINE_MAX+1];
+ char subject_str[LINE_MAX+1];
+ char line_str[LINE_MAX+1];
+ GW_DB user_db;
+ GIP gip;
+ void *user_info;
+ size_t info_length;
+ int id;
+ int r;
+ char fifo_client_name[1024];
+ char fifo_server_name[1024];
+
+ gw_log_init (*argv);
+ gw_log_level (GW_LOG_ALL);
+ gw_log_file (GW_LOG_ALL, "eti.log");
+ r = email_header (stdin, from_str, subject_str);
+ if (! *from_str)
+ {
+ gw_log (GW_LOG_WARN, module, "No \"From\" in mail");
+ exit (1);
+ }
+ gw_log (GW_LOG_STAT, module, "Mail from %s", from_str);
+ user_db = gw_db_open ("user.db", 1);
+
+ r = gw_db_lookup (user_db, from_str, strlen(from_str),
+ &user_info, &info_length);
+ if (r == 0)
+ {
+ gw_log (GW_LOG_STAT, module, "New user");
+ id = gw_db_seq_no (user_db);
+ r = gw_db_insert (user_db, from_str, strlen(from_str),
+ &id, sizeof(id));
+ gw_log (GW_LOG_STAT, module, "Added user with id %d", id);
+ }
+ else if (r == 1)
+ {
+ if (sizeof(id) != info_length)
+ {
+ gw_log (GW_LOG_FATAL, module, "Bad id-size");
+ exit (1);
+ }
+ memcpy (&id, user_info, sizeof(id));
+ gw_log (GW_LOG_STAT, module, "Found with id %d", id);
+ }
+ else
+ {
+ gw_log (GW_LOG_FATAL, module, "gw_db_lookup fail");
+ }
+ sprintf (fifo_server_name, "fifo.s.%d", id);
+ sprintf (fifo_client_name, "fifo.c.%d", id);
+
+ gip = gipc_initialize (fifo_client_name);
+ if (kernel_active (id))
+ {
+ gw_log (GW_LOG_DEBUG, module, "Kernel already active");
+ gipc_open (gip, fifo_server_name, 0);
+ }
+ else
+ {
+ pid_t pid;
+ int i;
+ char **argv_p;
+ char userid_option[20];
+
+ argv_p = malloc (sizeof(*argv_p)*(argc+2));
+ if (!argv_p)
+ {
+ gw_log (GW_LOG_FATAL, module, "Malloc fail");
+ exit (1);
+ }
+ argv_p[0] = "kernel";
+ for (i = 1; i<argc; i++)
+ argv_p[i] = argv[i];
+ sprintf (userid_option, "-i%d", id);
+ argv_p[i++] = userid_option;
+ argv_p[i++] = NULL;
+
+ gw_log (GW_LOG_DEBUG, module, "Kernel not active");
+ pid = fork ();
+ if (pid == -1)
+ {
+ gw_log (GW_LOG_FATAL, module, "fork");
+ exit (1);
+ }
+ if (!pid)
+ {
+ execvp ("kernel", argv_p);
+ gw_log (GW_LOG_FATAL, module, "execvp");
+ exit (1);
+ }
+ gipc_open (gip, fifo_server_name, 1);
+ }
+ /* deliver message ... */
+ gw_log (GW_LOG_DEBUG, module, "Deliver mail header");
+ gip_wline (gip, "mail\n");
+ gip_wline (gip, "From ");
+ gip_wline (gip, from_str);
+ gip_wline (gip, "\n");
+ if (*subject_str)
+ {
+ gip_wline (gip, "Subject: ");
+ gip_wline (gip, subject_str);
+ gip_wline (gip, "\n");
+ }
+ gip_wline (gip, "\n");
+ gw_log (GW_LOG_DEBUG, module, "Deliver mail body");
+ while (fgets (line_str, LINE_MAX, stdin))
+ gip_wline (gip, line_str);
+ gip_wline (gip, "\001");
+ gw_log (GW_LOG_DEBUG, module, "Closing");
+ gipc_close (gip);
+ gipc_destroy (gip);
+ gw_db_close (user_db);
+ exit (0);
+}
+
* Europagate, 1995
*
* $Log: kernel.h,v $
- * Revision 1.9 1995/03/03 17:19:13 adam
+ * Revision 1.10 1995/03/27 08:24:01 adam
+ * First use of gip interface and gw-db.
+ * First work on eti program.
+ *
+ * Revision 1.9 1995/03/03 17:19:13 adam
* Smarter presentation. Bug fix in email header interpretation.
*
* Revision 1.8 1995/03/01 14:32:24 adam
#include <fmlmarc.h>
#endif
-int urp (FILE *inf);
+int urp (int fd);
struct gw_user_set {
char *name; /* name of result set */
void tty_emit (int ch);
void tty_init (FILE *out, int min, int max);
+int lgets (char *buf, int max, int fd);
+
#define KERNEL_LOG "kernel"
* Europagate, 1995
*
* $Log: main.c,v $
- * Revision 1.10 1995/03/01 14:32:25 adam
+ * 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.
*
#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"
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, "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, KERNEL_LOG, "select fail");
+ 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)
{
+ int userid = -1;
+
info.kernel_res = NULL;
info.default_res = "default.res";
info.override_res = NULL;
exit (1);
}
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, KERNEL_LOG, "unknown option %s", *argv);
exit (1);
info.default_res = *argv;
}
read_kernel_res ();
- urp (stdin);
+ if (userid != -1)
+ {
+ mk_active (userid);
+ kernel_events (userid);
+ rm_active (userid);
+ }
+ else
+ urp (0);
return 0;
}
* Europagate, 1995
*
* $Log: urp.c,v $
- * Revision 1.20 1995/03/03 17:19:17 adam
+ * Revision 1.21 1995/03/27 08:24:04 adam
+ * First use of gip interface and gw-db.
+ * First work on eti program.
+ *
+ * Revision 1.20 1995/03/03 17:19:17 adam
* Smarter presentation. Bug fix in email header interpretation.
*
* Revision 1.19 1995/03/02 09:32:11 adam
tty_emit (*s++);
}
+int lgets (char *buf, int max, int fd)
+{
+ int r, no = 0;
+
+ --max;
+ while (no <= max)
+ {
+ if ((r=read (fd, buf+no, 1)) != 1)
+ {
+ if (r == -1)
+ gw_log (GW_LOG_WARN, KERNEL_LOG, "read fail");
+ buf[no] = '\0';
+ return 0;
+ }
+ if (buf[no] == 1)
+ return 0;
+ if (buf[no++] == '\n')
+ break;
+ }
+ buf[no] = '\0';
+ return 1;
+}
+
static int reopen_target (void)
{
const char *v;
return NULL;
}
-static int email_header (FILE *inf, char *from_str, char *subject_str)
+static int email_header (int fd, char *from_str, char *subject_str)
{
*from_str = '\0';
*subject_str = '\0';
- while (fgets (line_buf, LINE_MAX, inf))
+ while (lgets (line_buf, LINE_MAX, fd))
{
if (line_buf[0] == '\n')
return 0;
static int exec_help (struct ccl_token *list)
{
+ static char *sep = "-------------------------------\\n";
help_general ();
#if 1
+ put_esc_str (sep);
put_esc_str (gw_res_get (info.kernel_res, "gw.help.target",
"target <name> - selects a given target\n"));
+ put_esc_str (sep);
put_esc_str (gw_res_get (info.kernel_res, "gw.help.base",
"base <base>.. - selects databases\n"));
+ put_esc_str (sep);
put_esc_str (gw_res_get (info.kernel_res, "gw.help.find",
"find <query> - performs a search request\n"));
+ put_esc_str (sep);
put_esc_str (gw_res_get (info.kernel_res, "gw.help.show",
"show <spec> - retrieves and displays "
"records\n"));
return 0;
}
-int urp (FILE *inf)
+int urp (int fd)
{
char from_str[128];
char subject_str[128];
int command_no = 0;
char *reply_fname = NULL;
- if (email_header (inf, from_str, subject_str))
+ if (email_header (fd, from_str, subject_str))
{
gw_log (GW_LOG_WARN, KERNEL_LOG, "No message body");
return -1;
gw_log (GW_LOG_WARN, KERNEL_LOG, "No From in email header");
fprintf (reply_fd, "%s\n", gw_res_get (info.kernel_res, "gw.msg.greeting",
"Email->Z39.50 gateway"));
- while (fgets (line_buf, LINE_MAX, inf))
+ while (lgets (line_buf, LINE_MAX, fd))
{
char *cp;
if (line_buf[0] == '\n')
if (command_no)
+ {
+ while (lgets (line_buf, LINE_MAX, fd))
+ ;
break;
+ }
else
continue;
if ((cp = strchr (line_buf, '\n')))