/* Copyright (c) 1979 Regents of the University of California */ # #include "def.h" /* * Mail -- a mail program * * Routines for processing and detecting headlines. */ /* * See if the passed line buffer is a mail header. * Return true if yes. Note the extreme pains to * accomodate all funny formats. */ ishead(linebuf) char linebuf[]; { register char *cp; struct headline hl; cp = linebuf; if (!isname("From ", cp, 5)) return(0); parse(cp, &hl); if (hl.l_from == NOSTR || hl.l_date == NOSTR) return(0); if (strlen(hl.l_from) >= 17) return(0); if (!isdate(hl.l_date)) return(0); /* * I guess we got it! */ return(1); } /* * Split a headline into its useful components. * Copy the line into dynamic string space, then set * pointers into the copied line in the passed headline * structure. Actually, it scans. */ parse(line, hl) char line[]; struct headline *hl; { register char *cp, *dp; char word[LINESIZE]; hl->l_from = NOSTR; hl->l_tty = NOSTR; hl->l_date = NOSTR; cp = line; /* * Skip the first "word" of the line, which should be "From" * anyway. */ cp = nextword(cp, word); dp = nextword(cp, word); if (!equal(word, "")) hl->l_from = savestr(word); if (isname(dp, "tty", 3)) { cp = nextword(dp, word); hl->l_tty = savestr(word); if (cp != NOSTR) hl->l_date = savestr(cp); } else if (dp != NOSTR) hl->l_date = savestr(dp); } /* * See if the two passed strings agree in the first n characters. * Return true if they do, gnu. */ isname(as1, as2, acount) char *as1, *as2; { register char *s1, *s2; register count; s1 = as1; s2 = as2; count = acount; if (count > 0) do if (*s1++ != *s2++) return(0); while (--count); return(1); } /* * Test to see if the passed string is a ctime(3) generated * date string as documented in the manual. The template * below is used as the criterion of correctness. */ #define L 1 /* An alpha char */ #define S 2 /* A space */ #define D 3 /* A digit */ #define O 4 /* An optional digit or space */ #define C 5 /* A colon */ #define N 6 /* A new line */ char ctypes[] = {L,L,L,S,L,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0}; isdate(date) char date[]; { register char *cp, *tp; register int c; cp = date; tp = ctypes; while (*cp != '\0' && *tp != 0) { c = *cp++; switch (*tp++) { case L: if (!isalpha(c)) return(0); break; case S: if (c != ' ') return(0); break; case D: if (!isdigit(c)) return(0); break; case O: if (c != ' ' && !isdigit(c)) return(0); break; case C: if (c != ':') return(0); break; case N: if (c != '\n') return(0); break; } } if (*cp != '\0' || *tp != 0) return(0); return(1); } /* * Collect a liberal (space, tab delimited) word into the word buffer * passed. Also, return a pointer to the next word following that, * or NOSTR if none follow. */ char * nextword(wp, wbuf) char wp[], wbuf[]; { register char *cp, *cp2; if ((cp = wp) == NOSTR) { copy("", wbuf); return(NOSTR); } cp2 = wbuf; while (!any(*cp, " \t") && *cp != '\0') *cp2++ = *cp++; *cp2 = '\0'; while (any(*cp, " \t")) cp++; if (*cp == '\0') return(NOSTR); return(cp); } /* * Test to see if the character is an ascii alphabetic. */ isalpha(c) { register int ch; ch = raise(c); return(ch >= 'A' && ch <= 'Z'); } /* * Test to see if the character is an ascii digit. */ isdigit(c) { return(c >= '0' && c <= '9'); } /* * Copy str1 to str2, return pointer to null in str2. */ char * copy(str1, str2) char *str1, *str2; { register char *s1, *s2; s1 = str1; s2 = str2; while (*s1) *s2++ = *s1++; *s2 = 0; return(s2); } /* * Is ch any of the characters in str? */ any(ch, str) char *str; { register char *f; register c; f = str; c = ch; while (*f) if (c == *f++) return(1); return(0); } /* * Convert lower case letters to upper case. */ raise(c) register int c; { if (c >= 'a' && c <= 'z') c += 'A' - 'a'; return(c); }