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 }