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