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

unix.superglobalmegacorp.com

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