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