Annotation of 43BSD/contrib/mh/uip/rmail.c, revision 1.1.1.1

1.1       root        1: /* rmail.c - replacement for /bin/rmail */
                      2: 
                      3: /* This program has a long, long history.  It started as UCB's rmail, and
                      4:    was then modified by OBrien@Rand-Unix to run with MMDF.  Then DpK@Brl
                      5:    re-wrote it, and SmB@Unc hacked it up a bit.  After that
                      6:    MRose.UCI@Rand-Relay upgraded it to use the nifty MF (mail filtering)
                      7:    system.  Finally, the latter stripped it down to work with MH.
                      8: 
                      9:    This program should be used ONLY if you have both "mts mh" and "uucp on"
                     10:    set in your MH configuration.
                     11:  */
                     12: 
                     13: 
                     14: #include "../h/mh.h"
                     15: #include "../h/addrsbr.h"
                     16: #include "../zotnet/mf.h"
                     17: #include "../zotnet/tws.h"
                     18: #include <stdio.h>
                     19: #include "../zotnet/mts.h"
                     20: #include <signal.h>
                     21: 
                     22: 
                     23: #define        ADDROK  0               /* okay to use post to deliver message */
                     24: #define        UUCP    1               /* okay to use uux to deliver message */
                     25: #define        RETURN  2               /* message loses */
                     26: 
                     27: /*  */
                     28: int     pbroke;                        /* broken-pipe flag */
                     29: int     rtnflag;               /* note was sent back */
                     30: 
                     31: char    date[BUFSIZ];          /* date of origination from uucp header */
                     32: char    from[BUFSIZ];          /* accumulated path of sender */
                     33: char    origsys[BUFSIZ];       /* originating system */
                     34: char    origpath[BUFSIZ];      /* path from us to originating system */
                     35: char    usrfrm[BUFSIZ];                /* the 822 version of from[] */
                     36: char    Mailsys[BUFSIZ];       /* address of the mail agent */
                     37: char    overseer[BUFSIZ];      /* address of the watchdog */
                     38: 
                     39: char    mmdf[BUFSIZ];          /* filtered mail file */
                     40: 
                     41: char   *rtnmessage[] = {
                     42:     "  Your message has been intercepted trying to access\n",
                     43:     "a restricted access host (e.g. an ARPANET host).  A copy\n",
                     44:     "of your message has been sent to the system administrators.\n",
                     45:     "The text of your message follows.\n\n",
                     46:     NULL
                     47: };
                     48: 
                     49: char    rtnbegin[] =
                     50:         " ---------------- Returned Mail Follows --------------\n";
                     51: char    rtnend[] =
                     52:         "  --------------- End of Returned Mail ---------------\n";
                     53: 
                     54: char   *oopsmessage[] = {
                     55:     "\n\n\tThe system administrators (%s) have been informed of\n",
                     56:     "the problem, but have not been given a copy of your message.\n\n",
                     57:     NULL
                     58: };
                     59: 
                     60: FILE * fromf;                  /* UUCP "From lines */
                     61: FILE * msgf;                   /* message text */
                     62: FILE * pipef;                  /* output for "post" or "uux" */
                     63: 
                     64: 
                     65: int    pipeser ();
                     66: 
                     67: 
                     68: long    lseek ();
                     69: 
                     70: /*  */
                     71: 
                     72: main (argc, argv)
                     73: int     argc;
                     74: char  **argv;
                     75: {
                     76:     int     cpyback;
                     77:     char   *cp,
                     78:            *fromptr,
                     79:             fromwhom[BUFSIZ],
                     80:             linebuf[BUFSIZ],
                     81:             sys[BUFSIZ];
                     82: 
                     83:     invo_name = r1bindex (*argv, '/');
                     84:     m_foil (NULLCP);
                     85:     mts_init (invo_name);
                     86: 
                     87:     if (argc < 2)
                     88:        adios (NULLCP, "usage: %s user [user ...]", invo_name);
                     89:     (void) umask (0);
                     90:     (void) setgid (1);
                     91:     (void) setuid (1);
                     92: 
                     93:     (void) sprintf (Mailsys, "%s@%s", Mailer, LocalName ());
                     94:     if (Overseer == NULL)
                     95:        Overseer = Mailsys;
                     96:     if (index (Overseer, '@') == NULL) {
                     97:        (void) sprintf (overseer, "%s@%s", Overseer, LocalName ());
                     98:        Overseer = overseer;
                     99:     }
                    100: 
                    101:     (void) mktemp (Errtmp);
                    102:     if (freopen (Errtmp, "w", stderr) == NULL)
                    103:        adios (Errtmp, "unable to create");
                    104:     (void) dup2 (fileno (stderr), fileno (stdout));
                    105: 
                    106:     (void) mktemp (Msgtmp);
                    107:     if ((msgf = fdopen (creat (Msgtmp, Tmpmode), "w")) == NULL)
                    108:        adios (Msgtmp, "unable to create");
                    109: 
                    110:     (void) mktemp (Fromtmp);
                    111:     if ((fromf = fdopen (creat (Fromtmp, Tmpmode), "w")) == NULL)
                    112:        adios (Fromtmp, "unable to create");
                    113: 
                    114: /*  */
                    115: 
                    116:     for (;;) {
                    117:        if (fgets (linebuf, sizeof linebuf, stdin) == NULL)
                    118:            break;
                    119:        if (strncmp (linebuf, "From ", 5)
                    120:                && strncmp (linebuf, ">From ", 6))
                    121:            break;
                    122: 
                    123:        if (linebuf[0] != '>')
                    124:            fputs (">", fromf);
                    125:        fputs (linebuf, fromf);
                    126:        cp = index (linebuf, ' ');
                    127:        fromptr = ++cp;
                    128:        cp = index (cp, ' ');
                    129:        *cp++ = NULL;
                    130:        (void) strcpy (fromwhom, fromptr);
                    131:        (void) strncpy (date, cp, 24);
                    132: 
                    133:        for (;;) {
                    134:            if ((cp = index (cp + 1, 'r')) == NULL) {
                    135:                if ((cp = rindex (fromwhom, '!')) != NULL) {
                    136:                    char   *p;
                    137:                    *cp = NULL;
                    138:                    if ((p = rindex (fromwhom, '!')) != NULL)
                    139:                        (void) strcpy (origsys, p + 1);
                    140:                    else
                    141:                        (void) strcpy (origsys, fromwhom);
                    142:                    (void) strcat (from, fromwhom);
                    143:                    (void) strcat (from, "!");
                    144:                    (void) strcpy (fromwhom, cp + 1);
                    145:                    goto out;
                    146:                }
                    147:                (void) strcpy (sys, SystemName ());
                    148:                (void) strcat (from, sys);
                    149:                (void) strcpy (origsys, sys);
                    150:                (void) strcat (from, "!");
                    151:                goto out;
                    152:            }
                    153:            if (strncmp (cp, "remote from ", 12) == 0)
                    154:                break;
                    155:        }
                    156: 
                    157:        (void) sscanf (cp, "remote from %s", sys);
                    158:        (void) strcat (from, sys);
                    159:        (void) strcpy (origsys, sys);
                    160:        (void) strcat (from, "!");
                    161: out:   ;
                    162:     }
                    163:     if (fromwhom[0] == NULL)
                    164:        adios (NULLCP, "no from line");
                    165: 
                    166: /*  */
                    167: 
                    168:     (void) strcpy (origpath, from);
                    169:     (void) strcat (from, fromwhom);
                    170:     get_mmdf_addr (from, usrfrm);
                    171:     if ((cp = rindex (usrfrm, '<')) != NULL) {
                    172:        (void) strcpy (usrfrm, ++cp);   /* sigh */
                    173:        if ((cp = rindex (usrfrm, '>')) != NULL)
                    174:            *cp = NULL;
                    175:     }
                    176:     if (usrfrm[0] == NULL)
                    177:        (void) sprintf (usrfrm, "%s!%s%%%s@%s%c",
                    178:                SystemName (), from, UucpChan (), LocalName (), NULL);
                    179: 
                    180:     fputs (linebuf, msgf);
                    181:     if (txtcpy (stdin, msgf) == NOTOK)
                    182:        fputs ("\n  *** Problem during receipt from UUCP ***\n", msgf);
                    183: 
                    184:     (void) freopen (Msgtmp, "r", msgf);
                    185:     (void) freopen (Fromtmp, "r", fromf);
                    186:     (void) unlink (Fromtmp);
                    187:     mmdf[0] = NULL;
                    188: 
                    189:     cpyback = 0;
                    190:     for (argv++; --argc > 0;) {
                    191:        rewind (fromf);
                    192:        rewind (msgf);
                    193:        rtnflag = 0;
                    194:        if (deliver (*argv++) == NOTOK && !rtnflag)
                    195:            cpyback++;
                    196:     }
                    197: 
                    198:     (void) fflush (stderr);
                    199:     (void) fflush (stdout);
                    200: 
                    201:     if (cpyback) {
                    202:        rcpy ();
                    203:        zcpy ();
                    204:     }
                    205: 
                    206:     (void) unlink (Msgtmp);
                    207:     if (mmdf[0])
                    208:        (void) unlink (mmdf);
                    209:     (void) unlink (Errtmp);
                    210: 
                    211:     exit (0);
                    212: }
                    213: 
                    214: /*  */
                    215: 
                    216: deliver (to)
                    217: char   *to;
                    218: {
                    219:     int     i,
                    220:             replyval;
                    221:     char    tmpfil[BUFSIZ];
                    222: 
                    223:     switch (adrcheck (to)) {
                    224:        case ADDROK: 
                    225:            if (mmdf[0] == NULL && filter () == NOTOK)
                    226:                (void) strcpy (mmdf, Msgtmp);
                    227:            replyval = xpost (to, mmdf);
                    228:            break;
                    229: 
                    230:        case UUCP: 
                    231:            if ((replyval = xuucp (to)) == NOTOK)
                    232:                break;
                    233: 
                    234:            if ((replyval = txtcpy (fromf, pipef)) != NOTOK)
                    235:                replyval = txtcpy (msgf, pipef);
                    236:            i = (pclose (pipef) >> 8) & 0xff;
                    237:            if (replyval != NOTOK)
                    238:                replyval = (i != 0 ? NOTOK : OK);
                    239:            break;
                    240: 
                    241: /*  */
                    242: 
                    243:        case RETURN: 
                    244:            rtnflag++;
                    245:            switch (adrcheck (from)) {
                    246:                case ADDROK: 
                    247:                case RETURN: 
                    248:                    (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
                    249:                    (void) unlink (mktemp (tmpfil));
                    250:                    if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
                    251:                        return NOTOK;
                    252: 
                    253:                    fprintf (pipef, "Date: %s\nFrom: %s\n",
                    254:                            dtimenow (), Mailsys);
                    255:                    fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer);
                    256:                    rtnmesg (to);
                    257:                    (void) fclose (pipef);
                    258: 
                    259:                    replyval = xpost (from, tmpfil);
                    260:                    (void) unlink (tmpfil);
                    261:                    break;
                    262: 
                    263:                case UUCP: 
                    264:                    if ((replyval = xuucp (from)) == NOTOK)
                    265:                        break;
                    266: 
                    267:                    fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer);
                    268:                    rtnmesg (to);
                    269:                    i = (pclose (pipef) >> 8) & 0xff;
                    270:                    if (replyval != NOTOK)
                    271:                        replyval = (i != 0 ? NOTOK : OK);
                    272:                    break;
                    273:            }
                    274:            if (Syscpy) {
                    275:                (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
                    276:                (void) unlink (mktemp (tmpfil));
                    277:                if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
                    278:                    return NOTOK;
                    279: 
                    280:                fprintf (pipef, "Date: %s\nFrom: %s\n",
                    281:                        dtimenow (), Mailsys);
                    282:                fprintf (pipef, "To: %s\ncc: %s\n", usrfrm, Overseer);
                    283:                rtnmesg (to);
                    284:                (void) fclose (pipef);
                    285: 
                    286:                replyval = xpost (Overseer, tmpfil);
                    287:                (void) unlink (tmpfil);
                    288:            }
                    289:            break;
                    290:     }
                    291: 
                    292:     return replyval;
                    293: }
                    294: 
                    295: /*  */
                    296: 
                    297: adrcheck (adr)
                    298: char   *adr;
                    299: {
                    300:     int     type;
                    301:     char   *cp,
                    302:             host[BUFSIZ];
                    303:     struct mailname *mp;
                    304: 
                    305:     if ((cp = getname (adr)) == NULL)
                    306:        return RETURN;
                    307:     mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP);
                    308:     while (getname (""))
                    309:        continue;
                    310:     if (mp == NULL)
                    311:        return RETURN;
                    312: 
                    313:     type = mp -> m_type;
                    314:     (void) strcpy (host, mp -> m_host);
                    315:     mnfree (mp);
                    316:     if (mp -> m_mbox == NULL)
                    317:        return RETURN;
                    318: 
                    319:     switch (type) {
                    320:        case LOCALHOST: 
                    321:            return ADDROK;
                    322: 
                    323:        case UUCPHOST: 
                    324:            return (strcmp (host, SystemName ()) ? UUCP : ADDROK);
                    325: 
                    326:        default: 
                    327:            if (lookup (origsys, Okhosts) == OK)
                    328:                return ADDROK;
                    329:            return (okhost (host) == NOTOK ? RETURN : ADDROK);
                    330:     }
                    331: }
                    332: 
                    333: /*  */
                    334: 
                    335: okhost (host)
                    336: char   *host;
                    337: {
                    338:     return (lookup (origsys, Okhosts) == OK
                    339:            || lookup (host, Okhosts) == OK
                    340:            || lookup (host, Okdests) == OK ? OK : NOTOK);
                    341: }
                    342: 
                    343: 
                    344: lookup (what, where)
                    345: char   *what,
                    346:        *where;
                    347: {
                    348:     char   *cp,
                    349:             entry[BUFSIZ];
                    350:     FILE * lookf;
                    351: 
                    352:     if ((lookf = fopen (where, "r")) == NULL)
                    353:        return NOTOK;
                    354:     while (fgets (entry, sizeof entry, lookf) != NULL) {
                    355:        cp = entry;
                    356:        while (*cp != '\n' && *cp != ' ' && *cp != '\t')
                    357:            cp++;
                    358:        *cp = NULL;
                    359:        if (uleq (what, entry)) {
                    360:            (void) fclose (lookf);
                    361:            return OK;
                    362:        }
                    363:     }
                    364:     (void) fclose (lookf);
                    365: 
                    366:     return NOTOK;
                    367: }
                    368: 
                    369: 
                    370: /*  */
                    371: 
                    372: rtnmesg (badadr)
                    373: char   *badadr;
                    374: {
                    375:     int     i;
                    376: 
                    377:     fprintf (pipef, "Subject: Illegal Address (%s)\n\n", badadr);
                    378:     for (i = 0; rtnmessage[i]; i++)
                    379:        fputs (rtnmessage[i], pipef);
                    380:     fputs (rtnbegin, pipef);
                    381: 
                    382:     rewind (fromf);
                    383:     (void) txtcpy (fromf, pipef);
                    384:     rewind (msgf);
                    385:     (void) txtcpy (msgf, pipef);
                    386: 
                    387:     fputs (rtnend, pipef);
                    388: }
                    389: 
                    390: 
                    391: txtcpy (frm, to)
                    392: FILE * frm, *to;
                    393: {
                    394:     int     nread;
                    395:     char    buffer[BUFSIZ];
                    396: 
                    397:     while (!pbroke
                    398:            && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0)
                    399:        (void) fwrite (buffer, sizeof (*buffer), nread, to);
                    400: 
                    401:     return (ferror (frm) ? NOTOK : OK);
                    402: }
                    403: 
                    404: /*  */
                    405: 
                    406: xpost (addr, file)
                    407: char   *addr,
                    408:        *file;
                    409: {
                    410:     int     i,
                    411:             child_id;
                    412: 
                    413:     for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
                    414:        sleep (5);
                    415:     switch (child_id) {
                    416:        case NOTOK: 
                    417:            return NOTOK;
                    418: 
                    419:        case OK: 
                    420:            execlp (postproc, r1bindex (postproc, '/'),
                    421:                    "-deliver", addr, file, NULLCP);
                    422:            fprintf (stderr, "unable to exec ");
                    423:            perror (postproc);
                    424:            _exit (1);
                    425: 
                    426:        default: 
                    427:            return (pidwait (child_id, OK) ? NOTOK : OK);
                    428:     }
                    429: }
                    430: 
                    431: /*  */
                    432: 
                    433: xuucp (to)
                    434: char   *to;
                    435: {
                    436:     char   *cp,
                    437:             buffer[BUFSIZ],
                    438:             cmdstr[BUFSIZ];
                    439: 
                    440:     (void) strcpy (buffer, to);
                    441:     if (cp = index (buffer, '!'))
                    442:        *cp++ = NULL;
                    443:     else {
                    444:        fprintf (stderr, "internal error -- %s has no host\n", to);
                    445:        return NOTOK;
                    446:     }
                    447:     (void) sprintf (cmdstr, "uux -p %s!rmail \\(%s\\)", buffer, cp);
                    448: 
                    449:     if ((pipef = popen (cmdstr, "w")) == NULL)
                    450:        return NOTOK;
                    451: 
                    452:     (void) signal (SIGPIPE, pipeser);
                    453:     pbroke = 0;
                    454: 
                    455:     return OK;
                    456: }
                    457: 
                    458: /*  */
                    459: 
                    460: #ifdef BSD42
                    461: /* ARGSUSED */
                    462: #endif BSD42
                    463: 
                    464: static int  pipeser (i)
                    465: int     i;
                    466: {
                    467: #ifndef        BSD42
                    468:     (void) signal (i, SIG_IGN);
                    469: #endif BSD42
                    470: 
                    471:     pbroke = 1;
                    472: }
                    473: 
                    474: /*  */
                    475: 
                    476: rcpy () {
                    477:     int     i;
                    478:     char    buffer[BUFSIZ],
                    479:             tmpfil[BUFSIZ];
                    480:     FILE * fp;
                    481: 
                    482:     (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
                    483:     (void) unlink (mktemp (tmpfil));
                    484:     if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
                    485:        return;
                    486: 
                    487:     fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys);
                    488:     fprintf (pipef, "To: %s\n", usrfrm);
                    489:     fprintf (pipef, "\nProblems sending mail:\n\n");
                    490:     i = 0;
                    491:     if ((fp = fopen (Errtmp, "r")) != NULL) {
                    492:        while (fgets (buffer, sizeof buffer, fp) != NULL) {
                    493:            if (ferror (pipef))
                    494:                break;
                    495:            fputs (buffer, pipef);
                    496:            i++;
                    497:        }
                    498:     }
                    499:     if (i == 0)
                    500:        fprintf (pipef, "\tunknown problem\n");
                    501:     for (i = 0; oopsmessage[i]; i++)
                    502:        fprintf (pipef, oopsmessage[i], Overseer);
                    503:     fputs (rtnbegin, pipef);
                    504: 
                    505:     rewind (fromf);
                    506:     (void) txtcpy (fromf, pipef);
                    507:     rewind (msgf);
                    508:     (void) txtcpy (msgf, pipef);
                    509: 
                    510:     fputs (rtnend, pipef);
                    511:     (void) fclose (pipef);
                    512: 
                    513:     (void) xpost (usrfrm, tmpfil);
                    514:     (void) unlink (tmpfil);
                    515: }
                    516: 
                    517: /*  */
                    518: 
                    519: zcpy () {
                    520:     int     i;
                    521:     char    buffer[BUFSIZ],
                    522:             tmpfil[BUFSIZ];
                    523:     FILE * fp;
                    524: 
                    525:     (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
                    526:     (void) unlink (mktemp (tmpfil));
                    527:     if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
                    528:        return;
                    529: 
                    530:     fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys);
                    531:     fprintf (pipef, "To: %s\n", Mailsys);
                    532:     fprintf (pipef, "\nProblems sending mail for %s (aka %s):\n\n",
                    533:            from, usrfrm);
                    534: 
                    535:     i = 0;
                    536:     if ((fp = fopen (Errtmp, "r")) != NULL) {
                    537:        while (fgets (buffer, sizeof buffer, fp) != NULL) {
                    538:            if (ferror (pipef))
                    539:                break;
                    540:            fputs (buffer, pipef);
                    541:            i = 1;
                    542:        }
                    543:        (void) fclose (fp);
                    544:        if (i == 0)
                    545:            fprintf (pipef, "\tunknown problem\n");
                    546:     }
                    547:     else
                    548:        fprintf (pipef, "\tunable to open %s\n", Errtmp);
                    549:     (void) fclose (pipef);
                    550: 
                    551:     (void) xpost (Mailsys, tmpfil);
                    552:     (void) unlink (tmpfil);
                    553: }
                    554: 
                    555: /*  */
                    556: 
                    557: filter () {
                    558:     int     i,
                    559:             fd,
                    560:             td;
                    561:     char    tmpfil[BUFSIZ],
                    562:             mmdfil[BUFSIZ];
                    563:     FILE * out;
                    564: 
                    565:     (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
                    566:     (void) unlink (mktemp (tmpfil));
                    567:     if ((fd = creat (tmpfil, Tmpmode)) == NOTOK)
                    568:        return NOTOK;
                    569:     (void) close (fd);
                    570:     if ((fd = open (tmpfil, 2)) == NOTOK)
                    571:        return NOTOK;
                    572:     if ((out = fdopen (fd, "w")) == NULL) {
                    573:        (void) close (fd);
                    574:        return NOTOK;
                    575:     }
                    576:     if ((td = dup (fd)) == NOTOK) {
                    577:        (void) close (fd);
                    578:        return NOTOK;
                    579:     }
                    580: 
                    581:     fprintf (out, "From %s %s\n", from, date);
                    582:     if (txtcpy (msgf, out) == NOTOK) {
                    583:        (void) close (fd);
                    584:        (void) close (td);
                    585:        return NOTOK;
                    586:     }
                    587:     (void) fclose (out);
                    588:     (void) lseek (td, 0L, 0);
                    589: 
                    590:     (void) strcpy (mmdfil, "/tmp/mmdfXXXXXX");
                    591:     (void) unlink (mktemp (mmdfil));
                    592:     if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) {
                    593:        (void) close (td);
                    594:        (void) unlink (tmpfil);
                    595:        return NOTOK;
                    596:     }
                    597:     if ((fd = open (mmdfil, 2)) == NOTOK) {
                    598:        (void) close (td);
                    599:        (void) unlink (tmpfil);
                    600:        return NOTOK;
                    601:     }
                    602: 
                    603: /*  */
                    604: 
                    605:     switch (i = uucp2mmdf (td, fd, TRUE)) {
                    606:        case OK: 
                    607:            (void) strcpy (mmdf, mmdfil);
                    608:            break;
                    609: 
                    610:        default: 
                    611:            mmdf[0] = NULL;
                    612:            break;
                    613:     }
                    614:     (void) close (td);
                    615:     (void) unlink (tmpfil);
                    616:     (void) close (fd);
                    617: 
                    618:     return (i != OK ? NOTOK : OK);
                    619: }
                    620: 
                    621: /*  */
                    622: 
                    623: get_mmdf_addr (addr, to)
                    624: char   *addr,
                    625:        *to;
                    626: {
                    627:     struct adrx *adrxp;
                    628: 
                    629:     *to = NULL;
                    630:     if ((adrxp = seekadrx (addr)) == NULL)
                    631:        return;
                    632: 
                    633:     addr_convert (adrxp, to, TRUE);
                    634:     while (seekadrx (NULLCP))
                    635:        continue;
                    636: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.