-
-/*
- * m_getfld.c -- read/parse a message
+/* m_getfld.c -- read/parse a message
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
/*
* static prototypes
*/
-struct m_getfld_state;
static int m_Eom (m_getfld_state_t);
#define eom(c,s) (s->msg_style != MS_DEFAULT && \
((c) == *s->msg_delim && m_Eom(s)))
+/*
+ * Maildrop styles
+ */
+#define MS_DEFAULT 0 /* default (one msg per file) */
+#define MS_UNKNOWN 1 /* type not known yet */
+#define MS_MBOX 2 /* Unix-style "from" lines */
+#define MS_MMDF 3 /* string MMDF_DELIM */
+
/* This replaces the old approach, with its direct access to stdio
* internals. It uses one fread() to load a buffer that we manage.
*
max = *bufsz-1;
/* Back up and store the current position. */
bp = --s->readpos;
- c = s->end - s->readpos < max ? s->end - s->readpos : max;
+ c = min(s->end - s->readpos, max);
if (s->msg_style != MS_DEFAULT && c > 1) {
/*
* packed maildrop - only take up to the (possible)
s = *gstate;
/*
- * Figure out what the message delimitter string is for this
+ * Figure out what the message delimiter string is for this
* maildrop. (This used to be part of m_Eom but I didn't like
* the idea of an "if" statement that could only succeed on the
* first call to m_Eom getting executed on each call, i.e., at
if ((c = Getc (s)) == EOF) {
*cp = '\0';
break;
- } else {
- *cp = c;
}
+ *cp = c;
}
if (i == sizeof from-1 && strncmp (text, "From ", sizeof from-1) == 0) {
/* not a Unix style maildrop */
s->readpos -= s->bytes_read;
s->bytes_read = 0;
- delimstr = mmdlm2;
+ delimstr = MMDF_DELIM;
s->msg_style = MS_MMDF;
}
if (s->edelimlen <= 1)
adios (NULL, "maildrop delimiter must be at least 2 bytes");
- /* Now malloc'd memory at s->fdelim-1 referenced several times:
+ /* Now malloc'd memory at s->fdelim-1 is referenced several times,
+ * containing a copy of the string constant from delimstr.
*
- * delimstr "\nFrom " "\001\001\001\001\n"
- * c 6 5
- * s->fdelim \0"\n\nFrom " \0"\n\001\001\001\001\n"
- * s->fdelimlen 6 5
- * s->msg_delim "\nFrom " "\001\001\001\001\n"
- * s->edelim "From " "\001\001\001\n"
- * s->edelimlen 5 4
- * s->delimend " " "\n"
+ * "\nFrom \0" 7 "\001\001\001\001\n\0" 6
+ * | |
+ * delimstr c=6 delimstr c=5
+ *
+ * "\0\n\nFrom \0" 9 "\0\n\001\001\001\001\n\0" 8
+ * | || | | | | |
+ * | || s->delimend | | | s->delimend
+ * | || | | |
+ * | |s->edelim s->edelimlen=5 | | s->edelim s->edelimlen=4
+ * | | | |
+ * | s->msg_delim | s->msg_delim
+ * | |
+ * s->fdelim s->fdelimlen=7 s->fdelim s->fdelimlen=6
*/
/*
int i;
char text[MAX_DELIMITER_SIZE];
char *cp;
+ int adjust = 1;
for (i = 0, cp = text; i < s->edelimlen; ++i, ++cp) {
int c2;
if ((c2 = Getc (s)) == EOF) {
*cp = '\0';
break;
- } else {
- *cp = c2;
}
+ *cp = c2;
}
if (i != s->edelimlen ||
strncmp (text, (char *)s->edelim, s->edelimlen)) {
- if (i == 0 && s->msg_style == MS_MBOX)
+ if (i == 0 && s->msg_style == MS_MBOX) {
/* the final newline in the (brain damaged) unix-format
- * maildrop is part of the delimitter - delete it.
+ * maildrop is part of the delimiter - delete it.
*/
return 1;
+ }
+
+ if (i <= 2 && s->msg_style == MS_MBOX &&
+ i != s->edelimlen && ! strncmp(text, s->fdelim, i)) {
+ /* If all or part of fdelim appeared at the end of the file,
+ back up even more so that the bytes are included in the
+ message. */
+ adjust = 2;
+ }
/* Did not find delimiter, so restore the read position.
Note that on input, a character had already been read
with Getc(). It will be unget by m_getfld () on return. */
- s->readpos -= s->bytes_read - 1;
- s->bytes_read = 1;
+ s->readpos -= s->bytes_read - adjust;
+ s->bytes_read = adjust;
return 0;
}