]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/zotnet/mf/mmuu.c
Beginning of implementation of new argsplit() function to handle arguments
[nmh] / docs / historical / mh-6.8.5 / zotnet / mf / mmuu.c
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 /* \f */
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
35 static char buffer[BUFSIZ],
36 tmpbuf[BUFSIZ];
37
38 long time ();
39 char *ctime ();
40
41 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
184
185 static 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 NOTOK:
223 close (tmp_fd);
224 fclose (tmp);
225 return MFHDR;
226
227 case OK:
228 continue;
229
230 case DONE:
231 fclose (tmp);
232 break;
233 }
234 break;
235 }
236
237 /* \f */
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 /* \f */
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 /* \f */
312
313 static 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 /* \f */
344
345 switch (hl -> h_type) {
346 case HOTHR:
347 *cp = ':';
348 fprintf (out, "%s\n", bp);
349 break;
350
351 case HDATE:
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 HFROM:
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 HADDR:
380 case HSNDR:
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 /* \f */
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 /* \f */
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 /* \f */
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 }