|
|
1.1 root 1: #
2:
3: #include "rcv.h"
4:
5: /*
6: * Mail -- a mail program
7: *
8: * Routines for processing and detecting headlines.
9: */
10:
11: /*
12: * See if the passed line buffer is a mail header.
13: * Return true if yes. Note the extreme pains to
14: * accomodate all funny formats.
15: */
16:
17: ishead(linebuf)
18: char linebuf[];
19: {
20: register char *cp;
21: struct headline hl;
22: char parbuf[BUFSIZ];
23:
24: cp = linebuf;
25: if (!isname("From ", cp, 5))
26: return(0);
27: parse(cp, &hl, parbuf);
28: if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
29: fail(linebuf, "No from or date field");
30: return(0);
31: }
32: if (!isdate(hl.l_date)) {
33: fail(linebuf, "Date field not legal date");
34: return(0);
35: }
36:
37: /*
38: * I guess we got it!
39: */
40:
41: return(1);
42: }
43:
44: fail(linebuf, reason)
45: char linebuf[], reason[];
46: {
47:
48: if (1 /*value("debug") == NOSTR*/)
49: return;
50: fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
51: }
52:
53: /*
54: * Split a headline into its useful components.
55: * Copy the line into dynamic string space, then set
56: * pointers into the copied line in the passed headline
57: * structure. Actually, it scans.
58: */
59:
60: parse(line, hl, pbuf)
61: char line[], pbuf[];
62: struct headline *hl;
63: {
64: register char *cp, *dp;
65: char *sp;
66: char word[LINESIZE];
67:
68: hl->l_from = NOSTR;
69: hl->l_tty = NOSTR;
70: hl->l_date = NOSTR;
71: cp = line;
72: sp = pbuf;
73:
74: /*
75: * Skip the first "word" of the line, which should be "From"
76: * anyway.
77: */
78:
79: cp = nextword(cp, word);
80: dp = nextword(cp, word);
81: if (!equal(word, ""))
82: hl->l_from = copyin(word, &sp);
83: if (isname(dp, "tty", 3)) {
84: cp = nextword(dp, word);
85: hl->l_tty = copyin(word, &sp);
86: if (cp != NOSTR)
87: hl->l_date = copyin(cp, &sp);
88: }
89: else
90: if (dp != NOSTR)
91: hl->l_date = copyin(dp, &sp);
92: }
93:
94: /*
95: * Copy the string on the left into the string on the right
96: * and bump the right (reference) string pointer by the length.
97: * Thus, dynamically allocate space in the right string, copying
98: * the left string into it.
99: */
100:
101: char *
102: copyin(src, space)
103: char src[];
104: char **space;
105: {
106: register char *cp, *top;
107: register int s;
108:
109: s = strlen(src);
110: cp = *space;
111: top = cp;
112: strcpy(cp, src);
113: cp += s + 1;
114: *space = cp;
115: return(top);
116: }
117:
118: /*
119: * See if the two passed strings agree in the first n characters.
120: * Return true if they do, gnu.
121: */
122:
123: isname(as1, as2, acount)
124: char *as1, *as2;
125: {
126: register char *s1, *s2;
127: register count;
128:
129: s1 = as1;
130: s2 = as2;
131: count = acount;
132: if (count > 0)
133: do
134: if (*s1++ != *s2++)
135: return(0);
136: while (--count);
137: return(1);
138: }
139:
140: /*
141: * Test to see if the passed string is a ctime(3) generated
142: * date string as documented in the manual. The template
143: * below is used as the criterion of correctness.
144: * Also, we check for a possible trailing time zone using
145: * the auxtype template.
146: */
147:
148: #define L 1 /* A lower case char */
149: #define S 2 /* A space */
150: #define D 3 /* A digit */
151: #define O 4 /* An optional digit or space */
152: #define C 5 /* A colon */
153: #define N 6 /* A new line */
154: #define U 7 /* An upper case char */
155:
156: char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
157: char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
158:
159: isdate(date)
160: char date[];
161: {
162: register char *cp;
163:
164: cp = date;
165: if (cmatch(cp, ctypes))
166: return(1);
167: return(cmatch(cp, tmztypes));
168: }
169:
170: /*
171: * Match the given string against the given template.
172: * Return 1 if they match, 0 if they don't
173: */
174:
175: cmatch(str, temp)
176: char str[], temp[];
177: {
178: register char *cp, *tp;
179: register int c;
180:
181: cp = str;
182: tp = temp;
183: while (*cp != '\0' && *tp != 0) {
184: c = *cp++;
185: switch (*tp++) {
186: case L:
187: if (c < 'a' || c > 'z')
188: return(0);
189: break;
190:
191: case U:
192: if (c < 'A' || c > 'Z')
193: return(0);
194: break;
195:
196: case S:
197: if (c != ' ')
198: return(0);
199: break;
200:
201: case D:
202: if (!isdigit(c))
203: return(0);
204: break;
205:
206: case O:
207: if (c != ' ' && !isdigit(c))
208: return(0);
209: break;
210:
211: case C:
212: if (c != ':')
213: return(0);
214: break;
215:
216: case N:
217: if (c != '\n')
218: return(0);
219: break;
220: }
221: }
222: if (*cp != '\0' || *tp != 0)
223: return(0);
224: return(1);
225: }
226:
227: /*
228: * Collect a liberal (space, tab delimited) word into the word buffer
229: * passed. Also, return a pointer to the next word following that,
230: * or NOSTR if none follow.
231: */
232:
233: char *
234: nextword(wp, wbuf)
235: char wp[], wbuf[];
236: {
237: register char *cp, *cp2;
238:
239: if ((cp = wp) == NOSTR) {
240: copy("", wbuf);
241: return(NOSTR);
242: }
243: cp2 = wbuf;
244: while (!any(*cp, " \t") && *cp != '\0')
245: *cp2++ = *cp++;
246: *cp2 = '\0';
247: while (any(*cp, " \t"))
248: cp++;
249: if (*cp == '\0')
250: return(NOSTR);
251: return(cp);
252: }
253:
254: /*
255: * Test to see if the character is an ascii alphabetic.
256: */
257:
258: isalpha(c)
259: {
260: register int ch;
261:
262: ch = raise(c);
263: return(ch >= 'A' && ch <= 'Z');
264: }
265:
266: /*
267: * Test to see if the character is an ascii digit.
268: */
269:
270: isdigit(c)
271: {
272: return(c >= '0' && c <= '9');
273: }
274:
275: /*
276: * Copy str1 to str2, return pointer to null in str2.
277: */
278:
279: char *
280: copy(str1, str2)
281: char *str1, *str2;
282: {
283: register char *s1, *s2;
284:
285: s1 = str1;
286: s2 = str2;
287: while (*s1)
288: *s2++ = *s1++;
289: *s2 = 0;
290: return(s2);
291: }
292:
293: /*
294: * Is ch any of the characters in str?
295: */
296:
297: any(ch, str)
298: char *str;
299: {
300: register char *f;
301: register c;
302:
303: f = str;
304: c = ch;
305: while (*f)
306: if (c == *f++)
307: return(1);
308: return(0);
309: }
310:
311: /*
312: * Convert lower case letters to upper case.
313: */
314:
315: raise(c)
316: register int c;
317: {
318: if (c >= 'a' && c <= 'z')
319: c += 'A' - 'a';
320: return(c);
321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.