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