Annotation of 43BSD/ucb/Mail/names.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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