Annotation of src/usr.bin/mail/head.c, Revision 1.5
1.5 ! millert 1: /* $OpenBSD: head.c,v 1.4 1997/07/14 00:24:27 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.5 ! millert 41: static char rcsid[] = "$OpenBSD: head.c,v 1.4 1997/07/14 00:24:27 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: {
1.5 ! millert 63: char *cp;
1.1 deraadt 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[];
1.5 ! millert 108: struct headline *hl;
1.1 deraadt 109: {
1.5 ! millert 110: char *cp, *sp;
1.1 deraadt 111: char word[LINESIZE];
112:
1.4 millert 113: hl->l_from = NULL;
114: hl->l_tty = NULL;
115: hl->l_date = NULL;
1.1 deraadt 116: cp = line;
117: sp = pbuf;
118: /*
119: * Skip over "From" first.
120: */
121: cp = nextword(cp, word);
122: cp = nextword(cp, word);
123: if (*word)
124: hl->l_from = copyin(word, &sp);
1.4 millert 125: if (cp != NULL && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
1.1 deraadt 126: cp = nextword(cp, word);
127: hl->l_tty = copyin(word, &sp);
128: }
1.4 millert 129: if (cp != NULL)
1.1 deraadt 130: hl->l_date = copyin(cp, &sp);
131: }
132:
133: /*
134: * Copy the string on the left into the string on the right
135: * and bump the right (reference) string pointer by the length.
136: * Thus, dynamically allocate space in the right string, copying
137: * the left string into it.
138: */
139: char *
140: copyin(src, space)
1.5 ! millert 141: char *src;
1.1 deraadt 142: char **space;
143: {
1.5 ! millert 144: char *cp, *top;
1.1 deraadt 145:
146: top = cp = *space;
1.2 deraadt 147: while ((*cp++ = *src++) != '\0')
1.1 deraadt 148: ;
149: *space = cp;
1.3 millert 150: return(top);
1.1 deraadt 151: }
152:
153: /*
154: * Test to see if the passed string is a ctime(3) generated
155: * date string as documented in the manual. The template
156: * below is used as the criterion of correctness.
157: * Also, we check for a possible trailing time zone using
158: * the tmztype template.
159: */
160:
161: /*
162: * 'A' An upper case char
163: * 'a' A lower case char
164: * ' ' A space
165: * '0' A digit
166: * 'O' An optional digit or space
167: * ':' A colon
168: * 'N' A new line
169: */
170: char ctype[] = "Aaa Aaa O0 00:00:00 0000";
171: char tmztype[] = "Aaa Aaa O0 00:00:00 AAA 0000";
1.3 millert 172: /*
173: * Yuck. If the mail file is created by Sys V (Solaris),
174: * there are no seconds in the time...
175: */
176: char SysV_ctype[] = "Aaa Aaa O0 00:00 0000";
177: char SysV_tmztype[] = "Aaa Aaa O0 00:00 AAA 0000";
1.1 deraadt 178:
179: int
180: isdate(date)
181: char date[];
182: {
183:
1.3 millert 184: return(cmatch(date, ctype) || cmatch(date, tmztype)
185: || cmatch(date, SysV_tmztype) || cmatch(date, SysV_ctype));
1.1 deraadt 186: }
187:
188: /*
189: * Match the given string (cp) against the given template (tp).
190: * Return 1 if they match, 0 if they don't
191: */
192: int
193: cmatch(cp, tp)
1.5 ! millert 194: char *cp, *tp;
1.1 deraadt 195: {
196:
197: while (*cp && *tp)
198: switch (*tp++) {
199: case 'a':
200: if (!islower(*cp++))
1.3 millert 201: return(0);
1.1 deraadt 202: break;
203: case 'A':
204: if (!isupper(*cp++))
1.3 millert 205: return(0);
1.1 deraadt 206: break;
207: case ' ':
208: if (*cp++ != ' ')
1.3 millert 209: return(0);
1.1 deraadt 210: break;
211: case '0':
212: if (!isdigit(*cp++))
1.3 millert 213: return(0);
1.1 deraadt 214: break;
215: case 'O':
216: if (*cp != ' ' && !isdigit(*cp))
1.3 millert 217: return(0);
1.1 deraadt 218: cp++;
219: break;
220: case ':':
221: if (*cp++ != ':')
1.3 millert 222: return(0);
1.1 deraadt 223: break;
224: case 'N':
225: if (*cp++ != '\n')
1.3 millert 226: return(0);
1.1 deraadt 227: break;
228: }
229: if (*cp || *tp)
1.3 millert 230: return(0);
231: return(1);
1.1 deraadt 232: }
233:
234: /*
235: * Collect a liberal (space, tab delimited) word into the word buffer
236: * passed. Also, return a pointer to the next word following that,
1.4 millert 237: * or NULL if none follow.
1.1 deraadt 238: */
239: char *
240: nextword(wp, wbuf)
1.5 ! millert 241: char *wp, *wbuf;
1.1 deraadt 242: {
1.5 ! millert 243: int c;
1.1 deraadt 244:
1.4 millert 245: if (wp == NULL) {
1.1 deraadt 246: *wbuf = 0;
1.4 millert 247: return(NULL);
1.1 deraadt 248: }
249: while ((c = *wp++) && c != ' ' && c != '\t') {
250: *wbuf++ = c;
251: if (c == '"') {
252: while ((c = *wp++) && c != '"')
253: *wbuf++ = c;
254: if (c == '"')
255: *wbuf++ = c;
256: else
257: wp--;
258: }
259: }
260: *wbuf = '\0';
261: for (; c == ' ' || c == '\t'; c = *wp++)
262: ;
263: if (c == 0)
1.4 millert 264: return(NULL);
1.3 millert 265: return(wp - 1);
1.1 deraadt 266: }