Annotation of 41BSD/cmd/ucbmail/names.c, revision 1.1.1.1

1.1       root        1: #
                      2: 
                      3: /*
                      4:  * Mail -- a mail program
                      5:  *
                      6:  * Handle name lists.
                      7:  */
                      8: 
                      9: #include "rcv.h"
                     10: 
                     11: /*
                     12:  * Allocate a single element of a name list,
                     13:  * initialize its name field to the passed
                     14:  * name and return it.
                     15:  */
                     16: 
                     17: struct name *
                     18: nalloc(str)
                     19:        char str[];
                     20: {
                     21:        register struct name *np;
                     22: 
                     23:        np = (struct name *) salloc(sizeof *np);
                     24:        np->n_flink = NIL;
                     25:        np->n_blink = NIL;
                     26:        np->n_type = -1;
                     27:        np->n_name = savestr(str);
                     28:        return(np);
                     29: }
                     30: 
                     31: /*
                     32:  * Find the tail of a list and return it.
                     33:  */
                     34: 
                     35: struct name *
                     36: tailof(name)
                     37:        struct name *name;
                     38: {
                     39:        register struct name *np;
                     40: 
                     41:        np = name;
                     42:        if (np == NIL)
                     43:                return(NIL);
                     44:        while (np->n_flink != NIL)
                     45:                np = np->n_flink;
                     46:        return(np);
                     47: }
                     48: 
                     49: /*
                     50:  * Extract a list of names from a line,
                     51:  * and make a list of names from it.
                     52:  * Return the list or NIL if none found.
                     53:  */
                     54: 
                     55: struct name *
                     56: extract(line, ntype)
                     57:        char line[];
                     58: {
                     59:        register char *cp;
                     60:        register struct name *top, *np, *t;
                     61:        char nbuf[BUFSIZ], abuf[BUFSIZ];
                     62: 
                     63:        if (line == NOSTR || strlen(line) == 0)
                     64:                return(NIL);
                     65:        top = NIL;
                     66:        np = NIL;
                     67:        cp = line;
                     68:        while ((cp = yankword(cp, nbuf)) != NOSTR) {
                     69:                if (np != NIL && equal(nbuf, "at")) {
                     70:                        strcpy(abuf, nbuf);
                     71:                        if ((cp = yankword(cp, nbuf)) == NOSTR) {
                     72:                                strcpy(nbuf, abuf);
                     73:                                goto normal;
                     74:                        }
                     75:                        strcpy(abuf, np->n_name);
                     76:                        stradd(abuf, '@');
                     77:                        strcat(abuf, nbuf);
                     78:                        np->n_name = savestr(abuf);
                     79:                        continue;
                     80:                }
                     81: normal:
                     82:                t = nalloc(nbuf);
                     83:                t->n_type = ntype;
                     84:                if (top == NIL)
                     85:                        top = t;
                     86:                else
                     87:                        np->n_flink = t;
                     88:                t->n_blink = np;
                     89:                np = t;
                     90:        }
                     91:        return(top);
                     92: }
                     93: 
                     94: /*
                     95:  * Turn a list of names into a string of the same names.
                     96:  */
                     97: 
                     98: char *
                     99: detract(np, ntype)
                    100:        register struct name *np;
                    101: {
                    102:        register int s;
                    103:        register char *cp, *top;
                    104:        register struct name *p;
                    105:        register int comma;
                    106: 
                    107:        comma = ntype & GCOMMA;
                    108:        if (np == NIL)
                    109:                return(NOSTR);
                    110:        ntype &= ~GCOMMA;
                    111:        s = 0;
                    112:        if (debug && comma)
                    113:                fprintf(stderr, "detract asked to insert commas\n");
                    114:        for (p = np; p != NIL; p = p->n_flink) {
                    115:                if (ntype && (p->n_type & GMASK) != ntype)
                    116:                        continue;
                    117:                s += strlen(p->n_name) + 1;
                    118:                if (comma)
                    119:                        s++;
                    120:        }
                    121:        if (s == 0)
                    122:                return(NOSTR);
                    123:        s += 2;
                    124:        top = salloc(s);
                    125:        cp = top;
                    126:        for (p = np; p != NIL; p = p->n_flink) {
                    127:                if (ntype && (p->n_type & GMASK) != ntype)
                    128:                        continue;
                    129:                cp = copy(p->n_name, cp);
                    130:                if (comma && p->n_flink != NIL)
                    131:                        *cp++ = ',';
                    132:                *cp++ = ' ';
                    133:        }
                    134:        *--cp = 0;
                    135:        if (comma && *--cp == ',')
                    136:                *cp = 0;
                    137:        return(top);
                    138: }
                    139: 
                    140: /*
                    141:  * Grab a single word (liberal word)
                    142:  * Throw away things between ()'s.
                    143:  */
                    144: 
                    145: char *
                    146: yankword(ap, wbuf)
                    147:        char *ap, wbuf[];
                    148: {
                    149:        register char *cp, *cp2;
                    150: 
                    151:        do {
                    152:                for (cp = ap; *cp && any(*cp, " \t,"); cp++)
                    153:                        ;
                    154:                if (*cp == '(') {
                    155:                        while (*cp && *cp != ')')
                    156:                                cp++;
                    157:                        if (*cp)
                    158:                                cp++;
                    159:                }
                    160:                if (*cp == '\0')
                    161:                        return(NOSTR);
                    162:        } while (any(*cp, " \t,("));
                    163:        for (cp2 = wbuf; *cp && !any(*cp, " \t,("); *cp2++ = *cp++)
                    164:                ;
                    165:        *cp2 = '\0';
                    166:        return(cp);
                    167: }
                    168: 
                    169: /*
                    170:  * Verify that all the users in the list of names are
                    171:  * legitimate.  Bitch about and delink those who aren't.
                    172:  */
                    173: 
                    174: struct name *
                    175: verify(names)
                    176:        struct name *names;
                    177: {
                    178:        register struct name *np, *top, *t, *x;
                    179:        register char *cp;
                    180: 
                    181: #ifdef DELIVERMAIL
                    182:        return(names);
                    183: #else
                    184:        top = names;
                    185:        np = names;
                    186:        while (np != NIL) {
                    187:                if (np->n_type & GDEL) {
                    188:                        np = np->n_flink;
                    189:                        continue;
                    190:                }
                    191:                for (cp = "!:@^"; *cp; cp++)
                    192:                        if (any(*cp, np->n_name))
                    193:                                break;
                    194:                if (*cp != 0) {
                    195:                        np = np->n_flink;
                    196:                        continue;
                    197:                }
                    198:                cp = np->n_name;
                    199:                while (*cp == '\\')
                    200:                        cp++;
                    201:                if (equal(cp, "msgs") ||
                    202:                    getuserid(cp) != -1) {
                    203:                        np = np->n_flink;
                    204:                        continue;
                    205:                }
                    206:                fprintf(stderr, "Can't send to %s\n", np->n_name);
                    207:                senderr++;
                    208:                if (np == top) {
                    209:                        top = np->n_flink;
                    210:                        if (top != NIL)
                    211:                                top->n_blink = NIL;
                    212:                        np = top;
                    213:                        continue;
                    214:                }
                    215:                x = np->n_blink;
                    216:                t = np->n_flink;
                    217:                x->n_flink = t;
                    218:                if (t != NIL)
                    219:                        t->n_blink = x;
                    220:                np = t;
                    221:        }
                    222:        return(top);
                    223: #endif
                    224: }
                    225: 
                    226: /*
                    227:  * For each recipient in the passed name list with a /
                    228:  * in the name, append the message to the end of the named file
                    229:  * and remove him from the recipient list.
                    230:  *
                    231:  * Recipients whose name begins with | are piped through the given
                    232:  * program and removed.
                    233:  */
                    234: 
                    235: struct name *
                    236: outof(names, fo, hp)
                    237:        struct name *names;
                    238:        FILE *fo;
                    239:        struct header *hp;
                    240: {
                    241:        register int c;
                    242:        register struct name *np, *top, *t, *x;
                    243:        long now;
                    244:        char *date, *fname, *shell, *ctime();
                    245:        FILE *fout, *fin;
                    246:        int ispipe, s, pid;
                    247:        extern char tempEdit[];
                    248: 
                    249:        top = names;
                    250:        np = names;
                    251:        time(&now);
                    252:        date = ctime(&now);
                    253:        while (np != NIL) {
                    254:                if (!any('/', np->n_name) && np->n_name[0] != '|') {
                    255:                        np = np->n_flink;
                    256:                        continue;
                    257:                }
                    258:                ispipe = np->n_name[0] == '|';
                    259:                if (ispipe)
                    260:                        fname = np->n_name+1;
                    261:                else
                    262:                        fname = expand(np->n_name);
                    263: 
                    264:                /*
                    265:                 * See if we have copied the complete message out yet.
                    266:                 * If not, do so.
                    267:                 */
                    268: 
                    269:                if (image < 0) {
                    270:                        if ((fout = fopen(tempEdit, "a")) == NULL) {
                    271:                                perror(tempEdit);
                    272:                                senderr++;
                    273:                                goto cant;
                    274:                        }
                    275:                        image = open(tempEdit, 2);
                    276:                        unlink(tempEdit);
                    277:                        if (image < 0) {
                    278:                                perror(tempEdit);
                    279:                                senderr++;
                    280:                                goto cant;
                    281:                        }
                    282:                        else {
                    283:                                rewind(fo);
                    284:                                fprintf(fout, "From %s %s", myname, date);
                    285:                                puthead(hp, fout, GTO|GSUBJECT|GCC|GNL);
                    286:                                while ((c = getc(fo)) != EOF)
                    287:                                        putc(c, fout);
                    288:                                rewind(fo);
                    289:                                putc('\n', fout);
                    290:                                fflush(fout);
                    291:                                if (ferror(fout))
                    292:                                        perror(tempEdit);
                    293:                                fclose(fout);
                    294:                        }
                    295:                }
                    296: 
                    297:                /*
                    298:                 * Now either copy "image" to the desired file
                    299:                 * or give it as the standard input to the desired
                    300:                 * program as appropriate.
                    301:                 */
                    302: 
                    303:                if (ispipe) {
                    304:                        wait(&s);
                    305:                        switch (pid = fork()) {
                    306:                        case 0:
                    307:                                signal(SIGHUP, SIG_IGN);
                    308:                                signal(SIGINT, SIG_IGN);
                    309:                                signal(SIGQUIT, SIG_IGN);
                    310:                                close(0);
                    311:                                dup(image);
                    312:                                close(image);
                    313:                                if ((shell = value("SHELL")) == NOSTR)
                    314:                                        shell = SHELL;
                    315:                                execl(shell, shell, "-c", fname, 0);
                    316:                                perror(shell);
                    317:                                exit(1);
                    318:                                break;
                    319: 
                    320:                        case -1:
                    321:                                perror("fork");
                    322:                                senderr++;
                    323:                                goto cant;
                    324:                        }
                    325:                }
                    326:                else {
                    327:                        if ((fout = fopen(fname, "a")) == NULL) {
                    328:                                perror(fname);
                    329:                                senderr++;
                    330:                                goto cant;
                    331:                        }
                    332:                        fin = Fdopen(image, "r");
                    333:                        if (fin == NULL) {
                    334:                                fprintf(stderr, "Can't reopen image\n");
                    335:                                fclose(fout);
                    336:                                senderr++;
                    337:                                goto cant;
                    338:                        }
                    339:                        rewind(fin);
                    340:                        while ((c = getc(fin)) != EOF)
                    341:                                putc(c, fout);
                    342:                        if (ferror(fout))
                    343:                                senderr++, perror(fname);
                    344:                        fclose(fout);
                    345:                        fclose(fin);
                    346:                }
                    347: 
                    348: cant:
                    349: 
                    350:                /*
                    351:                 * In days of old we removed the entry from the
                    352:                 * the list; now for sake of header expansion
                    353:                 * we leave it in and mark it as deleted.
                    354:                 */
                    355: 
                    356: #ifdef CRAZYWOW
                    357:                if (np == top) {
                    358:                        top = np->n_flink;
                    359:                        if (top != NIL)
                    360:                                top->n_blink = NIL;
                    361:                        np = top;
                    362:                        continue;
                    363:                }
                    364:                x = np->n_blink;
                    365:                t = np->n_flink;
                    366:                x->n_flink = t;
                    367:                if (t != NIL)
                    368:                        t->n_blink = x;
                    369:                np = t;
                    370: #endif
                    371: 
                    372:                np->n_type |= GDEL;
                    373:                np = np->n_flink;
                    374:        }
                    375:        if (image >= 0) {
                    376:                close(image);
                    377:                image = -1;
                    378:        }
                    379:        return(top);
                    380: }
                    381: 
                    382: /*
                    383:  * Map all of the aliased users in the invoker's mailrc
                    384:  * file and insert them into the list.
                    385:  * Changed after all these months of service to recursively
                    386:  * expand names (2/14/80).
                    387:  */
                    388: 
                    389: struct name *
                    390: usermap(names)
                    391:        struct name *names;
                    392: {
                    393:        register struct name *new, *np, *cp;
                    394:        struct name *getto;
                    395:        struct grouphead *gh;
                    396:        register int metoo;
                    397: 
                    398:        new = NIL;
                    399:        np = names;
                    400:        getto = NIL;
                    401:        metoo = (value("metoo") != NOSTR);
                    402:        while (np != NIL) {
                    403:                if (np->n_name[0] == '\\') {
                    404:                        cp = np->n_flink;
                    405:                        new = put(new, np);
                    406:                        np = cp;
                    407:                        continue;
                    408:                }
                    409:                gh = findgroup(np->n_name);
                    410:                cp = np->n_flink;
                    411:                if (gh != NOGRP)
                    412:                        new = gexpand(new, gh, metoo, np->n_type);
                    413:                else
                    414:                        new = put(new, np);
                    415:                np = cp;
                    416:        }
                    417:        return(new);
                    418: }
                    419: 
                    420: /*
                    421:  * Recursively expand a group name.  We limit the expansion to some
                    422:  * fixed level to keep things from going haywire.
                    423:  * Direct recursion is not expanded for convenience.
                    424:  */
                    425: 
                    426: struct name *
                    427: gexpand(nlist, gh, metoo, ntype)
                    428:        struct name *nlist;
                    429:        struct grouphead *gh;
                    430: {
                    431:        struct group *gp;
                    432:        struct grouphead *ngh;
                    433:        struct name *np;
                    434:        static int depth;
                    435:        char *cp;
                    436: 
                    437:        if (depth > MAXEXP) {
                    438:                printf("Expanding alias to depth larger than %d\n", MAXEXP);
                    439:                return(nlist);
                    440:        }
                    441:        depth++;
                    442:        for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) {
                    443:                cp = gp->ge_name;
                    444:                if (*cp == '\\')
                    445:                        goto quote;
                    446:                if (strcmp(cp, gh->g_name) == 0)
                    447:                        goto quote;
                    448:                if ((ngh = findgroup(cp)) != NOGRP) {
                    449:                        nlist = gexpand(nlist, ngh, metoo, ntype);
                    450:                        continue;
                    451:                }
                    452: quote:
                    453:                np = nalloc(cp);
                    454:                np->n_type = ntype;
                    455:                /*
                    456:                 * At this point should allow to expand
                    457:                 * to self if only person in group
                    458:                 */
                    459:                if (gp == gh->g_list && gp->ge_link == NOGE)
                    460:                        goto skip;
                    461:                if (!metoo && strcmp(cp, myname) == 0)
                    462:                        np->n_type |= GDEL;
                    463: skip:
                    464:                nlist = put(nlist, np);
                    465:        }
                    466:        depth--;
                    467:        return(nlist);
                    468: }
                    469: 
                    470: 
                    471: 
                    472: /*
                    473:  * Compute the length of the passed name list and
                    474:  * return it.
                    475:  */
                    476: 
                    477: lengthof(name)
                    478:        struct name *name;
                    479: {
                    480:        register struct name *np;
                    481:        register int c;
                    482: 
                    483:        for (c = 0, np = name; np != NIL; c++, np = np->n_flink)
                    484:                ;
                    485:        return(c);
                    486: }
                    487: 
                    488: /*
                    489:  * Concatenate the two passed name lists, return the result.
                    490:  */
                    491: 
                    492: struct name *
                    493: cat(n1, n2)
                    494:        struct name *n1, *n2;
                    495: {
                    496:        register struct name *tail;
                    497: 
                    498:        if (n1 == NIL)
                    499:                return(n2);
                    500:        if (n2 == NIL)
                    501:                return(n1);
                    502:        tail = tailof(n1);
                    503:        tail->n_flink = n2;
                    504:        n2->n_blink = tail;
                    505:        return(n1);
                    506: }
                    507: 
                    508: /*
                    509:  * Unpack the name list onto a vector of strings.
                    510:  * Return an error if the name list won't fit.
                    511:  */
                    512: 
                    513: char **
                    514: unpack(np)
                    515:        struct name *np;
                    516: {
                    517:        register char **ap, **top;
                    518:        register struct name *n;
                    519:        char *cp;
                    520:        char hbuf[10];
                    521:        int t, extra, metoo;
                    522: 
                    523:        n = np;
                    524:        if ((t = lengthof(n)) == 0)
                    525:                panic("No names to unpack");
                    526: 
                    527:        /*
                    528:         * Compute the number of extra arguments we will need.
                    529:         * We need at least two extra -- one for "mail" and one for
                    530:         * the terminating 0 pointer.  Additional spots may be needed
                    531:         * to pass along -r and -f to the host mailer.
                    532:         */
                    533: 
                    534:        extra = 2;
                    535:        if (rflag != NOSTR)
                    536:                extra += 2;
                    537: #ifdef DELIVERMAIL
                    538:        extra++;
                    539:        metoo = value("metoo") != NOSTR;
                    540:        if (metoo)
                    541:                extra++;
                    542: #endif DELIVERMAIL
                    543:        if (hflag)
                    544:                extra += 2;
                    545:        top = (char **) salloc((t + extra) * sizeof cp);
                    546:        ap = top;
                    547:        *ap++ = "send-mail";
                    548:        if (rflag != NOSTR) {
                    549:                *ap++ = "-r";
                    550:                *ap++ = rflag;
                    551:        }
                    552: #ifdef DELIVERMAIL
                    553:        *ap++ = "-i";
                    554:        if (metoo)
                    555:                *ap++ = "-m";
                    556: #endif DELIVERMAIL
                    557:        if (hflag) {
                    558:                *ap++ = "-h";
                    559:                sprintf(hbuf, "%d", hflag);
                    560:                *ap++ = savestr(hbuf);
                    561:        }
                    562:        while (n != NIL) {
                    563:                if (n->n_type & GDEL) {
                    564:                        n = n->n_flink;
                    565:                        continue;
                    566:                }
                    567:                cp = n->n_name;
                    568:                while (*cp == '\\')
                    569:                        cp++;
                    570:                *ap++ = cp;
                    571:                n = n->n_flink;
                    572:        }
                    573:        *ap = NOSTR;
                    574:        return(top);
                    575: }
                    576: 
                    577: /*
                    578:  * See if the user named himself as a destination
                    579:  * for outgoing mail.  If so, set the global flag
                    580:  * selfsent so that we avoid removing his mailbox.
                    581:  */
                    582: 
                    583: mechk(names)
                    584:        struct name *names;
                    585: {
                    586:        register struct name *np;
                    587: 
                    588:        for (np = names; np != NIL; np = np->n_flink)
                    589:                if ((np->n_type & GDEL) == 0 && equal(myname, np->n_name)) {
                    590:                        selfsent++;
                    591:                        return;
                    592:                }
                    593: }
                    594: 
                    595: /*
                    596:  * Remove all of the duplicates from the passed name list by
                    597:  * insertion sorting them, then checking for dups.
                    598:  * Return the head of the new list.
                    599:  */
                    600: 
                    601: struct name *
                    602: elide(names)
                    603:        struct name *names;
                    604: {
                    605:        register struct name *np, *t, *new;
                    606:        struct name *x;
                    607: 
                    608:        if (names == NIL)
                    609:                return(NIL);
                    610:        new = names;
                    611:        np = names;
                    612:        np = np->n_flink;
                    613:        if (np != NIL)
                    614:                np->n_blink = NIL;
                    615:        new->n_flink = NIL;
                    616:        while (np != NIL) {
                    617:                t = new;
                    618:                while (nstrcmp(t->n_name, np->n_name) < 0) {
                    619:                        if (t->n_flink == NIL)
                    620:                                break;
                    621:                        t = t->n_flink;
                    622:                }
                    623: 
                    624:                /*
                    625:                 * If we ran out of t's, put the new entry after
                    626:                 * the current value of t.
                    627:                 */
                    628: 
                    629:                if (nstrcmp(t->n_name, np->n_name) < 0) {
                    630:                        t->n_flink = np;
                    631:                        np->n_blink = t;
                    632:                        t = np;
                    633:                        np = np->n_flink;
                    634:                        t->n_flink = NIL;
                    635:                        continue;
                    636:                }
                    637: 
                    638:                /*
                    639:                 * Otherwise, put the new entry in front of the
                    640:                 * current t.  If at the front of the list,
                    641:                 * the new guy becomes the new head of the list.
                    642:                 */
                    643: 
                    644:                if (t == new) {
                    645:                        t = np;
                    646:                        np = np->n_flink;
                    647:                        t->n_flink = new;
                    648:                        new->n_blink = t;
                    649:                        t->n_blink = NIL;
                    650:                        new = t;
                    651:                        continue;
                    652:                }
                    653: 
                    654:                /*
                    655:                 * The normal case -- we are inserting into the
                    656:                 * middle of the list.
                    657:                 */
                    658: 
                    659:                x = np;
                    660:                np = np->n_flink;
                    661:                x->n_flink = t;
                    662:                x->n_blink = t->n_blink;
                    663:                t->n_blink->n_flink = x;
                    664:                t->n_blink = x;
                    665:        }
                    666: 
                    667:        /*
                    668:         * Now the list headed up by new is sorted.
                    669:         * Go through it and remove duplicates.
                    670:         */
                    671: 
                    672:        np = new;
                    673:        while (np != NIL) {
                    674:                t = np;
                    675:                while (t->n_flink!=NIL &&
                    676:                    icequal(np->n_name,t->n_flink->n_name))
                    677:                        t = t->n_flink;
                    678:                if (t == np || t == NIL) {
                    679:                        np = np->n_flink;
                    680:                        continue;
                    681:                }
                    682:                
                    683:                /*
                    684:                 * Now t points to the last entry with the same name
                    685:                 * as np.  Make np point beyond t.
                    686:                 */
                    687: 
                    688:                np->n_flink = t->n_flink;
                    689:                if (t->n_flink != NIL)
                    690:                        t->n_flink->n_blink = np;
                    691:                np = np->n_flink;
                    692:        }
                    693:        return(new);
                    694: }
                    695: 
                    696: /*
                    697:  * Version of strcmp which ignores case differences.
                    698:  */
                    699: 
                    700: nstrcmp(s1, s2)
                    701:        register char *s1, *s2;
                    702: {
                    703:        register int c1, c2;
                    704: 
                    705:        do {
                    706:                c1 = *s1++;
                    707:                c2 = *s2++;
                    708:        } while (c1 && c1 == c2);
                    709:        return(c1 - c2);
                    710: }
                    711: 
                    712: /*
                    713:  * Put another node onto a list of names and return
                    714:  * the list.
                    715:  */
                    716: 
                    717: struct name *
                    718: put(list, node)
                    719:        struct name *list, *node;
                    720: {
                    721:        node->n_flink = list;
                    722:        node->n_blink = NIL;
                    723:        if (list != NIL)
                    724:                list->n_blink = node;
                    725:        return(node);
                    726: }
                    727: 
                    728: /*
                    729:  * Determine the number of elements in
                    730:  * a name list and return it.
                    731:  */
                    732: 
                    733: count(np)
                    734:        register struct name *np;
                    735: {
                    736:        register int c = 0;
                    737: 
                    738:        while (np != NIL) {
                    739:                c++;
                    740:                np = np->n_flink;
                    741:        }
                    742:        return(c);
                    743: }
                    744: 
                    745: /*
                    746:  * Delete the given name from a namelist.
                    747:  */
                    748: 
                    749: struct name *
                    750: delname(np, name)
                    751:        register struct name *np;
                    752:        char name[];
                    753: {
                    754:        register struct name *p;
                    755: 
                    756:        for (p = np; p != NIL; p = p->n_flink)
                    757:                if (equal(p->n_name, name)) {
                    758:                        if (p->n_blink == NIL) {
                    759:                                if (p->n_flink != NIL)
                    760:                                        p->n_flink->n_blink = NIL;
                    761:                                np = p->n_flink;
                    762:                                continue;
                    763:                        }
                    764:                        if (p->n_flink == NIL) {
                    765:                                if (p->n_blink != NIL)
                    766:                                        p->n_blink->n_flink = NIL;
                    767:                                continue;
                    768:                        }
                    769:                        p->n_blink->n_flink = p->n_flink;
                    770:                        p->n_flink->n_blink = p->n_blink;
                    771:                }
                    772:        return(np);
                    773: }
                    774: 
                    775: /*
                    776:  * Call the given routine on each element of the name
                    777:  * list, replacing said value if need be.
                    778:  */
                    779: 
                    780: mapf(np, from)
                    781:        register struct name *np;
                    782:        char *from;
                    783: {
                    784:        register struct name *p;
                    785: 
                    786:        for (p = np; p != NIL; p = p->n_flink)
                    787:                p->n_name = netmap(p->n_name, from);
                    788: }
                    789: 
                    790: /*
                    791:  * Pretty print a name list
                    792:  * Uncomment it if you need it.
                    793:  */
                    794: 
                    795: prettyprint(name)
                    796:        struct name *name;
                    797: {
                    798:        register struct name *np;
                    799: 
                    800:        np = name;
                    801:        while (np != NIL) {
                    802:                fprintf(stderr, "%s(%d) ", np->n_name, np->n_type);
                    803:                np = np->n_flink;
                    804:        }
                    805:        fprintf(stderr, "\n");
                    806: }

unix.superglobalmegacorp.com

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