changed method of holding SIGCONT to just catch signal or
[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
79ddb121 11static char *SccsId = "@(#)head.c 2.1 %G%";
6a550447
KS
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
2be238e5
KS
142/*
143 * See if the two passed strings agree in the first n characters.
144 * Return true if they do, ignoring case.
145 */
146
147icisname(as1, as2, acount)
148 char *as1, *as2;
149{
150 register char *s1, *s2;
151 register count;
152
153 s1 = as1;
154 s2 = as2;
155 count = acount;
156 if (count > 0)
157 do
158 if (raise(*s1++) != raise(*s2++))
159 return(0);
160 while (--count);
161 return(1);
162}
163
6a550447
KS
164/*
165 * Test to see if the passed string is a ctime(3) generated
166 * date string as documented in the manual. The template
167 * below is used as the criterion of correctness.
168 * Also, we check for a possible trailing time zone using
169 * the auxtype template.
170 */
171
172#define L 1 /* A lower case char */
173#define S 2 /* A space */
174#define D 3 /* A digit */
175#define O 4 /* An optional digit or space */
176#define C 5 /* A colon */
177#define N 6 /* A new line */
178#define U 7 /* An upper case char */
179
180char 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};
181char 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};
182
183isdate(date)
184 char date[];
185{
186 register char *cp;
187
188 cp = date;
189 if (cmatch(cp, ctypes))
190 return(1);
191 return(cmatch(cp, tmztypes));
192}
193
194/*
195 * Match the given string against the given template.
196 * Return 1 if they match, 0 if they don't
197 */
198
199cmatch(str, temp)
200 char str[], temp[];
201{
202 register char *cp, *tp;
203 register int c;
204
205 cp = str;
206 tp = temp;
207 while (*cp != '\0' && *tp != 0) {
208 c = *cp++;
209 switch (*tp++) {
210 case L:
211 if (c < 'a' || c > 'z')
212 return(0);
213 break;
214
215 case U:
216 if (c < 'A' || c > 'Z')
217 return(0);
218 break;
219
220 case S:
221 if (c != ' ')
222 return(0);
223 break;
224
225 case D:
226 if (!isdigit(c))
227 return(0);
228 break;
229
230 case O:
231 if (c != ' ' && !isdigit(c))
232 return(0);
233 break;
234
235 case C:
236 if (c != ':')
237 return(0);
238 break;
239
240 case N:
241 if (c != '\n')
242 return(0);
243 break;
244 }
245 }
246 if (*cp != '\0' || *tp != 0)
247 return(0);
248 return(1);
249}
250
251/*
252 * Collect a liberal (space, tab delimited) word into the word buffer
253 * passed. Also, return a pointer to the next word following that,
254 * or NOSTR if none follow.
255 */
256
257char *
258nextword(wp, wbuf)
259 char wp[], wbuf[];
260{
261 register char *cp, *cp2;
262
263 if ((cp = wp) == NOSTR) {
264 copy("", wbuf);
265 return(NOSTR);
266 }
267 cp2 = wbuf;
268 while (!any(*cp, " \t") && *cp != '\0')
269 *cp2++ = *cp++;
270 *cp2 = '\0';
271 while (any(*cp, " \t"))
272 cp++;
273 if (*cp == '\0')
274 return(NOSTR);
275 return(cp);
276}
277
278/*
279 * Test to see if the character is an ascii alphabetic.
280 */
281
282isalpha(c)
283{
284 register int ch;
285
286 ch = raise(c);
287 return(ch >= 'A' && ch <= 'Z');
288}
289
290/*
291 * Test to see if the character is an ascii digit.
292 */
293
294isdigit(c)
295{
296 return(c >= '0' && c <= '9');
297}
298
299/*
300 * Copy str1 to str2, return pointer to null in str2.
301 */
302
303char *
304copy(str1, str2)
305 char *str1, *str2;
306{
307 register char *s1, *s2;
308
309 s1 = str1;
310 s2 = str2;
311 while (*s1)
312 *s2++ = *s1++;
313 *s2 = 0;
314 return(s2);
315}
316
317/*
318 * Is ch any of the characters in str?
319 */
320
321any(ch, str)
322 char *str;
323{
324 register char *f;
325 register c;
326
327 f = str;
328 c = ch;
329 while (*f)
330 if (c == *f++)
331 return(1);
332 return(0);
333}
334
335/*
336 * Convert lower case letters to upper case.
337 */
338
339raise(c)
340 register int c;
341{
342 if (c >= 'a' && c <= 'z')
343 c += 'A' - 'a';
344 return(c);
345}