Mercurial > hg > Applications > mh
comparison zotnet/mf/uumm.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bce86c4163a3 |
---|---|
1 /* uumm.c - routines to filter UUCP to MMDF mailboxes */ | |
2 | |
3 #include "mf.h" | |
4 #include "../tws/tws.h" | |
5 #include <stdio.h> | |
6 #include "../mts/mts.h" | |
7 #include <ctype.h> | |
8 #include <sys/types.h> | |
9 #include <sys/stat.h> | |
10 | |
11 /* */ | |
12 | |
13 static struct header { | |
14 char *h_name; | |
15 int h_type; | |
16 } headers[] = { | |
17 "From", HFROM, | |
18 "Sender", HSNDR, | |
19 "Reply-To", HADDR, | |
20 "To", HADDR, | |
21 "cc", HADDR, | |
22 "Bcc", HADDR, | |
23 "Resent-From", HADDR, | |
24 "Resent-Sender", HADDR, | |
25 "Resent-Reply-To", HADDR, | |
26 "Resent-To", HADDR, | |
27 "Resent-cc", HADDR, | |
28 "Resent-Bcc", HADDR, | |
29 "Date", HDATE, | |
30 "Resent-Date", HDATE, | |
31 NULL, HOTHR | |
32 }; | |
33 | |
34 static char buffer[BUFSIZ], | |
35 tmpbuf[BUFSIZ]; | |
36 | |
37 char *shrink (); | |
38 | |
39 long time (); | |
40 | |
41 /* */ | |
42 | |
43 /* | |
44 * uucp2mmdf() - given a file descriptor to a uucp mailbox, filter | |
45 * its contents to the file descriptor for a mmdf mailbox. Returns | |
46 * non-zero on error (see mf.h for values) | |
47 * | |
48 * It is assumed that the caller will have made sure that the necessary | |
49 * locking has been performed on the output fd. | |
50 */ | |
51 | |
52 int uucp2mmdf (infd, outfd, nodelim) | |
53 int infd, | |
54 outfd, | |
55 nodelim; | |
56 { | |
57 int fd, | |
58 result; | |
59 struct stat st; | |
60 FILE * in, *out; | |
61 | |
62 if (fstat (infd, &st) == NOTOK || fstat (outfd, &st) == NOTOK) | |
63 return MFPRM; | |
64 if ((in = fdopen (infd, "r")) == NULL | |
65 || (out = fdopen (outfd, "w")) == NULL) | |
66 return MFSIO; | |
67 | |
68 result = uumm (in, out, nodelim); | |
69 | |
70 /* for STDIO - free up some fp:s */ | |
71 fd = dup (fileno (in)); | |
72 fclose (in); | |
73 dup2 (fd, infd); | |
74 close (fd); | |
75 | |
76 fd = dup (fileno (out)); | |
77 fclose (out); | |
78 dup2 (fd, outfd); | |
79 close (fd); | |
80 | |
81 return result; | |
82 } | |
83 | |
84 /* */ | |
85 | |
86 int uumm (in, out, nodelim) | |
87 FILE *in, | |
88 *out; | |
89 int nodelim; | |
90 { | |
91 int i, | |
92 tmp_fd; | |
93 char from[LINESIZ], | |
94 date[LINESIZ]; | |
95 FILE *tmp; | |
96 | |
97 for (tmp_fd = NOTOK;;) { | |
98 if ((i = uucp_file (&tmp_fd, in, &tmp, nodelim)) == DONE) | |
99 break; | |
100 else | |
101 if (i != OK) | |
102 return i; | |
103 if ((i = uucp_from (from, date, tmp)) != OK) | |
104 return uucp_die (i, tmp, in, out, nodelim); | |
105 if ((i = uucp_headers (from, date, tmp, out, nodelim)) != OK) | |
106 return uucp_die (i, tmp, in, out, nodelim); | |
107 if ((i = uucp_text (tmp, out, nodelim)) != OK) | |
108 return uucp_die (i, tmp, in, out, nodelim); | |
109 } | |
110 | |
111 fflush (out); | |
112 | |
113 return (ferror (in) || ferror (out) ? MFERR : MFOK); | |
114 } | |
115 | |
116 /* */ | |
117 | |
118 static int uucp_file (tmp_fd, in, tmp, nodelim) | |
119 int *tmp_fd, | |
120 nodelim; | |
121 FILE * in, **tmp; | |
122 { | |
123 int done, | |
124 fd; | |
125 char tmpfil[LINESIZ]; | |
126 FILE * out; | |
127 | |
128 if (nodelim) | |
129 if (*tmp_fd != NOTOK) | |
130 return DONE; | |
131 else | |
132 if ((*tmp_fd = dup (fileno (in))) == NOTOK) | |
133 return MFERR; | |
134 else | |
135 if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) { | |
136 close (*tmp_fd); | |
137 return MFERR; | |
138 } | |
139 else | |
140 return OK; | |
141 | |
142 if (*tmp_fd == NOTOK && fgets (tmpbuf, sizeof tmpbuf, in) == NULL) | |
143 return DONE; | |
144 else | |
145 if (feof (in)) | |
146 return DONE; | |
147 | |
148 strcpy (tmpfil, "/tmp/uummXXXXXX"); | |
149 unlink (mktemp (tmpfil)); | |
150 if ((fd = creat (tmpfil, TMPMODE)) == NOTOK) | |
151 return MFERR; | |
152 close (fd); | |
153 | |
154 if ((fd = open (tmpfil, 2)) == NOTOK) | |
155 return MFERR; | |
156 if ((out = fdopen (fd, "w")) == NULL) { | |
157 close (fd); | |
158 return MFERR; | |
159 } | |
160 unlink (tmpfil); | |
161 | |
162 if ((*tmp_fd = dup (fd)) == NOTOK) { | |
163 close (fd); | |
164 return MFERR; | |
165 } | |
166 if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) { | |
167 close (fd); | |
168 close (*tmp_fd); | |
169 return MFERR; | |
170 } | |
171 | |
172 /* */ | |
173 | |
174 for (done = FALSE;;) { | |
175 if (done) | |
176 if (isfrom (tmpbuf)) | |
177 break; | |
178 else | |
179 putc ('\n', out); | |
180 done = tmpbuf[0] == '\n'; | |
181 if (!done) | |
182 fputs (tmpbuf, out); | |
183 if (fgets (tmpbuf, sizeof tmpbuf, in) == NULL) | |
184 break; | |
185 } | |
186 | |
187 fclose (out); | |
188 fseek (*tmp, 0L, 0); | |
189 return OK; | |
190 } | |
191 | |
192 /* */ | |
193 | |
194 /* We might want to attempt recovery here. Forget it. */ | |
195 | |
196 static int uucp_from (from, date, in) | |
197 char *from, | |
198 *date; | |
199 FILE * in; | |
200 { | |
201 char *cp, | |
202 *pp, | |
203 fromwhom[LINESIZ]; | |
204 struct adrx *adrxp; | |
205 | |
206 if (fgets (buffer, sizeof buffer, in) == NULL || !isfrom (buffer)) | |
207 return MFROM; | |
208 if (buffer[strlen (buffer) - 1] == '\n') | |
209 buffer[strlen (buffer) - 1] = NULL; | |
210 if ((cp = index (buffer, ' ')) == NULL) | |
211 return MFROM; | |
212 pp = ++cp; | |
213 if ((cp = index (cp, ' ')) == NULL) | |
214 return MFROM; | |
215 *cp++ = NULL; | |
216 strcpy (fromwhom, pp); | |
217 while (isspace (*cp)) | |
218 cp++; | |
219 sprintf (date, "%.24s", cp); | |
220 | |
221 for (;;) { | |
222 if ((cp = index (cp + 1, 'r')) == NULL) { | |
223 if (index (fromwhom, '!') || index (fromwhom, '@')) | |
224 strcpy (from, fromwhom); | |
225 else | |
226 sprintf (from, "%s!%s", SystemName (), fromwhom); | |
227 break; | |
228 } | |
229 if (strncmp (cp, "remote from ", 12) == 0) { | |
230 *cp = NULL; | |
231 sprintf (from, "%s!%s", cp + 12, fromwhom); | |
232 break; | |
233 } | |
234 } | |
235 | |
236 if ((adrxp = seekadrx (from)) == NULL) | |
237 return MFROM; | |
238 addr_convert (adrxp, from, TRUE); | |
239 while (seekadrx (NULL)) | |
240 continue; | |
241 if (from[0] == NULL) | |
242 return MFROM; | |
243 date_convert (date, date); | |
244 return (date[0] != NULL ? OK : MFROM); | |
245 } | |
246 | |
247 /* */ | |
248 | |
249 static int uucp_headers (from, date, in, out, nodelim) | |
250 int nodelim; | |
251 char *from, | |
252 *date; | |
253 FILE * in, *out; | |
254 { | |
255 int i, | |
256 seen_from, | |
257 seen_sender, | |
258 seen_date; | |
259 | |
260 seen_from = seen_sender = seen_date = 0; | |
261 if (!nodelim) | |
262 fputs (mmdlm1, out); | |
263 | |
264 fprintf (out, "Munged: from %s to %s; %s\n", | |
265 SystemName (), LocalName (), dtimenow ()); | |
266 | |
267 for (;;) { | |
268 switch (do_header (&seen_from, &seen_sender, &seen_date, in, out)) { | |
269 case NOTOK: | |
270 return MFHDR; | |
271 | |
272 case OK: | |
273 continue; | |
274 | |
275 case DONE: | |
276 break; | |
277 } | |
278 break; | |
279 } | |
280 /* extra newline separates headers and body */ | |
281 fprintf (out, "%sDate: %s\n%s: %s\n\n", | |
282 seen_date ? "UUCP-" : NULL, date, | |
283 seen_from ? (seen_sender ? "UUCP-Sender" : "Sender") : "From", | |
284 from); | |
285 | |
286 return OK; | |
287 } | |
288 | |
289 /* */ | |
290 | |
291 static int uucp_text (in, out, nodelim) | |
292 int nodelim; | |
293 FILE * in, *out; | |
294 { | |
295 if (feof (in)) /* probably no body */ | |
296 putc ('\n', out); | |
297 else | |
298 while (fgets (buffer, sizeof buffer, in) != NULL) { | |
299 if (!nodelim && isdlm2 (buffer)) | |
300 buffer[0]++; | |
301 fputs (buffer, out); | |
302 } | |
303 | |
304 if (!nodelim) | |
305 fputs (mmdlm2, out); | |
306 fclose (in); | |
307 | |
308 return OK; | |
309 } | |
310 | |
311 /* */ | |
312 | |
313 static int do_header (seen_from, seen_sender, seen_date, in, out) | |
314 int *seen_from, | |
315 *seen_sender, | |
316 *seen_date; | |
317 FILE * in, *out; | |
318 { | |
319 int i, | |
320 margin, | |
321 some, | |
322 spat, | |
323 pos; | |
324 char *bp, | |
325 *cp, | |
326 *pp, | |
327 line[BUFSIZ]; | |
328 struct adrx *adrxp; | |
329 struct header *hl; | |
330 | |
331 if ((i = mfgets (in, &bp)) != OK) | |
332 return i; | |
333 | |
334 if ((cp = index (bp, ':')) == NULL) { | |
335 fprintf (out, "Illegal-Field: %s\n", bp); | |
336 return OK; | |
337 } | |
338 | |
339 *cp = NULL; | |
340 for (hl = &headers[0]; hl -> h_name; hl++) | |
341 if (lequal (hl -> h_name, bp)) | |
342 break; | |
343 | |
344 /* */ | |
345 | |
346 switch (hl -> h_type) { | |
347 case HDATE: | |
348 if (lequal (hl -> h_name, "Date")) | |
349 (*seen_date)++; | |
350 for (pp = cp + 1; isspace (*pp); pp++) | |
351 continue; | |
352 date_convert (pp, line); | |
353 if (line[0] == NULL) | |
354 fprintf (out, "Illegal-Object: %s: %s -- %s\n", | |
355 hl -> h_name, pp, "illegal date construct"); | |
356 else | |
357 fprintf (out, "%s: %s\n", hl -> h_name, line); | |
358 break; | |
359 | |
360 case HOTHR: | |
361 *cp = ':'; | |
362 fprintf (out, "%s\n", bp); | |
363 break; | |
364 | |
365 case HFROM: | |
366 case HSNDR: | |
367 if (hl -> h_type == HFROM) | |
368 (*seen_from)++; | |
369 else | |
370 (*seen_sender)++; | |
371 case HADDR: | |
372 spat = 0; | |
373 some = FALSE; | |
374 pp = ++cp; | |
375 margin = pos = strlen (hl -> h_name) + 2; | |
376 while (adrxp = seekadrx (pp)) { | |
377 addr_convert (adrxp, line, FALSE); | |
378 if (line[0] != NULL) { | |
379 if (!spat++) | |
380 fprintf (out, "%s: ", hl -> h_name); | |
381 if (some++) | |
382 fputs (", ", out), pos += 2; | |
383 if (pos + strlen (line) >= OWIDTH) { | |
384 fprintf (out, "\n%*s", margin, " "); | |
385 pos = margin; | |
386 } | |
387 fputs (line, out); | |
388 pos += strlen (line); | |
389 } | |
390 else { | |
391 if (spat) | |
392 putc ('\n', out); | |
393 fprintf (out, "Illegal-Object: %s: %s -- %s\n", | |
394 hl -> h_name, adrxp -> text, adrxp -> err); | |
395 spat = 0; | |
396 some = FALSE; | |
397 pos = margin; | |
398 } | |
399 } | |
400 if (spat) | |
401 putc ('\n', out); | |
402 break; | |
403 | |
404 default: | |
405 return NOTOK; | |
406 } | |
407 | |
408 return OK; | |
409 } | |
410 | |
411 /* */ | |
412 | |
413 addr_convert (adrxp, to, notice) | |
414 struct adrx *adrxp; | |
415 char *to; | |
416 int notice; | |
417 { | |
418 int addrlen, | |
419 uucplen; | |
420 char *cp, | |
421 *wp, | |
422 addr[BUFSIZ], | |
423 tmp[LINESIZ], | |
424 uucp[LINESIZ]; | |
425 static char path[LINESIZ] = ""; | |
426 | |
427 if (adrxp -> err || !adrxp -> mbox) { | |
428 *to = NULL; | |
429 return; | |
430 } | |
431 if (notice) | |
432 if ((cp = rindex (adrxp -> mbox, '!')) != NULL) | |
433 sprintf (path, "%.*s!", cp - adrxp -> mbox, adrxp -> mbox); | |
434 else | |
435 path[0] = NULL; | |
436 | |
437 sprintf (addr, "%s%s", path, adrxp -> mbox); | |
438 sprintf (uucp, "%s!", SystemName ()); | |
439 uucplen = strlen (uucp); | |
440 if ((addrlen = strlen (addr) - uucplen - 1) >= 0) | |
441 for (cp = addr + addrlen; cp >= addr; cp--) | |
442 if (strncmp (cp, uucp, uucplen) == NULL) { | |
443 if (cp != addr && *(cp - 1) != '!') | |
444 continue; | |
445 strcpy (addr, cp + uucplen); | |
446 break; | |
447 } | |
448 | |
449 /* */ | |
450 | |
451 if (adrxp -> host == NULL) { | |
452 cp = shrink (addr); | |
453 #ifdef MMDFMTS | |
454 sprintf (uucp, "%s%%%s@%s", cp, UucpChan (), LocalName ()); | |
455 #else MMDFMTS | |
456 if (wp = index (adrxp -> mbox, '!')) | |
457 sprintf (uucp, "%s@%.*s.%s", | |
458 wp + 1, wp - adrxp -> mbox, adrxp -> mbox, UucpChan ()); | |
459 else | |
460 sprintf (uucp, "%s@%s.%s", | |
461 adrxp -> mbox, SystemName (), UucpChan ()); | |
462 #endif MMDFMTS | |
463 if (strcmp (adrxp -> mbox, cp)) | |
464 sprintf (tmp, "\"%s\" <%s>", adrxp -> mbox, uucp); | |
465 else | |
466 strcpy (tmp, uucp); | |
467 } | |
468 else | |
469 if ((wp = rindex (adrxp -> mbox, '!')) == NULL) | |
470 sprintf (tmp, "%s@%s", adrxp -> mbox, adrxp -> host); | |
471 else { | |
472 sprintf (uucp, "%%%s", UucpChan ()); | |
473 uucplen = strlen (uucp); | |
474 cp = (lequal (LocalName (), adrxp -> host) | |
475 && (addrlen = strlen (addr) - uucplen) > 0) | |
476 ? addr + addrlen : NULL; | |
477 if (lequal (uucp, cp)) | |
478 sprintf (tmp, "%s@%s", shrink (addr), adrxp -> host); | |
479 else { | |
480 if (lequal (adrxp -> mbox, ++wp)) | |
481 sprintf (tmp, "%s@%s", wp, adrxp -> host); | |
482 else | |
483 sprintf (tmp, "\"%s\" <%s@%s>", adrxp -> mbox, | |
484 wp, adrxp -> host); | |
485 } | |
486 } | |
487 | |
488 strcpy (to, tmp); | |
489 } | |
490 | |
491 /* */ | |
492 | |
493 static char *shrink (addr) | |
494 char *addr; | |
495 { | |
496 int i, | |
497 j; | |
498 char *cp, | |
499 *pp, | |
500 *wp, | |
501 *xp; | |
502 static char r1[BUFSIZ], | |
503 r2[BUFSIZ]; | |
504 | |
505 sprintf (r2, "%s!", SystemName ()); | |
506 i = strlen (r2); | |
507 if ((j = strlen (addr) - i - 1) >= 0) | |
508 for (cp = &addr[j]; cp >= addr; cp--) | |
509 if (strncmp (cp, r2, i) == NULL) { | |
510 if (cp != addr && *(cp - 1) != '!') | |
511 continue; | |
512 strcpy (addr, cp + i); | |
513 break; | |
514 } | |
515 | |
516 if ((cp = rindex (addr, '!')) == NULL) { | |
517 sprintf (r1, "%s%s", r2, addr); | |
518 return r1; | |
519 } | |
520 *cp++ = NULL; | |
521 | |
522 if ((pp = rindex (addr, '!')) == NULL) { | |
523 *--cp = '!'; | |
524 strcpy (r1, addr); | |
525 return r1; | |
526 } | |
527 strcpy (r1, cp); | |
528 | |
529 while ((pp = rindex (addr, '!')) != NULL) { | |
530 for (pp++, xp = addr; (wp = index (xp, '!')) != NULL;) { | |
531 *wp = NULL; | |
532 if (strcmp (pp, xp)) { | |
533 *wp++ = '!'; | |
534 xp = wp; | |
535 } | |
536 else { | |
537 pp = xp; | |
538 break; | |
539 } | |
540 } | |
541 sprintf (r2, "%s!%s", pp, r1); | |
542 strcpy (r1, r2); | |
543 if (--pp > addr) | |
544 *pp = NULL; | |
545 } | |
546 | |
547 /* */ | |
548 | |
549 if ((wp = index (r1, '!')) != NULL) { | |
550 *wp = NULL; | |
551 strcpy (r2, r1); | |
552 *wp = '!'; | |
553 if (strcmp (addr, r2)) { | |
554 sprintf (r2, "%s!%s", addr, r1); | |
555 strcpy (r1, r2); | |
556 } | |
557 } | |
558 | |
559 return r1; | |
560 } | |
561 | |
562 /* */ | |
563 | |
564 date_convert (from, to) | |
565 char from[], | |
566 *to; | |
567 { | |
568 static int zone = -1, | |
569 flags = TW_NULL; | |
570 char date[LINESIZ]; | |
571 struct tws *tw; | |
572 | |
573 if (dparsetime (from)) /* might be OK as is */ | |
574 strcpy (date, from); | |
575 else | |
576 if (isdigit (from[20])) { | |
577 if (zone == -1) { | |
578 if (tw = dtwstime ()) { | |
579 zone = tw -> tw_zone; | |
580 flags = tw -> tw_flags; | |
581 } | |
582 else | |
583 zone = 0, flags = TW_NULL; | |
584 } | |
585 sprintf (date, "%.3s, %.2s %.3s %.2s %.2s:%.2s:%.2s %s", | |
586 from + 0, from + 8, from + 4, from + 22, from + 11, | |
587 from + 14, from + 17, dtimezone (zone, flags)); | |
588 } | |
589 else | |
590 sprintf (date, "%.3s, %.2s %.3s %.2s %.2s:%.2s:%.2s %s", | |
591 from + 0, from + 8, from + 4, from + 26, from + 11, | |
592 from + 14, from + 17, from + 20); | |
593 | |
594 strcpy (to, date); | |
595 } | |
596 | |
597 /* */ | |
598 | |
599 static int uucp_die (error, in1, in2, out, nodelim) | |
600 int error, | |
601 nodelim; | |
602 FILE * in1, *in2, *out; | |
603 { | |
604 long clock; | |
605 char date[LINESIZ]; | |
606 | |
607 if (nodelim) { | |
608 fclose (in1); | |
609 return error; | |
610 } | |
611 | |
612 switch (error) { | |
613 case MFHDR: | |
614 putc ('\n', out); | |
615 case MFTXT: | |
616 fprintf (out, "\n%s", mmdlm2); | |
617 break; | |
618 } | |
619 | |
620 time (&clock); | |
621 sprintf (date, "%.*s", sizeof date - 1, dtime (&clock)); | |
622 fprintf (out, "%sFrom: %s <%s@%s>\nDate: %s\nSubject: %s %s\n\n", | |
623 mmdlm1, "UUCP to MMDF filter", getusr (), LocalName (), date, | |
624 "Bad UUCP mailbox - error in", | |
625 error == MFHDR ? "Header" : error == MFTXT ? "Body" : "Mailbox"); | |
626 | |
627 fprintf (out, "%s: %s\n%s\n--------\n", | |
628 "Error detected at line", buffer, "Message being processed"); | |
629 fseek (in1, 0L, 0); | |
630 while (fgets (buffer, sizeof buffer, in1) != NULL) { | |
631 if (isdlm2 (buffer)) | |
632 buffer[0]++; | |
633 fputs (buffer, out); | |
634 } | |
635 fclose (in1); | |
636 | |
637 if (!feof (in2)) { | |
638 fprintf (out, "--------\n%s\n--------\n%s", | |
639 "Remainder of unfiltered mailbox follows", tmpbuf); | |
640 while (fgets (buffer, sizeof buffer, in2) != NULL) { | |
641 if (isdlm2 (buffer)) | |
642 buffer[0]++; | |
643 fputs (buffer, out); | |
644 } | |
645 } | |
646 | |
647 fprintf (out, "--------\n%s", mmdlm2); | |
648 fflush (out); | |
649 | |
650 return error; | |
651 } |