Annotation of researchv10no/lbin/mailx/optim.c, revision 1.1.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.