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 {
14: char *h_name;
15: int h_type;
16: } [] = {
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: 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 :
270: return MFHDR;
271:
272: case :
273: continue;
274:
275: case :
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: 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 :
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 :
361: *cp = ':';
362: fprintf (out, "%s\n", bp);
363: break;
364:
365: case :
366: case :
367: if (hl -> h_type == HFROM)
368: (*seen_from)++;
369: else
370: (*seen_sender)++;
371: case :
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: }