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

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

unix.superglobalmegacorp.com

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