head.c revision 1590
1/*
2 * Copyright (c) 1980, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)head.c	8.1 (Berkeley) 6/6/93";
36#endif /* not lint */
37
38#include "rcv.h"
39#include "extern.h"
40
41/*
42 * Mail -- a mail program
43 *
44 * Routines for processing and detecting headlines.
45 */
46
47/*
48 * See if the passed line buffer is a mail header.
49 * Return true if yes.  Note the extreme pains to
50 * accomodate all funny formats.
51 */
52int
53ishead(linebuf)
54	char linebuf[];
55{
56	register char *cp;
57	struct headline hl;
58	char parbuf[BUFSIZ];
59
60	cp = linebuf;
61	if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
62	    *cp++ != ' ')
63		return (0);
64	parse(linebuf, &hl, parbuf);
65	if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
66		fail(linebuf, "No from or date field");
67		return (0);
68	}
69	if (!isdate(hl.l_date)) {
70		fail(linebuf, "Date field not legal date");
71		return (0);
72	}
73	/*
74	 * I guess we got it!
75	 */
76	return (1);
77}
78
79/*ARGSUSED*/
80void
81fail(linebuf, reason)
82	char linebuf[], reason[];
83{
84
85	/*
86	if (value("debug") == NOSTR)
87		return;
88	fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
89	*/
90}
91
92/*
93 * Split a headline into its useful components.
94 * Copy the line into dynamic string space, then set
95 * pointers into the copied line in the passed headline
96 * structure.  Actually, it scans.
97 */
98void
99parse(line, hl, pbuf)
100	char line[], pbuf[];
101	register struct headline *hl;
102{
103	register char *cp;
104	char *sp;
105	char word[LINESIZE];
106
107	hl->l_from = NOSTR;
108	hl->l_tty = NOSTR;
109	hl->l_date = NOSTR;
110	cp = line;
111	sp = pbuf;
112	/*
113	 * Skip over "From" first.
114	 */
115	cp = nextword(cp, word);
116	cp = nextword(cp, word);
117	if (*word)
118		hl->l_from = copyin(word, &sp);
119	if (cp != NOSTR && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
120		cp = nextword(cp, word);
121		hl->l_tty = copyin(word, &sp);
122	}
123	if (cp != NOSTR)
124		hl->l_date = copyin(cp, &sp);
125}
126
127/*
128 * Copy the string on the left into the string on the right
129 * and bump the right (reference) string pointer by the length.
130 * Thus, dynamically allocate space in the right string, copying
131 * the left string into it.
132 */
133char *
134copyin(src, space)
135	register char *src;
136	char **space;
137{
138	register char *cp;
139	char *top;
140
141	top = cp = *space;
142	while (*cp++ = *src++)
143		;
144	*space = cp;
145	return (top);
146}
147
148/*
149 * Test to see if the passed string is a ctime(3) generated
150 * date string as documented in the manual.  The template
151 * below is used as the criterion of correctness.
152 * Also, we check for a possible trailing time zone using
153 * the tmztype template.
154 */
155
156/*
157 * 'A'	An upper case char
158 * 'a'	A lower case char
159 * ' '	A space
160 * '0'	A digit
161 * 'O'	An optional digit or space
162 * ':'	A colon
163 * 'N'	A new line
164 */
165char ctype[] = "Aaa Aaa O0 00:00:00 0000";
166char tmztype[] = "Aaa Aaa O0 00:00:00 AAA 0000";
167
168int
169isdate(date)
170	char date[];
171{
172
173	return cmatch(date, ctype) || cmatch(date, tmztype);
174}
175
176/*
177 * Match the given string (cp) against the given template (tp).
178 * Return 1 if they match, 0 if they don't
179 */
180int
181cmatch(cp, tp)
182	register char *cp, *tp;
183{
184
185	while (*cp && *tp)
186		switch (*tp++) {
187		case 'a':
188			if (!islower(*cp++))
189				return 0;
190			break;
191		case 'A':
192			if (!isupper(*cp++))
193				return 0;
194			break;
195		case ' ':
196			if (*cp++ != ' ')
197				return 0;
198			break;
199		case '0':
200			if (!isdigit(*cp++))
201				return 0;
202			break;
203		case 'O':
204			if (*cp != ' ' && !isdigit(*cp))
205				return 0;
206			cp++;
207			break;
208		case ':':
209			if (*cp++ != ':')
210				return 0;
211			break;
212		case 'N':
213			if (*cp++ != '\n')
214				return 0;
215			break;
216		}
217	if (*cp || *tp)
218		return 0;
219	return (1);
220}
221
222/*
223 * Collect a liberal (space, tab delimited) word into the word buffer
224 * passed.  Also, return a pointer to the next word following that,
225 * or NOSTR if none follow.
226 */
227char *
228nextword(wp, wbuf)
229	register char *wp, *wbuf;
230{
231	register c;
232
233	if (wp == NOSTR) {
234		*wbuf = 0;
235		return (NOSTR);
236	}
237	while ((c = *wp++) && c != ' ' && c != '\t') {
238		*wbuf++ = c;
239		if (c == '"') {
240 			while ((c = *wp++) && c != '"')
241 				*wbuf++ = c;
242 			if (c == '"')
243 				*wbuf++ = c;
244			else
245				wp--;
246 		}
247	}
248	*wbuf = '\0';
249	for (; c == ' ' || c == '\t'; c = *wp++)
250		;
251	if (c == 0)
252		return (NOSTR);
253	return (wp - 1);
254}
255