Smarter presentation. Bug fix in email header interpretation.
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 3 Mar 1995 17:19:09 +0000 (17:19 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 3 Mar 1995 17:19:09 +0000 (17:19 +0000)
kernel/Makefile
kernel/default.res
kernel/kernel.h
kernel/ttyemit.c [new file with mode: 0644]
kernel/urp.c

index adcfb09..6d4063d 100644 (file)
@@ -2,7 +2,10 @@
 # Europagate, 1995
 #
 # $Log: Makefile,v $
-# Revision 1.10  1995/03/01 14:32:24  adam
+# 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
 # Better diagnostics. Default is, that only one database selected when
 # several are known.
 #
@@ -44,7 +47,7 @@ ZLIB=$(ZPRE)/libz3950.a
 INCLUDE=-I../include
 CFLAGS=-g -Wall 
 TPROG1=kernel
-O=main.o urp.o
+O=main.o urp.o ttyemit.o
 CPP=$(CC) -E
 USELIBS1=../lib/ccl.a ../lib/fml.a ../lib/libzass.a ../lib/libres+log.a \
 ../lib/util.a $(ZLIB) $(REGEXOBJ)
index 74da4fe..fe79d7e 100644 (file)
@@ -1,5 +1,5 @@
 # Email gateway - general kernel resources
-# $Id: default.res,v 1.12 1995/03/01 14:32:24 adam Exp $
+# $Id: default.res,v 1.13 1995/03/03 17:19:11 adam Exp $
 #
 # Important directories, programs, etc.
 gw.reply.mta: /usr/lib/sendmail
@@ -114,33 +114,100 @@ gw.bib1.diag.131: Unsupported proximity relation
 gw.bib1.diag.132: Unsupported proximity unit code
 
 # Help messages
+gw.help.target: Command:\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
+ \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
+ 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
+ \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
+ In the second form, qualifiers are specified:\n
+ \tsearch-element = qualifier relation search-term ...\n\n
+ A qualifier directs the search to a specified index register. The
+ relation is:\n
+ \trelation = > | < | >= | <= | = | <>\n\n
+ The third type of <search-element> is the result-set reference:\n
+ \tsearch-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
+ \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
+ 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
+ If the 'or' is to be applied to "knuth" and "donald", one could use:\n
+ \tfind ti=computer and (au=knuth or donald)\n\n
+ \tfind computer and s=2\n
+ Here, the <search-term> "computer" is and'ed with result-set "2".
+ Note: The result-set reference faclility is unavailable at the moment.
+ \n
+gw.help.show: Command:\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
+ 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
+ Here <from> and <to> are two integers specifying the record
+ positions.\n
+ Example:\n
+ \tshow p=2-7 p=9-10 f=1\n
+ Records 2 through 7 and 9-10 are shown in format 1.\n
 gw.help.general: You 
  have triggered the "help"-information on the Email gateway. \n\n
- This preliminary service is a very early alpha release of a Email service\n
+ This preliminary service is a very early alpha release of a Email service
  which acts as a Z39.50-client (origin). \n\n
- With this service you can connect to several Z39.50-targets. Your Email\n
- body consists of one or more commands. Each command must start on column\n
- zero; otherwise it will be ignored. Also, everything AFTER the first\n
- empty line in your body is ignored. Thus, you probably do not have to\n
+ With this service you can connect to several Z39.50-targets. Your Email
+ body consists of one or more commands. Each command must start on column
+ zero; otherwise it will be ignored. Also, everything AFTER the first
+ empty line in your body is ignored. Thus, you probably do not have to
  delete your signature in the end.\n\n
- All your requests will be logged. Hopefully you will get a reply with\n
- the result of your queries in a minute or two. If you don't something\n
- probably went wrong. Hopefully, we will be able to see what went wrong\n
+ All your requests will be logged. Hopefully you will get a reply with
+ the result of your queries in a minute or two. If you don't something
+ probably went wrong. Hopefully, we will be able to see what went wrong
  by examining the log files.\n\n
- This is what you do:\n\n
- * First you must select a target (i.e. a host with a Z39.50-interface\n
+ This is what you do:\n
+ * First you must select a target (i.e. a host with a Z39.50-interface
  to one or more databases) with the "target" command. For example:\n
  \ttarget dranet.dra.com\n
- * Second, select the databases in which you wish to search, with the\n
+ * Second, select the databases in which you wish to search, with the
  "base" command. For example:\n
  \tbase drewdb\n\n
- * Now you are ready to issue real queries by using the "find"-command.\n
- The query consists of one or more search words. You can perform boolean\n
+ * Now you are ready to issue real queries by using the "find"-command.
+ The query consists of one or more search words. You can perform boolean
  searches by using the operators "and", "or" and "not". For example:\n
  \tfind computer and knuth\n
- If the target supports it, you may also direct the search to special\n
- indexes by using qualfiers. For example, the following query will search\n
+ If the target supports it, you may also direct the search to special
+ indexes by using qualfiers. For example, the following query will search
  for "computer" in the "title"-index and "knuth" in the "normal" index:\n
  \tfind ti=computer and knuth\n\n
- * If the query succeeds, you will be informed with the number of hits.\n
+ * If the query succeeds, you will be informed with the number of hits.
  To display the records use the "show"-command.\n
index beff40b..fa6767c 100644 (file)
@@ -2,7 +2,10 @@
  * Europagate, 1995
  *
  * $Log: kernel.h,v $
- * Revision 1.8  1995/03/01 14:32:24  adam
+ * 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
  * Better diagnostics. Default is, that only one database selected when
  * several are known.
  *
@@ -80,5 +83,7 @@ void read_kernel_res (void);
 struct gw_user_set *user_set_add (const char *name, int hits);
 struct gw_user_set *user_set_search (const char *name);
 void user_set_init (void);
+void tty_emit (int ch);
+void tty_init (FILE *out, int min, int max);
 
 #define KERNEL_LOG "kernel"
diff --git a/kernel/ttyemit.c b/kernel/ttyemit.c
new file mode 100644 (file)
index 0000000..4473db0
--- /dev/null
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "kernel.h"
+static char line_buf[256];
+static int  line_col = 0;
+static int  esc_flag = 0;
+
+static int  line_min = 30;
+static int  line_max = 76;
+static FILE *out_f = stdout;
+
+void tty_init (FILE *out, int min, int max)
+{
+    out_f = out;
+    if (min > 0)
+        line_min = min;
+    if (max > 2)
+        line_max = max;
+    line_col = 0;
+    esc_flag = 0;
+}
+
+static void flush (void)
+{
+    int j;
+
+    for (j = 0; j<line_col; j++)
+        putc (line_buf[j], out_f);
+    putc ('\n', out_f);
+    line_col = 0;
+}
+
+static void split (int ch)
+{
+    int i = line_col, j;
+
+    while (1)
+        if (line_buf[--i] == ' ')
+        {
+            int extra = 0;
+
+            for (j = 0; j<i; j++)
+            {
+#if 1
+                if (j>1 && line_buf[j] >= 'A'&& line_buf[j] <= 'Z'
+                     && line_buf[j-1] == ' '
+                     && (line_buf[j-2] == '.' || line_buf[j-2] == ';')
+                     && extra < line_max-i )
+                {
+                    extra++;
+                    putc (' ', out_f);
+                }
+#endif
+                putc (line_buf[j], out_f);
+            }
+            putc ('\n', out_f);
+            j = 0;
+            ++i;
+            while (i < line_col)
+                line_buf[j++] = line_buf[i++];
+            line_col = j;
+            break;
+        }
+        else if (i < line_min)
+            flush ();
+}
+
+static void escape (int ch)
+{
+    switch (ch)
+    {
+    case 'n':
+       if (line_col >= line_max)
+           split (' ');
+       else
+            flush ();
+        break;
+    case 't':
+        do
+            line_buf[line_col++] = ' ';
+        while (line_col & 7);
+        break;
+    case 's':
+        line_buf[line_col++] = ' ';
+        break;
+    default:
+        line_buf[line_col++] = ch;
+    }
+}
+
+void tty_emit (int ch)
+{
+    if (esc_flag)
+    {
+        escape (ch);
+        esc_flag = 0;
+    }
+    else if (ch == '\\')
+        esc_flag = 1;
+    else if (ch == '\n')
+        flush ();
+    else if (line_col || ch != ' ')
+    {
+        line_buf[line_col++] = ch;
+        if (line_col >= line_max)
+            split (ch);
+    }
+}
index 6816906..81c4c34 100644 (file)
@@ -2,7 +2,10 @@
  * Europagate, 1995
  *
  * $Log: urp.c,v $
- * Revision 1.19  1995/03/02 09:32:11  adam
+ * 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
  * New presentation formats. f0=full, f1=brief, f2=mid
  *
  * Revision 1.18  1995/03/01  14:32:26  adam
 
 static void put_esc_str (const char *s)
 {
-    int escape_flag = 0;
     while (*s)
-    {
-        if (*s == '\\' && s[1])
-        {
-            switch (*++s)
-            {
-            case 'n':
-                fputc ('\n', reply_fd);
-                break;
-            case 't':
-                fputc ('\t', reply_fd);
-                break;
-            default:
-                fputc (*s, reply_fd);
-                break;
-            }
-            escape_flag = 1;
-        }
-        else
-        {
-            if (*s != ' ' || !escape_flag)
-                fputc (*s, reply_fd);
-            escape_flag = 0;
-        }
-        s++;
-    }
+        tty_emit (*s++);
 }
 
 static int reopen_target (void)
@@ -264,7 +242,7 @@ static int exec_help (struct ccl_token *list)
 {
     help_general ();
 
-#if 0
+#if 1
     put_esc_str (gw_res_get (info.kernel_res, "gw.help.target",
                              "target <name> - selects a given target\n"));
 
@@ -277,8 +255,6 @@ static int exec_help (struct ccl_token *list)
     put_esc_str (gw_res_get (info.kernel_res, "gw.help.show",
                              "show <spec>    - retrieves and displays "
                              "records\n"));
-    put_esc_str (gw_res_get (info.kernel_res, "gw.help.help",
-                             "help           - displays help\n"));
 #endif
     return 0;
 }
@@ -726,6 +702,7 @@ int urp (FILE *inf)
         gw_log (GW_LOG_WARN, KERNEL_LOG, "No message body");
         return -1;
     }
+    tty_init (stdout, 40, 70);
     if (*from_str)
     {
         reply_fname = tempnam (gw_res_get (info.kernel_res,
@@ -740,6 +717,7 @@ int urp (FILE *inf)
                     reply_fname);
             return -1;
         }
+        tty_init (reply_fd, 0, 0);
         fprintf (reply_fd, "From: %s\n",
                  gw_res_get (info.kernel_res, "gw.msg.from","Email-gateway"));
         fprintf (reply_fd, "Subject: ");
@@ -761,7 +739,10 @@ int urp (FILE *inf)
         char *cp;
 
         if (line_buf[0] == '\n')
-            break;
+            if (command_no)
+                break;
+            else 
+                continue;
         if ((cp = strchr (line_buf, '\n')))
             *cp = '\0';
         gw_log (GW_LOG_ACCT, KERNEL_LOG, "cmd: %s", line_buf);