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