Annotation of 40BSD/cmd/ucbmail/optim.c, revision 1.1

1.1     ! root        1: #
        !             2: 
        !             3: /*
        !             4:  * Mail -- a program for sending and receiving mail.
        !             5:  *
        !             6:  * Network name modification routines.
        !             7:  */
        !             8: 
        !             9: #include "rcv.h"
        !            10: #include <ctype.h>
        !            11: 
        !            12: /*
        !            13:  * Map a name into the correct network "view" of the
        !            14:  * name.  This is done by prepending the name with the
        !            15:  * network address of the sender, then optimizing away
        !            16:  * nonsense.
        !            17:  */
        !            18: 
        !            19: char   *metanet = "!^:%@.";
        !            20: 
        !            21: char *
        !            22: netmap(name, from)
        !            23:        char name[], from[];
        !            24: {
        !            25:        char nbuf[BUFSIZ], ret[BUFSIZ];
        !            26:        register char *cp;
        !            27: 
        !            28:        if (strlen(from) == 0)
        !            29:                return(name);
        !            30:        if (any('@', name) || any('%', name))
        !            31:                return(arpafix(name, from));
        !            32:        cp = revarpa(from);
        !            33:        if (cp == NOSTR)
        !            34:                return(name);
        !            35:        strcpy(nbuf, cp);
        !            36:        cp = &nbuf[strlen(nbuf) - 1];
        !            37:        while (!any(*cp, metanet) && cp > nbuf)
        !            38:                cp--;
        !            39:        if (cp == nbuf)
        !            40:                return(name);
        !            41:        *++cp = 0;
        !            42:        strcat(nbuf, revarpa(name));
        !            43:        optim(nbuf, ret);
        !            44:        cp = revarpa(ret);
        !            45:        if (!icequal(name, cp))
        !            46:                return((char *) savestr(cp));
        !            47:        return(name);
        !            48: }
        !            49: 
        !            50: /*
        !            51:  * Rename the given network path to use
        !            52:  * the kinds of names that we would right here.
        !            53:  */
        !            54: 
        !            55: char *
        !            56: rename(str)
        !            57:        char str[];
        !            58: {
        !            59:        register char *cp, *cp2;
        !            60:        char buf[BUFSIZ], path[BUFSIZ];
        !            61:        register int c, host;
        !            62: 
        !            63:        strcpy(path, "");
        !            64:        for (;;) {
        !            65:                if ((c = *cp++) == 0)
        !            66:                        break;
        !            67:                cp2 = buf;
        !            68:                while (!any(c, metanet) && c != 0) {
        !            69:                        *cp2++ = c;
        !            70:                        c = *cp++;
        !            71:                }
        !            72:                *cp2 = 0;
        !            73:                if (c == 0) {
        !            74:                        strcat(path, buf);
        !            75:                        break;
        !            76:                }
        !            77:                host = netlook(buf, ntype(c));
        !            78:                strcat(path, netname(host));
        !            79:                stradd(path, c);
        !            80:        }
        !            81:        if (strcmp(str, path) != 0)
        !            82:                return(savestr(path));
        !            83:        return(str);
        !            84: }
        !            85: /*
        !            86:  * Turn a network machine name into a unique character
        !            87:  * + give connection-to status.  BN -- connected to Bell Net.
        !            88:  * AN -- connected to ARPA net, SN -- connected to Schmidt net.
        !            89:  * CN -- connected to COCANET.
        !            90:  */
        !            91: 
        !            92: #define        AN      1                       /* Connected to ARPA net */
        !            93: #define        BN      2                       /* Connected to BTL net */
        !            94: #define        CN      4                       /* Connected to COCANET */
        !            95: #define        SN      8                       /* Connected to Schmidt net */
        !            96: 
        !            97: struct netmach {
        !            98:        char    *nt_machine;
        !            99:        char    nt_mid;
        !           100:        short   nt_type;
        !           101: } netmach[] = {
        !           102:        "a",            'a',            SN,
        !           103:        "b",            'b',            SN,
        !           104:        "c",            'c',            SN,
        !           105:        "d",            'd',            SN,
        !           106:        "e",            'e',            SN,
        !           107:        "f",            'f',            SN,
        !           108:        "g",            'g',            SN,
        !           109:        "ingres",       'i',            AN|SN,
        !           110:        "ing70",        'i',            AN|SN,
        !           111:        "berkeley",     'i',            AN|SN,
        !           112:        "ingvax",       'j',            SN,
        !           113:        "virus",        'k',            SN,
        !           114:        "vlsi",         'l',            SN,
        !           115:        "image",        'm',            SN,
        !           116:        "esvax",        'o',            SN,
        !           117:        "sesm",         'o',            SN,
        !           118:        "q",            'q',            SN,
        !           119:        "research",     'R',            BN,
        !           120:        "arpavax",      'r',            SN,
        !           121:        "src",          's',            SN,
        !           122:        "mathstat",     't',            SN,
        !           123:        "csvax",        'v',            BN|SN,
        !           124:        "vax",          'v',            BN|SN,
        !           125:        "ucb",          'v',            BN|SN,
        !           126:        "ucbvax",       'v',            BN|SN,
        !           127:        "vax135",       'x',            BN,
        !           128:        "cory",         'y',            SN,
        !           129:        "eecs40",       'z',            SN,
        !           130:        0,              0,              0
        !           131: };
        !           132: 
        !           133: netlook(machine, attnet)
        !           134:        char machine[];
        !           135: {
        !           136:        register struct netmach *np;
        !           137:        register char *cp, *cp2;
        !           138:        char nbuf[20];
        !           139: 
        !           140:        /*
        !           141:         * Make into lower case.
        !           142:         */
        !           143: 
        !           144:        for (cp = machine, cp2 = nbuf; *cp; *cp2++ = little(*cp++))
        !           145:                ;
        !           146:        *cp2 = 0;
        !           147: 
        !           148:        /*
        !           149:         * If a single letter machine, look through those first.
        !           150:         */
        !           151: 
        !           152:        if (strlen(nbuf) == 1)
        !           153:                for (np = netmach; np->nt_mid != 0; np++)
        !           154:                        if (np->nt_mid == nbuf[0])
        !           155:                                return(nbuf[0]);
        !           156: 
        !           157:        /*
        !           158:         * Look for usual name
        !           159:         */
        !           160: 
        !           161:        for (np = netmach; np->nt_mid != 0; np++)
        !           162:                if (strcmp(np->nt_machine, nbuf) == 0)
        !           163:                        return(np->nt_mid);
        !           164: 
        !           165:        /*
        !           166:         * Look in side hash table.
        !           167:         */
        !           168: 
        !           169:        return(mstash(nbuf, attnet));
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Make a little character.
        !           174:  */
        !           175: 
        !           176: little(c)
        !           177:        register int c;
        !           178: {
        !           179: 
        !           180:        if (c >= 'A' && c <= 'Z')
        !           181:                c += 'a' - 'A';
        !           182:        return(c);
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Turn a network unique character identifier into a network name.
        !           187:  */
        !           188: 
        !           189: char *
        !           190: netname(mid)
        !           191: {
        !           192:        register struct netmach *np;
        !           193:        char *mlook();
        !           194: 
        !           195:        if (mid & 0200)
        !           196:                return(mlook(mid));
        !           197:        for (np = netmach; np->nt_mid != 0; np++)
        !           198:                if (np->nt_mid == mid)
        !           199:                        return(np->nt_machine);
        !           200:        return(NOSTR);
        !           201: }
        !           202: 
        !           203: /*
        !           204:  * Deal with arpa net addresses.  The way this is done is strange.
        !           205:  * In particular, if the destination arpa net host is not Berkeley,
        !           206:  * then the address is correct as stands.  Otherwise, we strip off
        !           207:  * the trailing @Berkeley, then cook up a phony person for it to
        !           208:  * be from and optimize the result.
        !           209:  */
        !           210: char *
        !           211: arpafix(name, from)
        !           212:        char name[];
        !           213:        char from[];
        !           214: {
        !           215:        register char *cp;
        !           216:        register int arpamach;
        !           217:        char newname[BUFSIZ];
        !           218:        char fake[5];
        !           219:        char fakepath[20];
        !           220: 
        !           221:        if (debug) {
        !           222:                fprintf(stderr, "arpafix(%s, %s)\n", name, from);
        !           223:        }
        !           224:        cp = rindex(name, '@');
        !           225:        if (cp == NOSTR)
        !           226:                cp = rindex(name, '%');
        !           227:        if (cp == NOSTR) {
        !           228:                fprintf(stderr, "Somethings amiss -- no @ or % in arpafix\n");
        !           229:                return(name);
        !           230:        }
        !           231:        cp++;
        !           232:        arpamach = netlook(cp, '@');
        !           233:        if (arpamach == 0) {
        !           234:                if (debug)
        !           235:                        fprintf(stderr, "machine %s unknown, uses: %s\n", cp, name);
        !           236:                return(name);
        !           237:        }
        !           238:        if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) {
        !           239:                if (debug)
        !           240:                        fprintf(stderr, "machine %s known but remote, uses: %s\n",
        !           241:                            cp, name);
        !           242:                return(name);
        !           243:        }
        !           244:        strcpy(newname, name);
        !           245:        cp = rindex(newname, '@');
        !           246:        if (cp == NOSTR)
        !           247:                cp = rindex(newname, '%');
        !           248:        *cp = 0;
        !           249:        fake[0] = arpamach;
        !           250:        fake[1] = ':';
        !           251:        fake[2] = LOCAL;
        !           252:        fake[3] = ':';
        !           253:        fake[4] = 0;
        !           254:        prefer(fake);
        !           255:        strcpy(fakepath, netname(fake[0]));
        !           256:        stradd(fakepath, fake[1]);
        !           257:        strcat(fakepath, "daemon");
        !           258:        if (debug)
        !           259:                fprintf(stderr, "machine local, call netmap(%s, %s)\n",
        !           260:                    newname, fakepath);
        !           261:        return(netmap(newname, fakepath));
        !           262: }
        !           263: 
        !           264: /*
        !           265:  * Take a network machine descriptor and find the types of connected
        !           266:  * nets and return it.
        !           267:  */
        !           268: 
        !           269: nettype(mid)
        !           270: {
        !           271:        register struct netmach *np;
        !           272: 
        !           273:        if (mid & 0200)
        !           274:                return(mtype(mid));
        !           275:        for (np = netmach; np->nt_mid != 0; np++)
        !           276:                if (np->nt_mid == mid)
        !           277:                        return(np->nt_type);
        !           278:        return(0);
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * Hashing routines to salt away machines seen scanning
        !           283:  * networks paths that we don't know about.
        !           284:  */
        !           285: 
        !           286: #define        XHSIZE          19              /* Size of extra hash table */
        !           287: #define        NXMID           (XHSIZE*3/4)    /* Max extra machines */
        !           288: 
        !           289: struct xtrahash {
        !           290:        char    *xh_name;               /* Name of machine */
        !           291:        short   xh_mid;                 /* Machine ID */
        !           292:        short   xh_attnet;              /* Attached networks */
        !           293: } xtrahash[XHSIZE];
        !           294: 
        !           295: struct xtrahash        *xtab[XHSIZE];          /* F: mid-->machine name */
        !           296: 
        !           297: short  midfree;                        /* Next free machine id */
        !           298: 
        !           299: /*
        !           300:  * Initialize the extra host hash table.
        !           301:  * Called by sreset.
        !           302:  */
        !           303: 
        !           304: minit()
        !           305: {
        !           306:        register struct xtrahash *xp, **tp;
        !           307:        register int i;
        !           308: 
        !           309:        midfree = 0;
        !           310:        tp = &xtab[0];
        !           311:        for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) {
        !           312:                xp->xh_name = NOSTR;
        !           313:                xp->xh_mid = 0;
        !           314:                xp->xh_attnet = 0;
        !           315:                *tp++ = (struct xtrahash *) 0;
        !           316:        }
        !           317: }
        !           318: 
        !           319: /*
        !           320:  * Stash a net name in the extra host hash table.
        !           321:  * If a new entry is put in the hash table, deduce what
        !           322:  * net the machine is attached to from the net character.
        !           323:  *
        !           324:  * If the machine is already known, add the given attached
        !           325:  * net to those already known.
        !           326:  */
        !           327: 
        !           328: mstash(name, attnet)
        !           329:        char name[];
        !           330: {
        !           331:        register struct xtrahash *xp;
        !           332:        struct xtrahash *xlocate();
        !           333: 
        !           334:        xp = xlocate(name);
        !           335:        if (xp == (struct xtrahash *) 0) {
        !           336:                printf("Ran out of machine id spots\n");
        !           337:                return(0);
        !           338:        }
        !           339:        if (xp->xh_name == NOSTR) {
        !           340:                if (midfree >= XHSIZE) {
        !           341:                        printf("Out of machine ids\n");
        !           342:                        return(0);
        !           343:                }
        !           344:                xtab[midfree] = xp;
        !           345:                xp->xh_name = savestr(name);
        !           346:                xp->xh_mid = 0200 + midfree++;
        !           347:        }
        !           348:        switch (attnet) {
        !           349:        case '!':
        !           350:        case '^':
        !           351:                xp->xh_attnet |= BN;
        !           352:                break;
        !           353: 
        !           354:        default:
        !           355:        case ':':
        !           356:                xp->xh_attnet |= SN;
        !           357:                break;
        !           358: 
        !           359:        case '@':
        !           360:        case '%':
        !           361:                xp->xh_attnet |= AN;
        !           362:                break;
        !           363:        }
        !           364:        return(xp->xh_mid);
        !           365: }
        !           366: 
        !           367: /*
        !           368:  * Search for the given name in the hash table
        !           369:  * and return the pointer to it if found, or to the first
        !           370:  * empty slot if not found.
        !           371:  *
        !           372:  * If no free slots can be found, return 0.
        !           373:  */
        !           374: 
        !           375: struct xtrahash *
        !           376: xlocate(name)
        !           377:        char name[];
        !           378: {
        !           379:        register int h, q, i;
        !           380:        register char *cp;
        !           381:        register struct xtrahash *xp;
        !           382: 
        !           383:        for (h = 0, cp = name; *cp; h = (h << 2) + *cp++)
        !           384:                ;
        !           385:        if (h < 0 && (h = -h) < 0)
        !           386:                h = 0;
        !           387:        h = h % XHSIZE;
        !           388:        cp = name;
        !           389:        for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
        !           390:                xp = &xtrahash[(h + q) % XHSIZE];
        !           391:                if (xp->xh_name == NOSTR)
        !           392:                        return(xp);
        !           393:                if (strcmp(cp, xp->xh_name) == 0)
        !           394:                        return(xp);
        !           395:                if (h - q < 0)
        !           396:                        q += XHSIZE;
        !           397:                xp = &xtrahash[(h - q) % XHSIZE];
        !           398:                if (xp->xh_name == NOSTR)
        !           399:                        return(xp);
        !           400:                if (strcmp(cp, xp->xh_name) == 0)
        !           401:                        return(xp);
        !           402:        }
        !           403:        return((struct xtrahash *) 0);
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Return the name from the extra host hash table corresponding
        !           408:  * to the passed machine id.
        !           409:  */
        !           410: 
        !           411: char *
        !           412: mlook(mid)
        !           413: {
        !           414:        register int m;
        !           415: 
        !           416:        if ((mid & 0200) == 0)
        !           417:                return(NOSTR);
        !           418:        m = mid & 0177;
        !           419:        if (m >= midfree) {
        !           420:                printf("Use made of undefined machine id\n");
        !           421:                return(NOSTR);
        !           422:        }
        !           423:        return(xtab[m]->xh_name);
        !           424: }
        !           425: 
        !           426: /*
        !           427:  * Return the bit mask of net's that the given extra host machine
        !           428:  * id has so far.
        !           429:  */
        !           430: 
        !           431: mtype(mid)
        !           432: {
        !           433:        register int m;
        !           434: 
        !           435:        if ((mid & 0200) == 0)
        !           436:                return(0);
        !           437:        m = mid & 0177;
        !           438:        if (m >= midfree) {
        !           439:                printf("Use made of undefined machine id\n");
        !           440:                return(0);
        !           441:        }
        !           442:        return(xtab[m]->xh_attnet);
        !           443: }
        !           444: 
        !           445: /*
        !           446:  * Take a network name and optimize it.  This gloriously messy
        !           447:  * opertions takes place as follows:  the name with machine names
        !           448:  * in it is tokenized by mapping each machine name into a single
        !           449:  * character machine id (netlook).  The separator characters (network
        !           450:  * metacharacters) are left intact.  The last component of the network
        !           451:  * name is stripped off and assumed to be the destination user name --
        !           452:  * it does not participate in the optimization.  As an example, the
        !           453:  * name "research!vax135!research!ucbvax!bill" becomes, tokenized,
        !           454:  * "r!x!r!v!" and "bill"  A low level routine, optim1, fixes up the
        !           455:  * network part (eg, "r!x!r!v!"), then we convert back to network
        !           456:  * machine names and tack the user name on the end.
        !           457:  *
        !           458:  * The result of this is copied into the parameter "name"
        !           459:  */
        !           460: 
        !           461: optim(net, name)
        !           462:        char net[], name[];
        !           463: {
        !           464:        char netcomp[BUFSIZ], netstr[40], xfstr[40];
        !           465:        register char *cp, *cp2;
        !           466:        register int c;
        !           467: 
        !           468:        strcpy(netstr, "");
        !           469:        cp = net;
        !           470:        for (;;) {
        !           471:                /*
        !           472:                 * Rip off next path component into netcomp
        !           473:                 */
        !           474:                cp2 = netcomp;
        !           475:                while (*cp && !any(*cp, metanet))
        !           476:                        *cp2++ = *cp++;
        !           477:                *cp2 = 0;
        !           478:                /*
        !           479:                 * If we hit null byte, then we just scanned
        !           480:                 * the destination user name.  Go off and optimize
        !           481:                 * if its so.
        !           482:                 */
        !           483:                if (*cp == 0)
        !           484:                        break;
        !           485:                if ((c = netlook(netcomp, *cp)) == 0) {
        !           486:                        printf("No host named \"%s\"\n", netcomp);
        !           487: err:
        !           488:                        strcpy(name, net);
        !           489:                        return;
        !           490:                }
        !           491:                stradd(netstr, c);
        !           492:                stradd(netstr, *cp++);
        !           493:                /*
        !           494:                 * If multiple network separators given,
        !           495:                 * throw away the extras.
        !           496:                 */
        !           497:                while (any(*cp, metanet))
        !           498:                        cp++;
        !           499:        }
        !           500:        if (strlen(netcomp) == 0) {
        !           501:                printf("net name syntax\n");
        !           502:                goto err;
        !           503:        }
        !           504:        optim1(netstr, xfstr);
        !           505: 
        !           506:        /*
        !           507:         * Convert back to machine names.
        !           508:         */
        !           509: 
        !           510:        cp = xfstr;
        !           511:        strcpy(name, "");
        !           512:        while (*cp) {
        !           513:                if ((cp2 = netname(*cp++)) == NOSTR) {
        !           514:                        printf("Made up bad net name\n");
        !           515:                        goto err;
        !           516:                }
        !           517:                strcat(name, cp2);
        !           518:                stradd(name, *cp++);
        !           519:        }
        !           520:        strcat(name, netcomp);
        !           521: }
        !           522: 
        !           523: /*
        !           524:  * Take a string of network machine id's and separators and
        !           525:  * optimize them.  We process these by pulling off maximal
        !           526:  * leading strings of the same type, passing these to the appropriate
        !           527:  * optimizer and concatenating the results.
        !           528:  */
        !           529: 
        !           530: #define        IMPLICIT        1
        !           531: #define        EXPLICIT        2
        !           532: 
        !           533: optim1(netstr, name)
        !           534:        char netstr[], name[];
        !           535: {
        !           536:        char path[40], rpath[40];
        !           537:        register char *cp, *cp2;
        !           538:        register int tp, nc;
        !           539: 
        !           540:        cp = netstr;
        !           541:        prefer(cp);
        !           542:        strcpy(name, "");
        !           543:        while (*cp != 0) {
        !           544:                strcpy(path, "");
        !           545:                tp = ntype(cp[1]);
        !           546:                nc = cp[1];
        !           547:                while (*cp && tp == ntype(cp[1])) {
        !           548:                        stradd(path, *cp++);
        !           549:                        cp++;
        !           550:                }
        !           551:                switch (netkind(tp)) {
        !           552:                default:
        !           553:                        strcpy(rpath, path);
        !           554:                        break;
        !           555: 
        !           556:                case IMPLICIT:
        !           557:                        optimimp(path, rpath);
        !           558:                        break;
        !           559: 
        !           560:                case EXPLICIT:
        !           561:                        optimex(path, rpath);
        !           562:                        break;
        !           563:                }
        !           564:                for (cp2 = rpath; *cp2 != 0; cp2++) {
        !           565:                        stradd(name, *cp2);
        !           566:                        stradd(name, nc);
        !           567:                }
        !           568:        }
        !           569:        optiboth(name);
        !           570:        prefer(name);
        !           571: }
        !           572: 
        !           573: /*
        !           574:  * Return the network of the separator --
        !           575:  *     AN for arpa net
        !           576:  *     BN for Bell labs net
        !           577:  *     SN for Schmidt (berkeley net)
        !           578:  *     0 if we don't know.
        !           579:  */
        !           580: 
        !           581: ntype(nc)
        !           582:        register int nc;
        !           583: {
        !           584: 
        !           585:        switch (nc) {
        !           586:        case '^':
        !           587:        case '!':
        !           588:                return(BN);
        !           589: 
        !           590:        case ':':
        !           591:        case '.':
        !           592:                return(SN);
        !           593: 
        !           594:        case '@':
        !           595:        case '%':
        !           596:                return(AN);
        !           597: 
        !           598:        default:
        !           599:                return(0);
        !           600:        }
        !           601:        /* NOTREACHED */
        !           602: }
        !           603: 
        !           604: /*
        !           605:  * Return the kind of routing used for the particular net
        !           606:  * EXPLICIT means explicitly routed
        !           607:  * IMPLICIT means implicitly routed
        !           608:  * 0 means don't know
        !           609:  */
        !           610: 
        !           611: netkind(nt)
        !           612:        register int nt;
        !           613: {
        !           614: 
        !           615:        switch (nt) {
        !           616:        case BN:
        !           617:                return(EXPLICIT);
        !           618: 
        !           619:        case AN:
        !           620:        case SN:
        !           621:                return(IMPLICIT);
        !           622: 
        !           623:        default:
        !           624:                return(0);
        !           625:        }
        !           626:        /* NOTREACHED */
        !           627: }
        !           628: 
        !           629: /*
        !           630:  * Do name optimization for an explicitly routed network (eg BTL network).
        !           631:  */
        !           632: 
        !           633: optimex(net, name)
        !           634:        char net[], name[];
        !           635: {
        !           636:        register char *cp, *rp;
        !           637:        register int m;
        !           638:        char *rindex();
        !           639: 
        !           640:        strcpy(name, net);
        !           641:        cp = name;
        !           642:        if (strlen(cp) == 0)
        !           643:                return(-1);
        !           644:        if (cp[strlen(cp)-1] == LOCAL) {
        !           645:                name[0] = 0;
        !           646:                return(0);
        !           647:        }
        !           648:        for (cp = name; *cp; cp++) {
        !           649:                m = *cp;
        !           650:                rp = rindex(cp+1, m);
        !           651:                if (rp != NOSTR)
        !           652:                        strcpy(cp, rp);
        !           653:        }
        !           654:        return(0);
        !           655: }
        !           656: 
        !           657: /*
        !           658:  * Do name optimization for implicitly routed network (eg, arpanet,
        !           659:  * Berkeley network)
        !           660:  */
        !           661: 
        !           662: optimimp(net, name)
        !           663:        char net[], name[];
        !           664: {
        !           665:        register char *cp;
        !           666:        register int m;
        !           667: 
        !           668:        cp = net;
        !           669:        if (strlen(cp) == 0)
        !           670:                return(-1);
        !           671:        m = cp[strlen(cp) - 1];
        !           672:        if (m == LOCAL) {
        !           673:                strcpy(name, "");
        !           674:                return(0);
        !           675:        }
        !           676:        name[0] = m;
        !           677:        name[1] = 0;
        !           678:        return(0);
        !           679: }
        !           680: 
        !           681: /*
        !           682: 
        !           683:  * Perform global optimization on the given network path.
        !           684:  * The trick here is to look ahead to see if there are any loops
        !           685:  * in the path and remove them.  The interpretation of loops is
        !           686:  * more strict here than in optimex since both the machine and net
        !           687:  * type must match.
        !           688:  */
        !           689: 
        !           690: optiboth(net)
        !           691:        char net[];
        !           692: {
        !           693:        register char *cp, *cp2;
        !           694:        char *rpair();
        !           695: 
        !           696:        cp = net;
        !           697:        if (strlen(cp) == 0)
        !           698:                return;
        !           699:        if ((strlen(cp) % 2) != 0) {
        !           700:                printf("Strange arg to optiboth\n");
        !           701:                return;
        !           702:        }
        !           703:        while (*cp) {
        !           704:                cp2 = rpair(cp+2, *cp);
        !           705:                if (cp2 != NOSTR)
        !           706:                        strcpy(cp, cp2);
        !           707:                cp += 2;
        !           708:        }
        !           709: }
        !           710: 
        !           711: /*
        !           712:  * Find the rightmost instance of the given (machine, type) pair.
        !           713:  */
        !           714: 
        !           715: char *
        !           716: rpair(str, mach)
        !           717:        char str[];
        !           718: {
        !           719:        register char *cp, *last;
        !           720: 
        !           721:        last = NOSTR;
        !           722:        while (*cp) {
        !           723:                if (*cp == mach)
        !           724:                        last = cp;
        !           725:                cp += 2;
        !           726:        }
        !           727:        return(last);
        !           728: }
        !           729: 
        !           730: /*
        !           731:  * Change the network separators in the given network path
        !           732:  * to the preferred network transmission means.
        !           733:  */
        !           734: 
        !           735: prefer(name)
        !           736:        char name[];
        !           737: {
        !           738:        register char *cp;
        !           739:        register int state, n;
        !           740: 
        !           741:        state = LOCAL;
        !           742:        for (cp = name; *cp; cp += 2) {
        !           743:                n = best(state, *cp);
        !           744:                if (n)
        !           745:                        cp[1] = n;
        !           746:                state = *cp;
        !           747:        }
        !           748: }
        !           749: 
        !           750: /*
        !           751:  * Return the best network separator for the given machine pair.
        !           752:  */
        !           753: 
        !           754: struct netorder {
        !           755:        short   no_stat;
        !           756:        char    no_char;
        !           757: } netorder[] = {
        !           758:        CN,     ':',
        !           759:        AN,     '@',
        !           760:        AN,     '%',
        !           761:        SN,     ':',
        !           762:        BN,     '!',
        !           763:        -1,     0
        !           764: };
        !           765: 
        !           766: best(src, dest)
        !           767: {
        !           768:        register int dtype, stype;
        !           769:        register struct netorder *np;
        !           770: 
        !           771:        stype = nettype(src);
        !           772:        dtype = nettype(dest);
        !           773:        if (stype == 0 || dtype == 0) {
        !           774:                printf("ERROR:  unknown internal machine id\n");
        !           775:                return(0);
        !           776:        }
        !           777:        if ((stype & dtype) == 0) {
        !           778: #ifdef DELIVERMAIL
        !           779:                if (src != LOCAL)
        !           780: #endif
        !           781:                        printf("No way to get from \"%s\" to \"%s\"\n", 
        !           782:                            netname(src), netname(dest));
        !           783:                return(0);
        !           784:        }
        !           785:        np = &netorder[0];
        !           786:        while ((np->no_stat & stype & dtype) == 0)
        !           787:                np++;
        !           788:        return(np->no_char);
        !           789: }
        !           790: 
        !           791: /*
        !           792:  * Code to twist around arpa net names.
        !           793:  */
        !           794: 
        !           795: #define WORD 257                       /* Token for a string */
        !           796: 
        !           797: static char netbuf[256];
        !           798: static char *yylval;
        !           799: 
        !           800: /*
        !           801:  * Reverse all of the arpa net addresses in the given name to
        !           802:  * be of the form "host @ user" instead of "user @ host"
        !           803:  * This function is its own inverse.
        !           804:  */
        !           805: 
        !           806: char *
        !           807: revarpa(str)
        !           808:        char str[];
        !           809: {
        !           810: 
        !           811:        if (yyinit(str) < 0)
        !           812:                return(NOSTR);
        !           813:        if (name())
        !           814:                return(NOSTR);
        !           815:        if (strcmp(str, netbuf) == 0)
        !           816:                return(str);
        !           817:        return(savestr(netbuf));
        !           818: }
        !           819: 
        !           820: /*
        !           821:  * Parse (by recursive descent) network names, using the following grammar:
        !           822:  *     name:
        !           823:  *             term {':' term}
        !           824:  *             term {'^' term}
        !           825:  *             term {'!' term}
        !           826:  *             term '@' name
        !           827:  *             term '%' name
        !           828:  *
        !           829:  *     term:
        !           830:  *             string of characters.
        !           831:  */
        !           832: 
        !           833: name()
        !           834: {
        !           835:        register int t;
        !           836:        register char *cp;
        !           837: 
        !           838:        for (;;) {
        !           839:                t = yylex();
        !           840:                if (t != WORD)
        !           841:                        return(-1);
        !           842:                cp = yylval;
        !           843:                t = yylex();
        !           844:                switch (t) {
        !           845:                case 0:
        !           846:                        strcat(netbuf, cp);
        !           847:                        return(0);
        !           848: 
        !           849:                case '@':
        !           850:                case '%':
        !           851:                        if (name())
        !           852:                                return(-1);
        !           853:                        stradd(netbuf, '@');
        !           854:                        strcat(netbuf, cp);
        !           855:                        return(0);
        !           856: 
        !           857:                case WORD:
        !           858:                        return(-1);
        !           859: 
        !           860:                default:
        !           861:                        strcat(netbuf, cp);
        !           862:                        stradd(netbuf, t);
        !           863:                }
        !           864:        }
        !           865: }
        !           866: 
        !           867: /*
        !           868:  * Scanner for network names.
        !           869:  */
        !           870: 
        !           871: static char *charp;                    /* Current input pointer */
        !           872: static int nexttok;                    /* Salted away next token */
        !           873: 
        !           874: /*
        !           875:  * Initialize the network name scanner.
        !           876:  */
        !           877: 
        !           878: yyinit(str)
        !           879:        char str[];
        !           880: {
        !           881:        static char lexbuf[BUFSIZ];
        !           882: 
        !           883:        netbuf[0] = 0;
        !           884:        if (strlen(str) >= sizeof lexbuf - 1)
        !           885:                return(-1);
        !           886:        nexttok = 0;
        !           887:        strcpy(lexbuf, str);
        !           888:        charp = lexbuf;
        !           889:        return(0);
        !           890: }
        !           891: 
        !           892: /*
        !           893:  * Scan and return a single token.
        !           894:  * yylval is set to point to a scanned string.
        !           895:  */
        !           896: 
        !           897: yylex()
        !           898: {
        !           899:        register char *cp, *dot;
        !           900:        register int s;
        !           901: 
        !           902:        if (nexttok) {
        !           903:                s = nexttok;
        !           904:                nexttok = 0;
        !           905:                return(s);
        !           906:        }
        !           907:        cp = charp;
        !           908:        while (*cp && isspace(*cp))
        !           909:                cp++;
        !           910:        if (*cp == 0)
        !           911:                return(0);
        !           912:        if (any(*cp, "!^@:%")) {
        !           913:                charp = cp+1;
        !           914:                return(*cp);
        !           915:        }
        !           916:        dot = cp;
        !           917:        while (*cp && !any(*cp, " \t!^@:%"))
        !           918:                cp++;
        !           919:        if (any(*cp, "!^@:%"))
        !           920:                nexttok = *cp;
        !           921:        if (*cp == 0)
        !           922:                charp = cp;
        !           923:        else
        !           924:                charp = cp+1;
        !           925:        *cp = 0;
        !           926:        yylval = dot;
        !           927:        return(WORD);
        !           928: }
        !           929: 
        !           930: /*
        !           931:  * Add a single character onto a string.
        !           932:  */
        !           933: 
        !           934: stradd(str, c)
        !           935:        register char *str;
        !           936:        register int c;
        !           937: {
        !           938: 
        !           939:        str += strlen(str);
        !           940:        *str++ = c;
        !           941:        *str = 0;
        !           942: }

unix.superglobalmegacorp.com

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