1: /* mmuu.c - routines to filter MMDF to UUCP 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:
35: static char buffer[BUFSIZ],
36: tmpbuf[BUFSIZ];
37:
38: long time ();
39: char *ctime ();
40:
41: /* */
42:
43: /*
44: * mmdf2uucp() - given a file descriptor to a mmdf 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 mmdf2uucp (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 = mmuu (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: static int mmuu (in, out, nodelim)
87: FILE *in,
88: *out;
89: int nodelim;
90: {
91: int i,
92: tmp_fd;
93: FILE *tmp;
94:
95: for (tmp_fd = NOTOK;;) {
96: if ((i = mmdf_file (&tmp_fd, in, &tmp, nodelim)) == DONE)
97: break;
98: else
99: if (i != OK)
100: return i;
101: if ((i = mmdf_headers (tmp, out, nodelim)) != OK)
102: return mmdf_die (i, tmp, in, out, nodelim);
103: if ((i = mmdf_text (tmp, out, nodelim)) != OK)
104: return mmdf_die (i, tmp, in, out, nodelim);
105: }
106:
107: fflush (out);
108:
109: return (ferror (in) || ferror (out) ? MFERR : MFOK);
110: }
111:
112: /* */
113:
114: static int mmdf_file (tmp_fd, in, tmp, nodelim)
115: int *tmp_fd,
116: nodelim;
117: FILE * in, **tmp;
118: {
119: int done,
120: fd;
121: char tmpfil[LINESIZ];
122: FILE * out;
123:
124: if (nodelim)
125: if (*tmp_fd != NOTOK)
126: return DONE;
127: else
128: if ((*tmp_fd = dup (fileno (in))) == NOTOK)
129: return MFERR;
130: else
131: if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) {
132: close (*tmp_fd);
133: return MFERR;
134: }
135: else
136: return OK;
137:
138: if (fgets (tmpbuf, sizeof tmpbuf, in) == NULL)
139: return DONE;
140: if (!isdlm1 (tmpbuf))
141: return MFDLM;
142:
143: strcpy (tmpfil, "/tmp/mmuuXXXXXX");
144: unlink (mktemp (tmpfil));
145: if ((fd = creat (tmpfil, TMPMODE)) == NOTOK)
146: return MFERR;
147: close (fd);
148:
149: if ((fd = open (tmpfil, 2)) == NOTOK)
150: return MFERR;
151: if ((out = fdopen (fd, "w")) == NULL) {
152: close (fd);
153: return MFERR;
154: }
155: unlink (tmpfil);
156:
157: if ((*tmp_fd = dup (fd)) == NOTOK) {
158: close (fd);
159: return MFERR;
160: }
161: if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) {
162: close (fd);
163: close (*tmp_fd);
164: return MFERR;
165: }
166:
167: /* */
168:
169: for (done = FALSE;;) {
170: if (fgets (tmpbuf, sizeof tmpbuf, in) == NULL)
171: return MFDLM;
172: if (done && isdlm2 (tmpbuf))
173: break;
174: done = tmpbuf[strlen (tmpbuf) - 1] == '\n';
175: fputs (tmpbuf, out);
176: }
177:
178: fclose (out);
179: fseek (*tmp, 0L, 0);
180: return OK;
181: }
182:
183: /* */
184:
185: int mmdf_headers (in, out, nodelim)
186: FILE * in, *out;
187: int nodelim;
188: {
189: int fd,
190: i,
191: tmp_fd;
192: char *cp,
193: line[BUFSIZ],
194: from[LINESIZ],
195: date[LINESIZ],
196: tmpfil[LINESIZ];
197: FILE * tmp;
198:
199: *from = *date = NULL;
200:
201: strcpy (tmpfil, "/tmp/mmuuXXXXXX");
202: unlink (mktemp (tmpfil));
203: if ((fd = creat (tmpfil, TMPMODE)) == NOTOK)
204: return MFERR;
205: close (fd);
206: if ((tmp_fd = open (tmpfil, 2)) == NOTOK)
207: return MFERR;
208: unlink (tmpfil);
209:
210: if ((fd = dup (tmp_fd)) == NOTOK) {
211: close (tmp_fd);
212: return MFERR;
213: }
214: if ((tmp = fdopen (fd, "w")) == NULL) {
215: close (tmp_fd);
216: close (fd);
217: return MFERR;
218: }
219:
220: for (;;) {
221: switch (do_header (from, date, in, tmp)) {
222: case :
223: close (tmp_fd);
224: fclose (tmp);
225: return MFHDR;
226:
227: case :
228: continue;
229:
230: case :
231: fclose (tmp);
232: break;
233: }
234: break;
235: }
236:
237: /* */
238:
239: if (*date == NULL || *from == NULL) {
240: if (*date)
241: strcpy (buffer, "No (valid) From: field found in message\n");
242: else
243: if (*from)
244: strcpy (buffer, "No (valid) Date: field found in message\n");
245: else
246: strcpy (buffer,
247: "No (valid) From: or Date: fields found in message\n");
248: if (nodelim) {
249: if (*date == NULL) {
250: long clock;
251:
252: time (&clock);
253: sprintf (date, "%.24s", ctime (&clock));
254: }
255: if (*from == NULL)
256: sprintf (from, "%s!%s", SystemName (), getusr ());
257: }
258: else
259: return MFHDR;
260: }
261: else
262: buffer[0] = NULL;
263:
264: if (nodelim && (cp = index (from, '!')) != NULL) {
265: *cp++ = NULL;
266: fprintf (out, "From %s %s remote from %s\n", cp, date, from);
267: }
268: else
269: fprintf (out, "From %s %s\n", from, date);
270:
271: fprintf (out, "Munged: from %s to %s; %s\n",
272: LocalName (), SystemName (), dtimenow ());
273: if (buffer[0])
274: fprintf (out, "Illegal-Field: %s", buffer);
275:
276: if ((tmp = fdopen (tmp_fd, "r")) == NULL) {
277: close (tmp_fd);
278: return MFERR;
279: }
280: fseek (tmp, 0L, 0);
281:
282: while ((i = fread (line, sizeof *line, sizeof line, tmp)) > 0)
283: fwrite (line, sizeof *line, i, out);
284: putc ('\n', out); /* separate headers from body */
285: fclose (tmp);
286:
287: return OK;
288: }
289:
290: /* */
291:
292: static int mmdf_text (in, out, nodelim)
293: int nodelim;
294: FILE * in, *out;
295: {
296: int i;
297:
298: if (feof (in)) /* probably no body */
299: putc ('\n', out);
300: else
301: while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in)) > 0)
302: fwrite (buffer, sizeof *buffer, i, out);
303:
304: if (!nodelim)
305: putc ('\n', out);
306: fclose (in);
307:
308: return OK;
309: }
310:
311: /* */
312:
313: int do_header (from, date, in, out)
314: char *from,
315: *date;
316: FILE * in, *out;
317: {
318: int i,
319: margin,
320: some,
321: spat,
322: pos;
323: char *bp,
324: *cp,
325: *pp,
326: line[BUFSIZ];
327: struct adrx *adrxp;
328: struct header *hl;
329:
330: if ((i = mfgets (in, &bp)) != OK)
331: return i;
332:
333: if ((cp = index (bp, ':')) == NULL) {
334: fprintf (out, "Illegal-Field: %s\n", bp);
335: return OK;
336: }
337:
338: *cp = NULL;
339: for (hl = &headers[0]; hl -> h_name; hl++)
340: if (lequal (hl -> h_name, bp))
341: break;
342:
343: /* */
344:
345: switch (hl -> h_type) {
346: case :
347: *cp = ':';
348: fprintf (out, "%s\n", bp);
349: break;
350:
351: case :
352: pp = ++cp;
353: if (*date != NULL || !lequal (hl -> h_name, "Date"))
354: return OK;
355: date_convert (pp, date);
356: if (*date == NULL)
357: fprintf (out,
358: "Illegal-Object: %s: %s -- illegal date construct\n",
359: hl -> h_name, pp);
360: break;
361:
362: case :
363: pp = ++cp;
364: if (*from != NULL)
365: return OK;
366: if ((adrxp = getadrx (pp)) == NULL) {
367: fprintf (out, "Illegal-Object: %s: %s -- %s\n",
368: hl -> h_name, pp, "no address");
369: return OK; /* catch errors later (possibly) */
370: }
371: addr_convert (adrxp, from, TRUE);
372: if (*from == NULL)
373: fprintf (out, "Illegal-Object: %s: %s -- %s\n",
374: hl -> h_name, adrxp -> text, adrxp -> err);
375: while (getadrx (NULL))
376: continue;
377: break;
378:
379: case :
380: case :
381: spat = 0;
382: some = FALSE;
383: pp = ++cp;
384: margin = pos = strlen (hl -> h_name) + 2;
385: while (adrxp = getadrx (pp)) {
386: addr_convert (adrxp, line, FALSE);
387: if (line[0] != NULL) {
388: if (!spat++)
389: fprintf (out, "%s: ", hl -> h_name);
390: if (some++)
391: fputs (", ", out), pos += 2;
392: if (pos + strlen (line) >= OWIDTH) {
393: fprintf (out, "\n%*s", margin, " ");
394: pos = margin;
395: }
396: fputs (line, out);
397: pos += strlen (line);
398: }
399: else {
400: if (spat)
401: putc ('\n', out);
402: fprintf (out, "Illegal-Object: %s: %s -- %s\n",
403: hl -> h_name, adrxp -> text, adrxp -> err);
404: spat = 0;
405: some = FALSE;
406: pos = margin;
407: }
408: }
409: if (spat)
410: putc ('\n', out);
411: break;
412:
413: default:
414: return NOTOK;
415: }
416:
417: return OK;
418: }
419:
420: /* */
421:
422: static addr_convert (adrxp, to, notice)
423: struct adrx *adrxp;
424: char *to;
425: int notice;
426: {
427: int mboxlen,
428: uucplen;
429: char *cp,
430: tmp[LINESIZ],
431: uucp[LINESIZ];
432: static char path[LINESIZ] = "";
433:
434: if (path[0] == NULL)
435: strcpy (path, LocalName ());
436:
437: if (adrxp -> err || !adrxp -> mbox) {
438: *to = NULL;
439: return;
440: }
441: if (notice)
442: strcpy (path, adrxp -> host ? adrxp -> host : LocalName ());
443:
444: if (adrxp -> host == NULL)
445: if (index (adrxp -> mbox, '!') != NULL)
446: strcpy (tmp, adrxp -> mbox);
447: else
448: if (lequal (path, LocalName ()))
449: sprintf (tmp, "%s!%s", SystemName (), adrxp -> mbox);
450: else
451: sprintf (tmp, "%s!%s@%s", SystemName (), adrxp -> mbox, path);
452: else
453: if (index (adrxp -> mbox, '!') == NULL)
454: sprintf (tmp, "%s!%s@%s",
455: SystemName (), adrxp -> mbox, adrxp -> host);
456: else {
457: sprintf (uucp, "%%%s", UucpChan ());
458: uucplen = strlen (uucp);
459: cp = (lequal (LocalName (), adrxp -> host)
460: && (mboxlen = strlen (adrxp -> mbox) - uucplen) > 0)
461: ? (adrxp -> mbox) + mboxlen : NULL;
462: if (lequal (uucp, cp))
463: sprintf (tmp, "%.*s", mboxlen, adrxp -> mbox);
464: else
465: if ((cp = index (adrxp -> host, '.'))
466: && lequal (UucpChan (), cp + 1))
467: sprintf (tmp, "%.*s!%s",
468: cp - adrxp -> host, adrxp -> host, adrxp -> mbox);
469: else
470: if (lequal (adrxp -> host, UucpChan ()))
471: strcpy (tmp, adrxp -> mbox);
472: else {
473: sprintf (uucp, "%s!", SystemName ());
474: uucplen = strlen (uucp);
475: if (strncmp (uucp, adrxp -> mbox, uucplen))
476: sprintf (tmp, "%s!%s@%s",
477: SystemName (), adrxp -> mbox, adrxp -> host);
478: else
479: sprintf (tmp, "%s@%s", adrxp -> mbox, adrxp -> host);
480: }
481: }
482:
483: strcpy (to, tmp);
484: }
485:
486: /* */
487:
488: static date_convert (from, to)
489: char *from,
490: *to;
491: {
492: char *cp;
493:
494: if ((cp = dctime (dparsetime (from))) != NULL)
495: sprintf (to, "%.24s", cp);
496: else
497: *to = NULL;
498: }
499:
500: /* */
501:
502: static int mmdf_die (error, in1, in2, out, nodelim)
503: int error,
504: nodelim;
505: FILE * in1, *in2, *out;
506: {
507: int i;
508: long clock;
509: char date[LINESIZ];
510:
511: if (nodelim) {
512: fclose (in1);
513: return error;
514: }
515:
516: switch (error) {
517: case MFTXT:
518: putc ('\n', out);
519: break;
520: }
521:
522: time (&clock);
523: sprintf (date, "%.24s", ctime (&clock));
524: fprintf (out, "From %s %s\nSubject: %s %s\n\n",
525: getusr (), date, "Bad MMDF mailbox - error in",
526: error == MFHDR ? "Header" : error == MFTXT ? "Body" : "Mailbox");
527:
528: fprintf (out, "%s: %s\n%s\n--------\n",
529: "Error detected at line", buffer, "Message being processed");
530: fseek (in1, 0L, 0);
531: while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in1)) > 0)
532: fwrite (buffer, sizeof *buffer, i, out);
533: fclose (in1);
534:
535: if (!feof (in2)) {
536: fprintf (out, "--------\n%s\n--------\n%s",
537: "Remainder of unfiltered mailbox follows", tmpbuf);
538: while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in2)) > 0)
539: fwrite (buffer, sizeof *buffer, i, out);
540: }
541:
542: fprintf (out, "--------\n\n");
543: fflush (out);
544:
545: return error;
546: }