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

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

unix.superglobalmegacorp.com

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