First use of gip interface and gw-db.
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 27 Mar 1995 08:23:57 +0000 (08:23 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 27 Mar 1995 08:23:57 +0000 (08:23 +0000)
First work on eti program.

kernel/Makefile
kernel/default.res
kernel/eti.c [new file with mode: 0644]
kernel/kernel.h
kernel/main.c
kernel/urp.c

index 6d4063d..3d46052 100644 (file)
@@ -2,7 +2,11 @@
 # 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
@@ -46,23 +50,31 @@ ZLIB=$(ZPRE)/libz3950.a
 
 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
 
index fe79d7e..82e4bb4 100644 (file)
@@ -1,5 +1,5 @@
 # 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
@@ -115,46 +115,46 @@ gw.bib1.diag.132: Unsupported proximity unit code
 
 # 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
@@ -165,17 +165,17 @@ gw.help.find: Command:\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
diff --git a/kernel/eti.c b/kernel/eti.c
new file mode 100644 (file)
index 0000000..f901a10
--- /dev/null
@@ -0,0 +1,175 @@
+/* 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);
+}
+
index fa6767c..5aab169 100644 (file)
@@ -2,7 +2,11 @@
  * 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
@@ -46,7 +50,7 @@
 #include <fmlmarc.h>
 #endif
 
-int urp (FILE *inf);
+int urp (int fd);
 
 struct gw_user_set {
     char *name;        /* name of result set */
@@ -86,4 +90,6 @@ void user_set_init (void);
 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"
index 977dfee..1fa110e 100644 (file)
@@ -2,7 +2,11 @@
  * 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;
@@ -164,6 +267,20 @@ int main (int argc, char **argv)
                     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);
@@ -173,7 +290,14 @@ int main (int argc, char **argv)
             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;
 }
 
index 81c4c34..f3d61bc 100644 (file)
@@ -2,7 +2,11 @@
  * 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
@@ -88,6 +92,29 @@ static void put_esc_str (const char *s)
         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;
@@ -215,11 +242,11 @@ static char *error_no_search (struct error_no_struct *tab, int no)
     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;
@@ -240,18 +267,23 @@ static void help_general (void)
 
 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"));
@@ -690,14 +722,14 @@ static int exec_command (const char *str)
     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;
@@ -734,13 +766,17 @@ int urp (FILE *inf)
         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')))