Added m_getfld () interface description.
[mmh] / sbr / m_getfld.c
index ecbbd3c..fe88dc7 100644 (file)
@@ -2,8 +2,6 @@
 /*
  * m_getfld.c -- read/parse a message
  *
- * $Id$
- *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  * complete copyright information.
    there is data in "name" or "buf").
   */
 
+/*
+Purpose
+=======
+Reads an Internet message (RFC 5322), or one or more messages stored in a
+maildrop in mbox (RFC 4155) or MMDF format, from a file stream.  Each call
+to m_getfld() reads one header field, or a portion of the body, in sequence.
+
+Inputs
+======
+state:  message parse state
+bufsz:  maximum number of characters to load into buf
+iob:  input file stream
+
+Outputs
+=======
+name:  header field name (array of size NAMESZ=999)
+buf:  either a header field body or message body
+(return value):  message parse state on return from function
+(global) int msg_count:  number of characters loaded into buf
+
+Functions (part of Inputs, really)
+=========
+void m_unknown(FILE *iob):  Determines the message delimiter string for the
+  maildrop.  Called by inc, scan, and msh when reading from a maildrop file.
+
+void m_eomsbr (int (*action)(int)):  Sets the hook to check for end of
+  message in a maildrop.  Called only by msh.
+
+Those functions save state in the State variables listed below.
+
+Definitions
+===========
+state is one of:
+  FLD      // Field returned
+  FLDPLUS  // Field returned with more to come
+  FLDEOF   // Field returned ending at eom
+  BODY     // Body  returned with more to come
+  BODYEOF  // Body  returned ending at eom
+  FILEEOF  // Reached end of input file
+  FMTERR   // Message Format error
+  LENERR   // Name too long error from getfld
+
+msg_style is maildrop style, one of:
+  MS_UNKNOWN // type not known yet
+  MS_DEFAULT // default (one msg per file)
+  MS_MBOX    // Unix-style "from" lines
+  MS_MMDF    // string mmdlm2
+  MS_MSH     // whacko msh
+
+State variables (part of Outputs)
+===============
+m_getfld() retains state internally between calls in some state variables.
+
+These two variables are global, but only used internally by m_getfld.c:
+int msg_style
+char *msg_delim
+
+These are used for the end-of-message matcher when reading maildrops:
+static unsigned char **pat_map
+static unsigned char *fdelim
+static unsigned char *delimend
+static int fdelimlen
+static unsigned char *edelim
+static int edelimlen
+
+Restriction
+===========
+m_getfld() is restricted to operate on one file stream at a time because of
+the retained state (see "State variables" above).
+
+Current usage
+=============
+The first call to m_getfld() on a file stream is with a state of FLD.
+Subsequent calls provide the state returned by the previous call.
+
+Along the way, I thought of these possible interface changes that we
+might want to consider before rototilling the internals:
+
+1) To improve interface documentation:
+   Change type of name argument from unsigned char * to unsigned char[NAMESZ].
+   This would also be a step toward allowing the compiler to check for array
+   size consistency.
+
+2) To remove globals that don't need to be:
+   Change msg_style and msg_delim to be file static.
+
+3) To remove a global:
+   Change bufsz to be in-out instead of in, and therefore int * instead of
+   int, and use that instead of global msg_count.  There are only 3 call
+   sites that use msg_count so it wouldn't take much effort to remove use of
+   it.  Of course, all call sites would have to change to provide an int *
+   instead of an int.  Some now pass constants.
+
+4) To remove the state argument from the signature:
+   Given the Current usage and Restriction above, the state variable could
+   be removed from the signature and just retained internally.
+
+5) To remove the Restriction above:
+   One approach would be for m_getfld() to retain multiple copies of that
+   state, one per iob that it sees.  Another approach would be for the
+   caller to store it in an opaque struct, the address of which is passed
+   through the interface.
+*/
 
 /*
  * static prototypes
@@ -190,14 +291,11 @@ static int (*eom_action)(int) = NULL;
 # define _cnt    _r            /* Retch */
 # define _filbuf __srget       /* Puke  */
 # define DEFINED__FILBUF_TO_SOMETHING_SPECIFIC
-#endif
 
-#ifdef SCO_5_STDIO
-# define _ptr  __ptr
-# define _cnt  __cnt
-# define _base __base
-# define _filbuf(fp)  ((fp)->__cnt = 0, __filbuf(fp))
-# define DEFINED__FILBUF_TO_SOMETHING_SPECIFIC
+# if defined __CYGWIN__
+  /* Cygwin's stdio.h does not declare __srget(). */
+  int __srget(FILE *);
+# endif /* __CYGWIN__ */
 #endif
 
 #ifndef DEFINED__FILBUF_TO_SOMETHING_SPECIFIC
@@ -584,10 +682,6 @@ finish:
 }
 
 
-#ifdef RPATHS
-static char unixbuf[BUFSIZ] = "";
-#endif /* RPATHS */
-
 void
 m_unknown(FILE *iob)
 {
@@ -617,15 +711,8 @@ m_unknown(FILE *iob)
            && strncmp (text, "From ", 5) == 0) {
        msg_style = MS_MBOX;
        delimstr = "\nFrom ";
-#ifndef        RPATHS
        while ((c = getc (iob)) != '\n' && c >= 0)
            ;
-#else /* RPATHS */
-       cp = unixbuf;
-       while ((c = getc (iob)) != '\n' && cp - unixbuf < BUFSIZ - 1)
-           *cp++ = c;
-       *cp = 0;
-#endif /* RPATHS */
     } else {
        /* not a Unix style maildrop */
        fseek (iob, pos, SEEK_SET);
@@ -694,9 +781,6 @@ m_Eom (int c, FILE *iob)
     register long pos = 0L;
     register int i;
     char text[10];
-#ifdef RPATHS
-    register char *cp;
-#endif /* RPATHS */
 
     pos = ftell (iob);
     if ((i = fread (text, sizeof *text, edelimlen, iob)) != edelimlen
@@ -717,83 +801,15 @@ m_Eom (int c, FILE *iob)
     }
 
     if (msg_style == MS_MBOX) {
-#ifndef RPATHS
        while ((c = getc (iob)) != '\n')
            if (c < 0)
                break;
-#else /* RPATHS */
-       cp = unixbuf;
-       while ((c = getc (iob)) != '\n' && c >= 0 && cp - unixbuf < BUFSIZ - 1)
-           *cp++ = c;
-       *cp = 0;
-#endif /* RPATHS */
     }
 
     return 1;
 }
 
 
-#ifdef RPATHS
-/*
- * Return the Return-Path and Delivery-Date
- * header information.
- *
- * Currently, I'm assuming that the "From " line
- * takes one of the following forms.
- *
- * From sender date remote from host   (for UUCP delivery)
- * From sender@host  date              (for sendmail delivery)
- */
-
-int
-get_returnpath (char *rp, int rplen, char *dd, int ddlen)
-{
-    char *ap, *bp, *cp, *dp;
-
-    ap = unixbuf;
-    if (!(bp = cp = strchr(ap, ' ')))
-       return 0;
-
-    /*
-     * Check for "remote from" in envelope to see
-     * if this message uses UUCP style addressing
-     */
-    while ((cp = strchr(++cp, 'r'))) {
-       if (strncmp (cp, "remote from", 11) == 0) {
-           cp = strrchr (cp, ' ');
-           break;
-       }
-    }
-
-    /*
-     * Get the Return-Path information from
-     * the "From " envelope.
-     */
-    if (cp) {
-       /* return path for UUCP style addressing */
-       dp = strchr (++cp, '\n');
-       snprintf (rp, rplen, "%.*s!%.*s\n", (int)(dp - cp), cp, (int)(bp - ap), ap);
-    } else {
-       /* return path for standard domain addressing */
-       snprintf (rp, rplen, "%.*s\n", (int)(bp - ap), ap);
-    }
-
-    /*
-     * advance over the spaces to get to
-     * delivery date on envelope
-     */
-    while (*bp == ' ')
-       bp++;
-
-    /* Now get delivery date from envelope */
-    snprintf (dd, ddlen, "%.*s\n", 24, bp);
-
-    unixbuf[0] = 0;
-    return 1;
-}
-#endif /* RPATHS */
-
-
 static unsigned char *
 matchc(int patln, char *pat, int strln, char *str)
 {