Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / zotnet / mf / mmdfI / src / uucp / rmail.c
1 #define MFDEBUG                 /* temporarily */
2 #ifndef lint
3 static char Id[] = "@(#)$Id: rmail.c,v 1.2 1993/08/25 17:32:49 jromine Exp $";
4 #endif
5
6 #include "util.h"
7 #include "mmdf.h"
8 #include <pwd.h>
9 #include <signal.h>
10 #include "mf.h"
11 #include "tws.h"
12
13 /*
14  *                              R M A I L . C
15  *
16  *      Developed from the Berkeley mail program of the same name
17  *      by Mike Obrien at RAND to run with the MMDF mail system.
18  *      Rewritten by Doug Kingston, US Army Ballistics Research Laboratory
19  *      Hacked a lot by Steve Bellovin (smb@unc)
20  *
21  *      This program runs SETUID to root so that it can set effective and
22  *      real [ug]ids to mmdflogin.
23  *
24  *    27-Oct-82 Marshall T. Rose <mrose%uci@rand-relay>
25  *              Support proper munging by using the UCI mail filtering
26  *              routines (enabled by #ifdef MF)
27  *              Also use ll_log() package (enabled by #ifdef LOG)
28  *
29  *    17-Oct-83 Marshall T. Rose <mrose%uci@rand-relay>
30  *              New interfacing.  Remove the #ifdef:s
31  */
32
33
34 #define NAMESZ  64      /* Limit on component name size         */
35
36 #define ADDROK  0
37 #define UUCP    1
38 #define RETURN  2
39
40 int     Syscpy = 1;
41 int     Tmpmode = 0600;
42 char   *Fromtmp = "/tmp/rml.f.XXXXXX";
43 char   *Msgtmp = "/tmp/rml.m.XXXXXX";
44 char   *Errtmp = "/tmp/rml.e.XXXXXX";
45 char   *Okhosts = "/usr/mmdf/table/rmail.ok";
46 char   *Okdests = "/usr/mmdf/table/rmail.okdests";
47
48 extern  char    cmddfldir[];
49 extern  char    logdfldir[];
50 extern  char    mmdflogin[];
51 extern  char    pathsubmit[];
52 extern  char    sitesignature[];
53 extern  char    supportaddr[];
54 extern  struct ll_struct chanlog;
55
56 char   *dupfpath (), *index(), *rindex();
57 struct  passwd *getpwnam(), *getpwuid();
58 FILE   *popen();
59
60 /* \f */
61
62 struct ll_struct *logptr = &chanlog;
63
64 FILE *fromf;            /* temporary out for colon-less UUCP "From" lines */
65 FILE *msgf;             /* temporary out for message text */
66 FILE *mmdf;             /* filtered mail file */
67 FILE *pipef;            /* output to "submit" or "uux" */
68 char date[LINESIZE];    /* date of origination from uucp header */
69 char from[LINESIZE];    /* accumulated path of sender */
70 char origsys[NAMESZ];   /* originating system */
71 char origpath[LINESIZE];/* path from us to originating system */
72 char usrfrm[LINESIZE];
73 char Mailsys[LINESIZE];
74 int pbroke;             /* broken-pipe flag */
75 int rtnflag;            /* note was sent back */
76
77 int     brpipe();
78
79 /* \f */
80
81 main(argc, argv)
82 char **argv;
83 {
84         char fromwhom[NAMESZ];          /* user on remote system */
85         char *fromptr;
86         char linebuf[LINESIZE];         /* scratchpad */
87         char sys[NAMESZ];               /* an element in the uucp path */
88         char *cp;
89         struct passwd *pw;
90         int  error;
91         int cpyback;
92
93         if (argc < 2) {
94                 fprintf(stderr, "Usage: rmail user [user ...]\n");
95                 exit(1);
96         }
97         umask (0);
98
99         ll_hdinit (logptr, "RM");
100         logptr -> ll_file = dupfpath (logptr -> ll_file, logdfldir);
101
102         if ((pw = getpwnam (mmdflogin)) == NULL) {
103                 fprintf (stderr, "Cannot find mmdflogin\n");
104                 exit (99);
105         }
106         setgid (pw->pw_gid);
107         setuid (pw->pw_uid);
108
109         sprintf (Mailsys, "%s <%s@%s>",
110             sitesignature, mmdflogin, LocalName ());
111
112 /* \f */
113
114     {                           /* BE VERY SURE... */
115         int     i;
116     
117         for (i = fileno (stdout); i <= HIGHFD; i++)
118             close (i);
119     }
120
121         /* create file to hold stderr output.  We first open some */
122         /* null file to make sure stdout is taken.  If stdin isn't */
123         /* open either, we've got so much trouble it isn't even worth */
124         /* worrying about a little more */
125         open("/dev/null", 0);
126         mktemp(Errtmp);
127         if (freopen(Errtmp, "w", stderr) == NULL) {
128                 fprintf(stderr, "Can't create %s\n", Errtmp);
129                 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
130                         Errtmp);
131                 exit(1);
132         }
133         dup2 (fileno (stderr), fileno (stdout));
134
135         /* Create temp file for rest of message */
136         mktemp (Msgtmp);
137         if ((msgf=fdopen(creat(Msgtmp, Tmpmode), "w")) == NULL) {
138                 fprintf(stderr, "Can't create %s\n", Msgtmp);
139                 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
140                         Msgtmp);
141                 exit(1);
142         }
143
144         /* create temp file for colon-less UUCP "From" lines */
145         mktemp (Fromtmp);
146         if ((fromf=fdopen(creat(Fromtmp, Tmpmode), "w")) == NULL) {
147                 fprintf(stderr, "Can't create %s\n", Fromtmp);
148                 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
149                         Fromtmp);
150                 exit(1);
151         }
152
153 /* \f */
154
155         for (;;) {
156                 if( fgets(linebuf, sizeof linebuf, stdin) == NULL )
157                         break;
158                 if(   strncmp(linebuf, "From ", 5)
159                    && strncmp(linebuf, ">From ", 6) )
160                         break;
161
162                 if (linebuf[0] != '>')
163                         fputs (">", fromf);
164                 fputs(linebuf, fromf);  /* Save, we may forward via UUCP */
165                 cp = index (linebuf, ' ');      /* start of name */
166                 fromptr = ++cp;
167                 cp = index (cp, ' ');           /* cp at end of name */
168                 *cp++ = 0;                      /* term. name, cp at date */
169                 strcpy (fromwhom, fromptr);
170                 strncpy (date, cp, 24);         /* Mon Nov 10 23:12:09 1981 */
171
172                 for (;;) {
173                         cp = index(cp+1, 'r');
174                         if (cp == NULL) {
175                                 cp = rindex(fromwhom, '!');
176                                 if (cp != NULL) {
177                                         char *p;
178                                         *cp = '\0';
179                                         p = rindex(fromwhom, '!');
180                                         if (p != NULL) strcpy(origsys, p+1);
181                                         else strcpy(origsys, fromwhom);
182                                         strcat(from, fromwhom);
183                                         strcat(from, "!");
184                                         strcpy(fromwhom, cp+1);
185                                         goto out;
186                                 }
187                                 strcpy (sys, SystemName ());
188                                 strcat (from, sys);
189                                 strcpy (origsys, sys);
190                                 strcat (from, "!");
191                                 goto out;
192                         }
193                         if (strncmp(cp, "remote from ", 12) == 0)
194                                 break;
195                 }
196
197                 sscanf(cp, "remote from %s", sys);
198                 strcat(from, sys);
199                 strcpy(origsys, sys);           /* Save for quick ref. */
200                 strcat(from, "!");
201 out:;
202         }
203         if( fromwhom[0] == '\0' )               /* No from line, illegal */
204                 exit(99);
205
206 /* \f */
207
208         strcpy (origpath, from);
209         strcat (from, fromwhom);
210         mf_get_addr (from, usrfrm);
211         if ((cp = rindex (usrfrm, '<')) != NULL) {
212             strcpy (usrfrm, ++cp);/* sigh */
213             if ((cp = rindex (usrfrm, '>')) != NULL)
214                 *cp = NULL;
215             }
216         if (usrfrm[0] == NULL)
217             sprintf (usrfrm, "%s!%s%%%s@%s",
218                 SystemName (), from, UucpChan (), LocalName ());
219         ll_log (logptr, LLOGGEN, "Rmail from '%s' (%s)", from, usrfrm);
220         fputs (linebuf, msgf);
221         if (rp_isbad (txtcpy (stdin, msgf)))
222             fputs ("\n  *** Problem during receipt from UUCP ***\n", msgf);
223
224         freopen (Msgtmp, "r", msgf);
225         freopen (Fromtmp, "r", fromf);
226         unlink (Msgtmp);
227         unlink (Fromtmp);
228         mmdf = NULL;
229
230         cpyback = 0;
231         for (argv++; --argc > 0; ) {
232                 rewind (fromf);
233                 rewind (msgf);
234                 if (mmdf != NULL)
235                     rewind (mmdf);
236                 pbroke = 0;
237                 rtnflag = 0;
238                 signal(SIGPIPE, brpipe);
239                 if (rp_isbad(deliver(*argv++)) && !rtnflag)
240                         cpyback++;
241         }
242
243         /* Send back a copy if something nasty happened.  For now, we use */
244         /* a real kludge -- we see if we noted some error, or if we find */
245         /* anything written to stderr....  */
246         fflush(stderr);
247         fflush (stdout);
248
249         if (cpyback) {rcpy();zcpy();}
250
251         unlink(Errtmp);
252         ll_close (logptr);
253         exit (0);
254 }
255
256 /* \f */
257
258 /*
259  *      deliver() -- Handle all deliveries be they returns, automatic
260  *                      copies, or the real thing.  Based on the address
261  *                      the letter is accepted or returned with a copy
262  *                      to the system administrators
263  *
264  *                      main() has set up the "from" string and the
265  *                      "date" string.
266  */
267 char    rtnend[] =
268         "  --------------- End of Returned Mail ---------------\n";
269
270 deliver(to)
271 char *to;
272 {
273         int     replyval;
274         int     i;
275         char    linebuf[LINESIZE];
276         char    tmpbuf[LINESIZE];
277
278         switch (adrcheck (to)) {
279         case ADDROK:
280                 ll_log (logptr, LLOGGEN, "Rmail to '%s' via MMDF", to);
281                 if (rp_isbad (replyval = 
282                         xsubmit (NULL, usrfrm, NULL, NULL, to)))
283                     break;
284                 if (mmdf == NULL)
285                     if (mf_get_msg () == NOTOK)
286                         mmdf = msgf;
287                 replyval = txtcpy (mmdf, pipef);
288 #ifndef RUNALON
289                 i = (pclose(pipef) >> 8 ) & 0xff;
290                 if (rp_isgood(replyval)) replyval = i;
291 #endif
292                 break;
293
294         case UUCP:
295                 ll_log (logptr, LLOGGEN, "Rmail to '%s' via UUCP", to);
296                 if (rp_isbad (replyval = xuucp(from, to)))
297                         break;
298                 replyval = txtcpy(msgf, pipef);
299 #ifndef RUNALON
300                 i = (pclose(pipef) >> 8 ) & 0xff;
301                 if (rp_isgood(replyval)) replyval = (i == 0 ? RP_OK : RP_LIO);
302 #endif
303                 break;
304
305 /* \f */
306
307         case RETURN:
308                 rtnflag = 1;
309                 ll_log (logptr, LLOGGEN, "Illegal Rmail to '%s'", to);
310                 switch (adrcheck (from)) {
311                 case ADDROK:
312                 case RETURN:
313                         replyval = xsubmit (dtimenow (), Mailsys,
314                                         from, supportaddr, from);
315                         rtnmesg(to);
316                         txtcpy(fromf, pipef);
317                         txtcpy(msgf, pipef);
318                         fputs (rtnend, pipef);
319 #ifndef RUNALON
320                         i = (pclose(pipef) >> 8 ) & 0xff;
321                         if (rp_isgood(replyval)) replyval = i;
322 #endif
323                         break;
324
325                 case UUCP:
326                         replyval = xuucp (mmdflogin, from);
327                         if (rp_isbad (replyval))
328                                 break;
329                         fprintf (pipef, "To: %s\n", from);
330                         fprintf (pipef, "Cc: %s\n", supportaddr);
331                         rtnmesg(to);
332                         txtcpy(fromf, pipef);
333                         txtcpy(msgf, pipef);
334                         fputs (rtnend, pipef);
335 #ifndef RUNALON
336                         i = (pclose(pipef) >> 8 ) & 0xff;
337                         if (rp_isgood(replyval))
338                             replyval = (i == 0 ? RP_OK : RP_LIO);
339 #endif
340                         break;
341                 }
342
343                 /* And now for the mail overseer's copy */
344                 if (Syscpy) {
345                         ll_log (logptr, LLOGGEN, "Notifying %s", supportaddr);
346                         rewind (fromf);
347                         rewind (msgf);
348
349                         replyval = xsubmit (dtimenow (), Mailsys,
350                                         usrfrm, supportaddr, supportaddr);
351                         if (rp_isbad (replyval))
352                                 break;
353                         rtnmesg(to);
354                         txtcpy (fromf, pipef);
355                         txtcpy (msgf, pipef);
356                         fputs (rtnend, pipef);
357 #ifndef RUNALON
358                         i = (pclose(pipef) >> 8 ) & 0xff;
359                         if (rp_isgood(replyval)) replyval = i;
360 #endif
361                 }
362         }
363         return (replyval);
364 }
365
366 /* \f */
367
368 adrcheck (adr)                             /* Gateway to Arpanet? */
369 char *adr;
370 {
371     char   *cp,
372             err[BUFSIZ],
373             host[BUFSIZ],
374             mbox[BUFSIZ];
375     struct adrx *adrxp;
376
377     if ((adrxp = seekadrx (adr)) == NULL)
378         return RETURN;
379     strcpy (err, adrxp -> err ? adrxp -> err : "");
380     strcpy (host, adrxp -> host ? adrxp -> host : "");
381     strcpy (mbox, adrxp -> mbox ? adrxp -> mbox : "");
382     while (seekadrx (NULL))
383         continue;
384
385     if (err[0] || mbox[0] == NULL)
386         return RETURN;
387     if (index (mbox, '!') || host[0] == NULL)
388         return UUCP;
389     if (rp_isgood (lookup (origsys, Okhosts)))
390         return ADDROK;
391     if (index (host, '@') || rp_isbad (okhost (host)))
392         return RETURN;
393
394     return ADDROK;
395 }
396
397
398 okhost(host)             /* Host permitted to use mail facilities? */
399 char *host;
400 {
401         if (rp_isgood (lookup (origsys, Okhosts)))
402                 return (RP_OK);         /* Fully privledged originator */
403         if (rp_isgood (lookup (host, Okhosts)))
404                 return (RP_OK);         /* Fully privledged dest */
405         if (rp_isgood (lookup (host, Okdests)))
406                 return (RP_OK);         /* Unrestricted Dest. Host, OK */
407         return(RP_NO);                  /* Not permitted; must be bad */
408 }
409
410 /* \f */
411
412 /*
413  *      lookup()  --    This lookup function looks for strings which
414  *                      must be the first string on a line.  Sorry Dave (dhc)
415  *                      but the MMDF channel functions are too specific
416  *                      to be easily used here without much kludging.
417  */
418
419 /*****************************************
420 ****    Can this be a call to a MMDF function??
421 ****    Remember I have the RHOSTs table and the OKHOSTS table.
422 ******************************************/
423
424 lookup (what, where)
425 char *what, *where;
426 {
427         FILE *lookf;
428         char entry[LINESIZE];
429         char *cp;
430
431         if ((lookf = fopen (where, "r")) == NULL)
432                 return (RP_NO);         /* Unknown problem */
433         while (fgets (entry, sizeof entry, lookf) != NULL) {
434                 cp = entry;
435                 while (*cp != '\n' && *cp != ' ' && *cp != '\t')
436                         cp++;
437                 *cp = 0;
438                 if (lexequ (what, entry)) {
439                         fclose (lookf);
440                         return (RP_OK);
441                 }
442         }
443         fclose (lookf);
444         return (RP_NO);
445 }
446
447
448 /* \f */
449
450 char *rtnmessage[] = {
451         "       Your message has been intercepted trying to access\n",
452         "a restricted access host (e.g. an ARPANET host).  A copy\n",
453         "of your message has been sent to the system administrators.\n",
454         "The text of your message follows.\n\n",
455         "  --------------- Returned Mail Follows --------------\n",
456         0
457 };
458
459 rtnmesg (badadr)
460 char *badadr;
461 {
462         char **cpp;
463
464         fprintf (pipef, "Subject:  Illegal Address (%s)\n\n", badadr);
465         for (cpp = rtnmessage; *cpp; cpp++)
466                 fputs (*cpp, pipef);
467 }
468
469 txtcpy (frm, to)
470 FILE *frm, *to;
471 {
472         char buffer[BUFSIZ];
473         int nread;
474
475         while (!pbroke && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0)
476                 fwrite (buffer, sizeof (*buffer), nread, to);
477         return (ferror (frm) ? RP_LIO : RP_OK );
478 }
479
480 /* \f */
481
482 xsubmit (date, from, to, cc, realto)
483 char *date, *from, *to, *cc, *realto;
484 {
485     char    cmdstr[LINESIZE],
486             submit[LINESIZE];
487
488     getfpath (pathsubmit, cmddfldir, submit);
489     sprintf (cmdstr, "%s '-mlti%s*'", submit, UucpChan ());
490
491 #ifndef RUNALON
492     if ((pipef = popen (cmdstr, "w")) == NULL)
493         return (RP_NO);
494 #else
495     pipef = stdout;
496     printf ("%s\n", cmdstr);
497 #endif
498
499     fprintf (pipef, "%s\n%s\n!\n", from, realto);
500
501     if (date) {
502         fprintf (pipef, "Date:     %s\n", date);
503         fprintf (pipef, "From:     %s\n", from);
504     }
505     if (to) {
506         fprintf (pipef, "To:       %s", to);
507         if (index (to, '@'))
508             fputc ('\n', pipef);/* Explicit host specified */
509         else
510             fprintf (pipef, "@%s\n", LocalName ());
511     }
512     if (cc) {
513         fprintf (pipef, "Cc:       %s\n", cc);
514     }
515
516     return (RP_OK);
517 }
518
519 /* \f */
520
521 xuucp (from, to)
522 char *from, *to;
523 {
524         char    cmdstr[LINESIZE];
525
526         sprintf (cmdstr, "/etc/delivermail -r%s -ep -m -s -i %s", from, to);
527
528 #ifndef RUNALON
529         if ((pipef = popen (cmdstr, "w")) == NULL)
530                 return (RP_NO);
531 #else
532         pipef = stdout;
533         printf ("%s\n", cmdstr);
534 #endif
535
536         return (RP_OK);
537 }
538
539 /* \f */
540
541 brpipe()        /* catch broken-pipe signals */
542 {
543         signal(SIGPIPE, SIG_IGN);
544         pbroke = 1;
545 }
546
547 char *oopsmessage[] = {
548     "\n\n\tThe system administrators (%s) have been informed of the\n",
549     "problem, but have not been given a copy of your message.\n",
550     NULL
551 };
552
553 /* \f */
554
555 rcpy () {
556     int     i;
557     char    buffer[BUFSIZ],
558             message[BUFSIZ];
559     FILE * fp;
560
561     ll_log (logptr, LLOGGEN, "Advising %s of failure as %s...", from, usrfrm);
562
563     sprintf (buffer, "Problems sending mail:\n\n");
564     if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", usrfrm)
565             != OK)
566         goto ml_err;
567     ml_txt (buffer);
568
569     if ((fp = fopen (Errtmp, "r")) != NULL) {
570         ml_file (fp);
571         if (ftell (fp) == 0L)
572             fprintf (pipef, "\tunknown problem\n");
573         fclose (fp);
574     }
575     else
576         ml_txt ("\tunknown problem\n");
577
578     for (i = 0; oopsmessage[i]; i++) {
579         sprintf (message, oopsmessage[i], supportaddr);
580         ml_txt (message);
581     }
582     fprintf (pipef, "\n\nReturned message follows:\n\n---------------\n\n");
583     rewind (fromf);
584     ml_file (fromf);
585     rewind (msgf);
586     ml_file (msgf);
587
588     if (ml_end (OK) != OK) {
589         char   *cp;
590
591 ml_err: ;
592         if (cp = index (buffer, '\n'))
593             *cp = NULL;
594         ll_log (logptr, LLOGFAT, "Unable to post failure notice");
595         ll_log (logptr, LLOGFAT, "info: %s", buffer);
596     }
597 }
598
599 /* \f */
600
601 zcpy () {
602     char    buffer[BUFSIZ];
603     FILE * fp;
604
605     ll_log (logptr, LLOGGEN, "Advising %s of failure...", supportaddr);
606
607     sprintf (buffer, "Problems sending mail for %s (aka %s):\n\n",
608             from, usrfrm);
609     if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", supportaddr)
610             != OK)
611         goto ml_err;
612     ml_txt (buffer);
613
614     if ((fp = fopen (Errtmp, "r")) != NULL) {
615         ml_file (fp);
616         if (ftell (fp) == 0L)
617             fprintf (pipef, "\tunknown problem\n");
618         fclose (fp);
619     }
620     else
621         ml_txt ("\tunable to open error file\n");
622
623     if (ml_end (OK) != OK) {
624         char   *cp;
625
626 ml_err: ;
627         if (cp = index (buffer, '\n'))
628             *cp = NULL;
629         ll_log (logptr, LLOGFAT, "Unable to post failure notice");
630         ll_log (logptr, LLOGFAT, "info: %s", buffer);
631     }
632 }
633
634 /* \f */
635
636 mf_get_msg () {
637     int     i,
638             fd,
639             md,
640             td;
641     char    buffer[BUFSIZ],
642             tmpfil[LINESIZE],
643             mmdfil[LINESIZE];
644 #ifdef  MFDEBUG
645     FILE * fp;
646 #endif  MFDEBUG
647     FILE * out;
648
649     strcpy (tmpfil, "/tmp/rmailXXXXXX");
650     unlink (mktemp (tmpfil));
651     if ((fd = creat (tmpfil, Tmpmode)) == NOTOK)
652         return NOTOK;
653     close (fd);
654     if ((fd = open (tmpfil, 2)) == NOTOK)
655         return NOTOK;
656     if ((out = fdopen (fd, "w")) == NULL) {
657         close (fd);
658         return NOTOK;
659     }
660     if ((td = dup (fd)) == NOTOK) {
661         close (fd);
662         return NOTOK;
663     }
664
665     fprintf (out, "From %s %s\n", from, date);
666     if (rp_isbad (txtcpy (msgf, out))) {
667         close (fd);
668         close (td);
669         return NOTOK;
670     }
671     fclose (out);
672     lseek (td, (off_t)0, 0);
673
674     strcpy (mmdfil, "/tmp/mmdfXXXXXX");
675     unlink (mktemp (mmdfil));
676     if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) {
677         close (td);
678         unlink (tmpfil);
679         return NOTOK;
680     }
681     if ((fd = open (mmdfil, 2)) == NOTOK) {
682         close (td);
683         unlink (tmpfil);
684         return NOTOK;
685     }
686     if ((md = dup (fd)) == NOTOK) {
687         close (td);
688         unlink (tmpfil);
689         close (fd);
690         return NOTOK;
691     }
692
693 /* \f */
694
695     switch (i = uucp_to_mmdf (td, fd, TRUE)) {
696         case OK: 
697             lseek (md, (off_t)0, 0);
698             if ((mmdf = fdopen (md, "r")) != NULL)
699                 break;
700
701         default: 
702             close (md);
703
704             sprintf (buffer, "rmail(%d) filtering failed(%d)\n",
705                     getpid (), i);
706             if (ml_1adr (NO, NO, sitesignature, "MF Failure", supportaddr)
707                     != OK)
708                 goto ml_err;
709             ml_txt (buffer);
710 #ifdef  MFDEBUG
711             lseek (td, (off_t)0, 0);
712             if ((md = dup (td)) == NOTOK)
713                 ml_txt ("unable to dup() descriptor for message copy\n");
714             else
715                 if ((fp = fdopen (md, "r")) == NULL) {
716                     ml_txt ("unable to fdopen() descriptor for message copy\n");
717                     close (md);
718                 }
719                 else {
720                     ml_txt ("\n  --Message Follows--\n");
721                     ml_file (fp);
722                     fclose (fp);
723                 }
724 #endif  MFDEBUG
725             if (ml_end (OK) != OK) {
726                 char   *cp;
727
728         ml_err: ;
729                 if (cp = index (buffer, '\n'))
730                     *cp = NULL;
731                 ll_log (logptr, LLOGFAT, "Unable to post failure notice");
732                 ll_log (logptr, LLOGFAT, "info: %s", buffer);
733             }
734
735             md = NOTOK;
736             break;
737     }
738     close (td);
739     unlink (tmpfil);
740     close (fd);
741     unlink (mmdfil);
742
743     return md;
744 }
745
746 /* \f */
747
748 mf_get_addr (from, to)
749 char *from,
750      *to;
751 {
752     struct adrx *adrxp,
753                *seekadrx ();
754
755     *to = NULL;
756     if ((adrxp = seekadrx (from)) == NULL)
757         return;
758     addr_convert (adrxp, to, TRUE);
759     while (seekadrx (NULL))
760         continue;
761     return;
762 }