Annotation of researchv10no/lbin/mailx/optim.c, revision 1.1

1.1     ! root        1: #ident "@(#)optim.c    1.4 'attmail mail(1) command'"
        !             2: #ident "@(#)mailx:optim.c      1.5.2.1"
        !             3: /*     Copyright (c) 1984 AT&T */
        !             4: /*       All Rights Reserved   */
        !             5: 
        !             6: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
        !             7: /*     The copyright notice above does not evidence any        */
        !             8: /*     actual or intended publication of such source code.     */
        !             9: 
        !            10: #ident "@(#)mailx:optim.c      1.5"
        !            11: 
        !            12: /*
        !            13:  * mailx -- a modified version of a University of California at Berkeley
        !            14:  *     mail program
        !            15:  *
        !            16:  * Network name modification routines.
        !            17:  */
        !            18: 
        !            19: #include "rcv.h"
        !            20: #include "configdefs.h"
        !            21: 
        !            22: static char            *arpafix();
        !            23: static char            *lasthost();
        !            24: static char            *makeremote();
        !            25: static int             mstash();
        !            26: static int             mtype();
        !            27: static int             netlook();
        !            28: static int             nettype();
        !            29: static int             ntype();
        !            30: static char            *revarpa();
        !            31: static char            *tackon();
        !            32: static struct xtrahash *xlocate();
        !            33: static int             yyinit();
        !            34: static int             yylex();
        !            35: 
        !            36: /*
        !            37:  * Map a name into the correct network "view" of the
        !            38:  * name.  This is done by prepending the name with the
        !            39:  * network address of the sender, then optimizing away
        !            40:  * nonsense.
        !            41:  */
        !            42: 
        !            43: char *
        !            44: netmap(name, from)
        !            45:        char name[], from[];
        !            46: {
        !            47:        char nbuf[BUFSIZ], ret[BUFSIZ];
        !            48:        register char *cp, *oname;
        !            49: 
        !            50:        if (debug) fprintf(stderr, "netmap(name '%s', from '%s')\n", name, from);
        !            51:        if (strlen(from) == 0)
        !            52:                return(name);
        !            53:        if (any('@', name) || any('%', name))
        !            54:                return(arpafix(name, from));
        !            55:        if (any('@', from) || any('%', from))
        !            56:                return(unuucp(makeremote(name, from)));
        !            57:        if (value("onehop") && (cp = strchr(name, '!')) && cp > name)
        !            58:                strcpy(nbuf, name);
        !            59:        else {
        !            60:                from = tackon(host, from);
        !            61:                *strrchr(from, '!') = 0;
        !            62:                name = tackon(lasthost(from), name);
        !            63:                while (((cp = lasthost(from)) != 0) && ishost(cp, name)) {
        !            64:                        oname = name;
        !            65:                        name = strchr(name, '!') + 1;
        !            66:                        if (cp == from) {
        !            67:                                from[strlen(from)] = '!';
        !            68:                                if (value("mustbang") && !strchr(name, '!'))
        !            69:                                        name = oname;
        !            70:                                return(unuucp(name));
        !            71:                        }
        !            72:                        *--cp = 0;
        !            73:                }
        !            74:                from[strlen(from)] = '!';
        !            75:                from = strchr(from, '!') + 1;
        !            76:                sprintf(nbuf, "%s!%s", from, name);
        !            77:        }
        !            78:        strcpy(ret, nbuf);
        !            79:        cp = revarpa(ret);
        !            80:        if (debug) fprintf(stderr, "wind up with '%s'\n", name);
        !            81:        if (!icequal(name, cp))
        !            82:                return(unuucp(savestr(cp)));
        !            83:        return(unuucp(name));
        !            84: }
        !            85: 
        !            86: /*
        !            87:  * Stick a host on the beginning of a uucp
        !            88:  * address if it isn't there already.
        !            89:  */
        !            90: static char *
        !            91: tackon(sys, rest)
        !            92:        char *sys, *rest;
        !            93: {
        !            94:        while (*rest == '!')
        !            95:                rest++;
        !            96:        if (!ishost(sys, rest)) {
        !            97:                char *r = salloc(strlen(sys) + strlen(rest) + 2);
        !            98:                sprintf(r, "%s!%s", sys, rest);
        !            99:                rest = r;
        !           100:        }
        !           101:        return rest;
        !           102: }
        !           103: 
        !           104: /*
        !           105:  * Check equality of the first host in a uucp address.
        !           106:  */
        !           107: ishost(sys, rest)
        !           108:        char *sys, *rest;
        !           109: {
        !           110:        while (*sys && *sys == *rest)
        !           111:                sys++, rest++;
        !           112:        return(*sys == 0 && *rest == '!');
        !           113: }
        !           114: 
        !           115: /*
        !           116:  * Return last host in a uucp address.
        !           117:  */
        !           118: static char *
        !           119: lasthost(addr)
        !           120:        char *addr;
        !           121: {
        !           122:        char *r = strrchr(addr, '!');
        !           123:        return r ? ++r : addr;
        !           124: }
        !           125: 
        !           126: /*
        !           127:  * Optionally translate an old format uucp name into a new one, e.g.
        !           128:  * "mach1!mach2!user" becomes "[email protected]".  This optional because
        !           129:  * some information is necessarily lost (e.g. the route it got here
        !           130:  * via) and if we don't have the host in our routing tables, we lose.
        !           131:  */
        !           132: char *
        !           133: unuucp(name)
        !           134: char *name;
        !           135: {
        !           136:        register char *np, *hp, *cp;
        !           137:        char result[100];
        !           138:        char tname[300];
        !           139: 
        !           140:        if (UnUUCP==0 &&
        !           141:            ((cp = value("conv"))==NOSTR || strcmp(cp, "internet")))
        !           142:                return name;
        !           143:        if (debug) fprintf(stderr, "unuucp(%s)\n", name);
        !           144:        strcpy(tname, name);
        !           145:        np = strrchr(tname, '!');
        !           146:        if (np == NOSTR)
        !           147:                return name;
        !           148:        *np++ = 0;
        !           149:        hp = strrchr(tname, '!');
        !           150:        if (hp == NOSTR)
        !           151:                hp = tname;
        !           152:        else
        !           153:                *hp++ = 0;
        !           154:        cp = strchr(np, '@');
        !           155:        if (cp == NOSTR)
        !           156:                cp = strchr(np, '%');
        !           157:        if (cp)
        !           158:                *cp = 0;
        !           159:        if (debug) fprintf(stderr, "host %s, name %s\n", hp, np);
        !           160:        sprintf(result, "%s@%s.UUCP", np, hp);
        !           161:        if (debug) fprintf(stderr, "unuucp returns %s\n", result);
        !           162:        return savestr(result);
        !           163: }
        !           164: 
        !           165: /*
        !           166:  * Turn a network machine name into a unique character
        !           167:  */
        !           168: static int
        !           169: netlook(machine, attnet)
        !           170:        char machine[];
        !           171: {
        !           172:        register struct netmach *np;
        !           173:        register char *cp, *cp2;
        !           174:        char nbuf[BUFSIZ];
        !           175: 
        !           176:        /*
        !           177:         * Make into lower case.
        !           178:         */
        !           179:        for (cp = machine, cp2 = nbuf;
        !           180:             *cp && cp2 < &nbuf[BUFSIZ-1];
        !           181:             *cp2++ = tolower(*cp++))
        !           182:                /*nothing*/;
        !           183:        *cp2 = 0;
        !           184: 
        !           185:        /*
        !           186:         * If a single letter machine, look through those first.
        !           187:         */
        !           188: 
        !           189:        if (strlen(nbuf) == 1)
        !           190:                for (np = netmach; np->nt_mid != 0; np++)
        !           191:                        if (np->nt_mid == nbuf[0])
        !           192:                                return(nbuf[0]);
        !           193: 
        !           194:        /*
        !           195:         * Look for usual name
        !           196:         */
        !           197: 
        !           198:        for (np = netmach; np->nt_mid != 0; np++)
        !           199:                if (strcmp(np->nt_machine, nbuf) == 0)
        !           200:                        return(np->nt_mid);
        !           201: 
        !           202:        /*
        !           203:         * Look in side hash table.
        !           204:         */
        !           205: 
        !           206:        return(mstash(nbuf, attnet));
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * Deal with arpa net addresses.  The way this is done is strange.
        !           211:  * In particular, if the destination arpa net host is not Berkeley,
        !           212:  * then the address is correct as stands.  Otherwise, we strip off
        !           213:  * the trailing @Berkeley, then cook up a phony person for it to
        !           214:  * be from and optimize the result.
        !           215:  */
        !           216: static char *
        !           217: arpafix(name, from)
        !           218:        char name[];
        !           219:        char from[];
        !           220: {
        !           221:        register char *cp;
        !           222:        register int arpamach;
        !           223:        char newname[BUFSIZ];
        !           224: 
        !           225:        if (debug) {
        !           226:                fprintf(stderr, "arpafix(%s, %s)\n", name, from);
        !           227:        }
        !           228:        cp = strrchr(name, '@');
        !           229:        if (cp == NOSTR)
        !           230:                cp = strrchr(name, '%');
        !           231:        if (cp == NOSTR) {
        !           232:                fprintf(stderr, "Somethings amiss -- no @ or %% in arpafix\n");
        !           233:                return(name);
        !           234:        }
        !           235:        cp++;
        !           236:        arpamach = netlook(cp, '@');
        !           237:        if (debug) fprintf(stderr, "cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n", cp, arpamach, nettype(arpamach), nettype(LOCAL));
        !           238:        if (arpamach == 0) {
        !           239:                if (debug)
        !           240:                        fprintf(stderr, "machine %s unknown, uses: %s\n", cp, name);
        !           241:                return(name);
        !           242:        }
        !           243:        if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) {
        !           244:                if (debug)
        !           245:                        fprintf(stderr, "machine %s known but remote, uses: %s\n",
        !           246:                            cp, name);
        !           247:                return(name);
        !           248:        }
        !           249:        strcpy(newname, name);
        !           250:        cp = strrchr(newname, '@');
        !           251:        if (cp == NOSTR)
        !           252:                cp = strrchr(newname, '%');
        !           253:        *cp = 0;
        !           254:        if (debug) fprintf(stderr, "local address, return '%s'\n", newname);
        !           255:        return(savestr(newname));
        !           256: }
        !           257: 
        !           258: /*
        !           259:  * We have name with no @'s in it, and from with @'s.
        !           260:  * Assume that name is meaningful only on the site in from.
        !           261:  */
        !           262: static char *
        !           263: makeremote(name, from)
        !           264:        char name[];
        !           265:        char from[];
        !           266: {
        !           267:        register char *cp;
        !           268:        static char rbuf[200];
        !           269: 
        !           270:        if (debug) fprintf(stderr, "makeremote(%s, %s) returns ", name, from);
        !           271:        strcpy(rbuf, name);
        !           272:        cp = strrchr(from, '@');
        !           273:        if (cp == NOSTR)
        !           274:                cp = strrchr(from, '%');
        !           275:        strcat(rbuf, cp);
        !           276:        if (debug) fprintf(stderr, "%s\n", rbuf);
        !           277:        return rbuf;
        !           278: }
        !           279: 
        !           280: /*
        !           281:  * Take a network machine descriptor and find the types of connected
        !           282:  * nets and return it.
        !           283:  */
        !           284: static int
        !           285: nettype(mid)
        !           286: {
        !           287:        register struct netmach *np;
        !           288: 
        !           289:        if (mid & 0200)
        !           290:                return(mtype(mid));
        !           291:        for (np = netmach; np->nt_mid != 0; np++)
        !           292:                if (np->nt_mid == mid)
        !           293:                        return(np->nt_type);
        !           294:        return(0);
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Hashing routines to salt away machines seen scanning
        !           299:  * networks paths that we don't know about.
        !           300:  */
        !           301: 
        !           302: #define        XHSIZE          19              /* Size of extra hash table */
        !           303: #define        NXMID           (XHSIZE*3/4)    /* Max extra machines */
        !           304: 
        !           305: struct xtrahash {
        !           306:        char    *xh_name;               /* Name of machine */
        !           307:        short   xh_mid;                 /* Machine ID */
        !           308:        short   xh_attnet;              /* Attached networks */
        !           309: } xtrahash[XHSIZE];
        !           310: 
        !           311: static struct xtrahash *xtab[XHSIZE];          /* F: mid-->machine name */
        !           312: 
        !           313: static short   midfree;                        /* Next free machine id */
        !           314: 
        !           315: /*
        !           316:  * Initialize the extra host hash table.
        !           317:  * Called by sreset.
        !           318:  */
        !           319: void
        !           320: minit()
        !           321: {
        !           322:        register struct xtrahash *xp, **tp;
        !           323: 
        !           324:        midfree = 0;
        !           325:        tp = &xtab[0];
        !           326:        for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) {
        !           327:                xp->xh_name = NOSTR;
        !           328:                xp->xh_mid = 0;
        !           329:                xp->xh_attnet = 0;
        !           330:                *tp++ = (struct xtrahash *) 0;
        !           331:        }
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Stash a net name in the extra host hash table.
        !           336:  * If a new entry is put in the hash table, deduce what
        !           337:  * net the machine is attached to from the net character.
        !           338:  *
        !           339:  * If the machine is already known, add the given attached
        !           340:  * net to those already known.
        !           341:  */
        !           342: static int
        !           343: mstash(name, attnet)
        !           344:        char name[];
        !           345: {
        !           346:        register struct xtrahash *xp;
        !           347:        int x;
        !           348: 
        !           349:        xp = xlocate(name);
        !           350:        if (xp == (struct xtrahash *) 0) {
        !           351:                printf("Ran out of machine id spots\n");
        !           352:                return(0);
        !           353:        }
        !           354:        if (xp->xh_name == NOSTR) {
        !           355:                if (midfree >= XHSIZE) {
        !           356:                        printf("Out of machine ids\n");
        !           357:                        return(0);
        !           358:                }
        !           359:                xtab[midfree] = xp;
        !           360:                xp->xh_name = savestr(name);
        !           361:                xp->xh_mid = 0200 + midfree++;
        !           362:        }
        !           363:        x = ntype(attnet);
        !           364:        if (x == 0)
        !           365:                xp->xh_attnet |= AN;
        !           366:        else
        !           367:                xp->xh_attnet |= x;
        !           368:        return(xp->xh_mid);
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Search for the given name in the hash table
        !           373:  * and return the pointer to it if found, or to the first
        !           374:  * empty slot if not found.
        !           375:  *
        !           376:  * If no free slots can be found, return 0.
        !           377:  */
        !           378: 
        !           379: static struct xtrahash *
        !           380: xlocate(name)
        !           381:        char name[];
        !           382: {
        !           383:        register int h, q, i;
        !           384:        register char *cp;
        !           385:        register struct xtrahash *xp;
        !           386: 
        !           387:        for (h = 0, cp = name; *cp; h = (h << 2) + *cp++)
        !           388:                ;
        !           389:        if (h < 0 && (h = -h) < 0)
        !           390:                h = 0;
        !           391:        h = h % XHSIZE;
        !           392:        cp = name;
        !           393:        for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
        !           394:                xp = &xtrahash[(h + q) % XHSIZE];
        !           395:                if (xp->xh_name == NOSTR)
        !           396:                        return(xp);
        !           397:                if (strcmp(cp, xp->xh_name) == 0)
        !           398:                        return(xp);
        !           399:                if (h - q < 0)
        !           400:                        q += XHSIZE;
        !           401:                xp = &xtrahash[(h - q) % XHSIZE];
        !           402:                if (xp->xh_name == NOSTR)
        !           403:                        return(xp);
        !           404:                if (strcmp(cp, xp->xh_name) == 0)
        !           405:                        return(xp);
        !           406:        }
        !           407:        return((struct xtrahash *) 0);
        !           408: }
        !           409: 
        !           410: /*
        !           411:  * Return the bit mask of net's that the given extra host machine
        !           412:  * id has so far.
        !           413:  */
        !           414: static int
        !           415: mtype(mid)
        !           416: {
        !           417:        register int m;
        !           418: 
        !           419:        if ((mid & 0200) == 0)
        !           420:                return(0);
        !           421:        m = mid & 0177;
        !           422:        if (m >= midfree) {
        !           423:                printf("Use made of undefined machine id\n");
        !           424:                return(0);
        !           425:        }
        !           426:        return(xtab[m]->xh_attnet);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Return the network of the separator --
        !           431:  *     AN for arpa net
        !           432:  *     BN for Bell labs net    (e.g. UUCP, NOT Berknet)
        !           433:  *     SN for Schmidt net      (Berknet)
        !           434:  *     0 if we don't know.
        !           435:  */
        !           436: static int
        !           437: ntype(nc)
        !           438:        register int nc;
        !           439: {
        !           440:        register struct ntypetab *np;
        !           441: 
        !           442:        for (np = ntypetab; np->nt_char != 0; np++)
        !           443:                if (np->nt_char == nc)
        !           444:                        return(np->nt_bcode);
        !           445:        return(0);
        !           446: }
        !           447: 
        !           448: 
        !           449: /*
        !           450:  * Code to twist around arpa net names.
        !           451:  */
        !           452: 
        !           453: #define WORD 257                       /* Token for a string */
        !           454: 
        !           455: static char netbuf[256];
        !           456: static char *yylval;
        !           457: 
        !           458: /*
        !           459:  * Reverse all of the arpa net addresses in the given name to
        !           460:  * be of the form "host @ user" instead of "user @ host"
        !           461:  * This function is its own inverse.
        !           462:  */
        !           463: 
        !           464: static char *
        !           465: revarpa(str)
        !           466:        char str[];
        !           467: {
        !           468: 
        !           469:        if (yyinit(str) < 0)
        !           470:                return(NOSTR);
        !           471:        if (name())
        !           472:                return(NOSTR);
        !           473:        if (strcmp(str, netbuf) == 0)
        !           474:                return(str);
        !           475:        return(savestr(netbuf));
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * Parse (by recursive descent) network names, using the following grammar:
        !           480:  *     name:
        !           481:  *             term {':' term}
        !           482:  *             term {'^' term}
        !           483:  *             term {'!' term}
        !           484:  *             term '@' name
        !           485:  *             term '%' name
        !           486:  *
        !           487:  *     term:
        !           488:  *             string of characters.
        !           489:  */
        !           490: 
        !           491: name()
        !           492: {
        !           493:        register int t;
        !           494:        register char *cp;
        !           495: 
        !           496:        for (;;) {
        !           497:                t = yylex();
        !           498:                if (t != WORD)
        !           499:                        return(-1);
        !           500:                cp = yylval;
        !           501:                t = yylex();
        !           502:                switch (t) {
        !           503:                case 0:
        !           504:                        strcat(netbuf, cp);
        !           505:                        return(0);
        !           506: 
        !           507:                case '@':
        !           508:                case '%':
        !           509:                        if (name())
        !           510:                                return(-1);
        !           511:                        strcat(netbuf, "@");
        !           512:                        strcat(netbuf, cp);
        !           513:                        return(0);
        !           514: 
        !           515:                case WORD:
        !           516:                        return(-1);
        !           517: 
        !           518:                default:
        !           519:                        strcat(netbuf, cp);
        !           520:                        stradd(netbuf, t);
        !           521:                }
        !           522:        }
        !           523: }
        !           524: 
        !           525: /*
        !           526:  * Scanner for network names.
        !           527:  */
        !           528: 
        !           529: static char *charp;                    /* Current input pointer */
        !           530: static int nexttok;                    /* Salted away next token */
        !           531: 
        !           532: /*
        !           533:  * Initialize the network name scanner.
        !           534:  */
        !           535: static int
        !           536: yyinit(str)
        !           537:        char str[];
        !           538: {
        !           539:        static char lexbuf[BUFSIZ];
        !           540: 
        !           541:        netbuf[0] = 0;
        !           542:        if (strlen(str) >= sizeof lexbuf - 1)
        !           543:                return(-1);
        !           544:        nexttok = 0;
        !           545:        strcpy(lexbuf, str);
        !           546:        charp = lexbuf;
        !           547:        return(0);
        !           548: }
        !           549: 
        !           550: /*
        !           551:  * Scan and return a single token.
        !           552:  * yylval is set to point to a scanned string.
        !           553:  */
        !           554: static int
        !           555: yylex()
        !           556: {
        !           557:        register char *cp, *dot;
        !           558:        register int s;
        !           559: 
        !           560:        if (nexttok) {
        !           561:                s = nexttok;
        !           562:                nexttok = 0;
        !           563:                return(s);
        !           564:        }
        !           565:        cp = charp;
        !           566:        while (*cp && isspace(*cp))
        !           567:                cp++;
        !           568:        if (*cp == 0)
        !           569:                return(0);
        !           570:        if (any(*cp, metanet)) {
        !           571:                charp = cp+1;
        !           572:                return(*cp);
        !           573:        }
        !           574:        dot = cp;
        !           575:        while (*cp && !any(*cp, metanet) && !any(*cp, " \t"))
        !           576:                cp++;
        !           577:        if (any(*cp, metanet))
        !           578:                nexttok = *cp;
        !           579:        if (*cp == 0)
        !           580:                charp = cp;
        !           581:        else
        !           582:                charp = cp+1;
        !           583:        *cp = 0;
        !           584:        yylval = dot;
        !           585:        return(WORD);
        !           586: }
        !           587: 
        !           588: /*
        !           589:  * Add a single character onto a string.
        !           590:  */
        !           591: 
        !           592: void
        !           593: stradd(str, c)
        !           594:        register char *str;
        !           595:        register int c;
        !           596: {
        !           597:        while (*str)
        !           598:                str++;
        !           599:        *str++ = (char)c;
        !           600:        *str = '\0';
        !           601: }

unix.superglobalmegacorp.com

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