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