2 ** m_getfld2 -- replacement for m_getfld()
3 ** read an RFC 822 message
7 #define _POSIX_C_SOURCE 200809L
24 static enum threestate is_falted(FILE *);
25 static size_t copyname(char *, char *);
26 static boolean is_separator(char *);
30 ** FLD2: We read a (complete) header field
31 ** BODY2: We read a body line
32 ** LENERR2: Line is too long (>998, as defined by RFC 822)
33 ** FMTERR2: Header field invalid
34 ** IOERR2: Failure to read
35 ** FILEEOF2: We're at the end of the file
37 ** f->name is only filled in FLD2.
39 ** In FLD2, f->value contains the field's (complete) value only;
40 ** in BODY2, LENERR2 and FMTERR2 f->value contains the whole line;
41 ** in IOERR2 and FILEEOF2 f->value is not set.
44 m_getfld2(enum state s, struct field *f, FILE *msg)
49 enum threestate falted = B_FALSE;
54 nchars = getline(&tmpline, &len, msg);
57 *f = (struct field) { "\0", 0, NULL, 0, 0 };
65 f->crlf = (nchars > 2 && tmpline[nchars-2] == '\r');
66 if (nchars > NAMESZ+1 || (!f->crlf && nchars > NAMESZ)) {
70 if (*(tmpline + nchars - 1) != '\n') {
74 if (ret == FLD2 && is_separator(tmpline)) {
75 /* header/body separator found */
77 return m_getfld2(BODY2, f, msg);
80 f->namelen = copyname(f->name, tmpline);
87 /* copy the field's value */
88 if (f->alloclen <= nchars - f->namelen) {
89 f->value = mh_xrealloc(f->value, f->alloclen + len);
92 if (f->namelen != 0) {
93 strcpy(f->value, tmpline + f->namelen + 1);
94 f->valuelen = nchars - f->namelen - 1;
96 strcpy(f->value, tmpline);
100 while ((ret == FLD2 || ret == LENERR2) && (falted = is_falted(msg)) == B_TRUE) {
101 nchars = getline(&tmpline, &len, msg);
107 if (nchars > NAMESZ+1 || (!f->crlf && nchars > NAMESZ)) {
111 if (*(tmpline + nchars - 1) != '\n') {
115 if (f->alloclen - f->valuelen <= nchars) {
116 f->value = mh_xrealloc(f->value,
120 strcpy(f->value + f->valuelen, tmpline);
121 f->valuelen += nchars;
125 if (falted == FAIL) {
136 nchars = getline(&tmpline, &len, msg);
149 f->crlf = (nchars > 2 && tmpline[nchars-2] == '\r');
152 f->valuelen = nchars;
157 /* give error states back as received */
162 static enum threestate
168 if ((c = getc(msg)) < 0) {
181 if (ungetc(c, msg) != c) {
188 copyname(char *dst, char *src)
193 if (!(sep = strchr(src, ':'))) {
196 /* whitespace is forbidden in name */
197 for (cp=src; cp<sep; cp++) {
204 if (len >= NAMESZ - 1) {
215 is_separator(char *line)
218 ** In MH, lines that are consists of dashes only are
219 ** separators as well ... not so in RFC 822.
221 while (*line == '-') {
224 if (strcmp("\n", line) == 0 || strcmp("\r\n", line) == 0 ) {