|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #ifdef notdef
14: static char sccsid[] = "@(#)head.c 5.4 (Berkeley) 2/18/88";
15: #endif /* notdef */
16:
17: #include "rcv.h"
18:
19: /*
20: * Mail -- a mail program
21: *
22: * Routines for processing and detecting headlines.
23: */
24:
25: /*
26: * See if the passed line buffer is a mail header.
27: * Return true if yes. Note the extreme pains to
28: * accomodate all funny formats.
29: */
30: ishead(linebuf)
31: char linebuf[];
32: {
33: register char *cp;
34: struct headline hl;
35: char parbuf[BUFSIZ];
36:
37: cp = linebuf;
38: if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
39: *cp++ != ' ')
40: return (0);
41: parse(linebuf, &hl, parbuf);
42: if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
43: fail(linebuf, "No from or date field");
44: return (0);
45: }
46: if (!isdate(hl.l_date)) {
47: fail(linebuf, "Date field not legal date");
48: return (0);
49: }
50: /*
51: * I guess we got it!
52: */
53: return (1);
54: }
55:
56: /*ARGSUSED*/
57: fail(linebuf, reason)
58: char linebuf[], reason[];
59: {
60:
61: /*
62: if (value("debug") == NOSTR)
63: return;
64: fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
65: */
66: }
67:
68: /*
69: * Split a headline into its useful components.
70: * Copy the line into dynamic string space, then set
71: * pointers into the copied line in the passed headline
72: * structure. Actually, it scans.
73: */
74: parse(line, hl, pbuf)
75: char line[], pbuf[];
76: register struct headline *hl;
77: {
78: register char *cp;
79: char *sp;
80: char word[LINESIZE];
81:
82: hl->l_from = NOSTR;
83: hl->l_tty = NOSTR;
84: hl->l_date = NOSTR;
85: cp = line;
86: sp = pbuf;
87: /*
88: * Skip over "From" first.
89: */
90: cp = nextword(cp, word);
91: cp = nextword(cp, word);
92: if (*word)
93: hl->l_from = copyin(word, &sp);
94: if (cp != NOSTR && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
95: cp = nextword(cp, word);
96: hl->l_tty = copyin(word, &sp);
97: }
98: if (cp != NOSTR)
99: hl->l_date = copyin(cp, &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: char *
109: copyin(src, space)
110: register char *src;
111: char **space;
112: {
113: register char *cp;
114: char *top;
115:
116: top = cp = *space;
117: while (*cp++ = *src++)
118: ;
119: *space = cp;
120: return (top);
121: }
122:
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[] = { 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 };
140: 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 };
141:
142: isdate(date)
143: char date[];
144: {
145:
146: if (cmatch(date, ctypes))
147: return (1);
148: return (cmatch(date, tmztypes));
149: }
150:
151: /*
152: * Match the given string (cp) against the given template (tp).
153: * Return 1 if they match, 0 if they don't
154: */
155:
156: cmatch(cp, tp)
157: register char *cp, *tp;
158: {
159:
160: while (*cp && *tp)
161: switch (*tp++) {
162: case L:
163: if (!islower(*cp++))
164: return 0;
165: break;
166: case U:
167: if (!isupper(*cp++))
168: return 0;
169: break;
170: case S:
171: if (*cp++ != ' ')
172: return 0;
173: break;
174: case D:
175: if (!isdigit(*cp++))
176: return 0;
177: break;
178: case O:
179: if (*cp != ' ' && !isdigit(*cp))
180: return 0;
181: cp++;
182: break;
183: case C:
184: if (*cp++ != ':')
185: return 0;
186: break;
187: case N:
188: if (*cp++ != '\n')
189: return 0;
190: break;
191: }
192: if (*cp || *tp)
193: return 0;
194: return (1);
195: }
196:
197: /*
198: * Collect a liberal (space, tab delimited) word into the word buffer
199: * passed. Also, return a pointer to the next word following that,
200: * or NOSTR if none follow.
201: */
202: char *
203: nextword(wp, wbuf)
204: register char *wp, *wbuf;
205: {
206: register c;
207:
208: if (wp == NOSTR) {
209: *wbuf = 0;
210: return (NOSTR);
211: }
212: while ((c = *wp++) && c != ' ' && c != '\t') {
213: *wbuf++ = c;
214: if (c == '"') {
215: while ((c = *wp++) && c != '"')
216: *wbuf++ = c;
217: if (c == '"')
218: *wbuf++ = c;
219: else
220: wp--;
221: }
222: }
223: *wbuf = '\0';
224: for (; c == ' ' || c == '\t'; c = *wp++)
225: ;
226: if (c == 0)
227: return (NOSTR);
228: return (wp - 1);
229: }
230:
231: /*
232: * Is c contained in s?
233: */
234: any(c, s)
235: register c;
236: register char *s;
237: {
238:
239: while (*s)
240: if (*s++ == c)
241: return 1;
242: return 0;
243: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.