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