date and time created 80/10/08 09:51:24 by kas
[unix-history] / usr / src / usr.bin / mail / head.c
CommitLineData
6a550447
KS
1#
2
3#include "rcv.h"
4
5/*
6 * Mail -- a mail program
7 *
8 * Routines for processing and detecting headlines.
9 */
10
11static char *SccsId = "@(#)head.c 1.1 %G%";
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
19ishead(linebuf)
20 char linebuf[];
21{
22 register char *cp;
23 struct headline hl;
24 char parbuf[BUFSIZ];
25
26 cp = linebuf;
27 if (!isname("From ", cp, 5))
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
46fail(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
62parse(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
103char *
104copyin(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
125isname(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 * Also, we check for a possible trailing time zone using
147 * the auxtype template.
148 */
149
150#define L 1 /* A lower case char */
151#define S 2 /* A space */
152#define D 3 /* A digit */
153#define O 4 /* An optional digit or space */
154#define C 5 /* A colon */
155#define N 6 /* A new line */
156#define U 7 /* An upper case char */
157
158char 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};
159char 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};
160
161isdate(date)
162 char date[];
163{
164 register char *cp;
165
166 cp = date;
167 if (cmatch(cp, ctypes))
168 return(1);
169 return(cmatch(cp, tmztypes));
170}
171
172/*
173 * Match the given string against the given template.
174 * Return 1 if they match, 0 if they don't
175 */
176
177cmatch(str, temp)
178 char str[], temp[];
179{
180 register char *cp, *tp;
181 register int c;
182
183 cp = str;
184 tp = temp;
185 while (*cp != '\0' && *tp != 0) {
186 c = *cp++;
187 switch (*tp++) {
188 case L:
189 if (c < 'a' || c > 'z')
190 return(0);
191 break;
192
193 case U:
194 if (c < 'A' || c > 'Z')
195 return(0);
196 break;
197
198 case S:
199 if (c != ' ')
200 return(0);
201 break;
202
203 case D:
204 if (!isdigit(c))
205 return(0);
206 break;
207
208 case O:
209 if (c != ' ' && !isdigit(c))
210 return(0);
211 break;
212
213 case C:
214 if (c != ':')
215 return(0);
216 break;
217
218 case N:
219 if (c != '\n')
220 return(0);
221 break;
222 }
223 }
224 if (*cp != '\0' || *tp != 0)
225 return(0);
226 return(1);
227}
228
229/*
230 * Collect a liberal (space, tab delimited) word into the word buffer
231 * passed. Also, return a pointer to the next word following that,
232 * or NOSTR if none follow.
233 */
234
235char *
236nextword(wp, wbuf)
237 char wp[], wbuf[];
238{
239 register char *cp, *cp2;
240
241 if ((cp = wp) == NOSTR) {
242 copy("", wbuf);
243 return(NOSTR);
244 }
245 cp2 = wbuf;
246 while (!any(*cp, " \t") && *cp != '\0')
247 *cp2++ = *cp++;
248 *cp2 = '\0';
249 while (any(*cp, " \t"))
250 cp++;
251 if (*cp == '\0')
252 return(NOSTR);
253 return(cp);
254}
255
256/*
257 * Test to see if the character is an ascii alphabetic.
258 */
259
260isalpha(c)
261{
262 register int ch;
263
264 ch = raise(c);
265 return(ch >= 'A' && ch <= 'Z');
266}
267
268/*
269 * Test to see if the character is an ascii digit.
270 */
271
272isdigit(c)
273{
274 return(c >= '0' && c <= '9');
275}
276
277/*
278 * Copy str1 to str2, return pointer to null in str2.
279 */
280
281char *
282copy(str1, str2)
283 char *str1, *str2;
284{
285 register char *s1, *s2;
286
287 s1 = str1;
288 s2 = str2;
289 while (*s1)
290 *s2++ = *s1++;
291 *s2 = 0;
292 return(s2);
293}
294
295/*
296 * Is ch any of the characters in str?
297 */
298
299any(ch, str)
300 char *str;
301{
302 register char *f;
303 register c;
304
305 f = str;
306 c = ch;
307 while (*f)
308 if (c == *f++)
309 return(1);
310 return(0);
311}
312
313/*
314 * Convert lower case letters to upper case.
315 */
316
317raise(c)
318 register int c;
319{
320 if (c >= 'a' && c <= 'z')
321 c += 'A' - 'a';
322 return(c);
323}