|
|
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 (strlen(hl.l_from) >= 17) {
33: fail(linebuf, "From field too long");
34: return(0);
35: }
36: if (!isdate(hl.l_date)) {
37: fail(linebuf, "Date field not legal date");
38: return(0);
39: }
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: 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 (isname(dp, "tty", 3)) {
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: * See if the two passed strings agree in the first n characters.
122: * Return true if they do, gnu.
123: */
124:
125: isname(as1, as2, acount)
126: char *as1, *as2;
127: {
128: register char *s1, *s2;
129: register count;
130:
131: s1 = as1;
132: s2 = as2;
133: count = acount;
134: if (count > 0)
135: do
136: if (*s1++ != *s2++)
137: return(0);
138: while (--count);
139: return(1);
140: }
141:
142: /*
143: * Test to see if the passed string is a ctime(3) generated
144: * date string as documented in the manual. The template
145: * below is used as the criterion of correctness.
146: */
147:
148: #define L 1 /* An alpha 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:
155: 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};
156:
157: isdate(date)
158: char date[];
159: {
160: register char *cp, *tp;
161: register int c;
162:
163: cp = date;
164: tp = ctypes;
165: while (*cp != '\0' && *tp != 0) {
166: c = *cp++;
167: switch (*tp++) {
168: case L:
169: if (!isalpha(c))
170: return(0);
171: break;
172:
173: case S:
174: if (c != ' ')
175: return(0);
176: break;
177:
178: case D:
179: if (!isdigit(c))
180: return(0);
181: break;
182:
183: case O:
184: if (c != ' ' && !isdigit(c))
185: return(0);
186: break;
187:
188: case C:
189: if (c != ':')
190: return(0);
191: break;
192:
193: case N:
194: if (c != '\n')
195: return(0);
196: break;
197: }
198: }
199: if (*cp != '\0' || *tp != 0)
200: return(0);
201: return(1);
202: }
203:
204: /*
205: * Collect a liberal (space, tab delimited) word into the word buffer
206: * passed. Also, return a pointer to the next word following that,
207: * or NOSTR if none follow.
208: */
209:
210: char *
211: nextword(wp, wbuf)
212: char wp[], wbuf[];
213: {
214: register char *cp, *cp2;
215:
216: if ((cp = wp) == NOSTR) {
217: copy("", wbuf);
218: return(NOSTR);
219: }
220: cp2 = wbuf;
221: while (!any(*cp, " \t") && *cp != '\0')
222: *cp2++ = *cp++;
223: *cp2 = '\0';
224: while (any(*cp, " \t"))
225: cp++;
226: if (*cp == '\0')
227: return(NOSTR);
228: return(cp);
229: }
230:
231: /*
232: * Test to see if the character is an ascii alphabetic.
233: */
234:
235: isalpha(c)
236: {
237: register int ch;
238:
239: ch = raise(c);
240: return(ch >= 'A' && ch <= 'Z');
241: }
242:
243: /*
244: * Test to see if the character is an ascii digit.
245: */
246:
247: isdigit(c)
248: {
249: return(c >= '0' && c <= '9');
250: }
251:
252: /*
253: * Copy str1 to str2, return pointer to null in str2.
254: */
255:
256: char *
257: copy(str1, str2)
258: char *str1, *str2;
259: {
260: register char *s1, *s2;
261:
262: s1 = str1;
263: s2 = str2;
264: while (*s1)
265: *s2++ = *s1++;
266: *s2 = 0;
267: return(s2);
268: }
269:
270: /*
271: * Is ch any of the characters in str?
272: */
273:
274: any(ch, str)
275: char *str;
276: {
277: register char *f;
278: register c;
279:
280: f = str;
281: c = ch;
282: while (*f)
283: if (c == *f++)
284: return(1);
285: return(0);
286: }
287:
288: /*
289: * Convert lower case letters to upper case.
290: */
291:
292: raise(c)
293: register int c;
294: {
295: if (c >= 'a' && c <= 'z')
296: c += 'A' - 'a';
297: return(c);
298: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.