]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/zotnet/mf/mmdfI/src/uucp/rmail.c
Update XOAUTH2 documentation.
[nmh] / 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 }