Annotation of researchv10no/cmd/netnews/src/rfuncs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * rfuncs - functions for readnews.
                      3:  */
                      4: 
                      5: static char    *SccsId = "@(#)rfuncs.c 2.9     3/7/83";
                      6: 
                      7: #include "rparams.h"
                      8: 
                      9: long nngsize;  /* The next upcoming value of ngsize. */
                     10: 
                     11: nextng() 
                     12: {
                     13:        long    curpos;
                     14: #ifdef DEBUG
                     15:        fprintf(stderr, "nextng()\n");
                     16: #endif
                     17:        curpos = ftell(actfp);
                     18: 
                     19: next:
                     20: #ifdef DEBUG
                     21:        fprintf(stderr, "next:\n");
                     22: #endif
                     23:        if (actdirect == BACKWARD) {
                     24:                if (back()) {
                     25:                        fseek(actfp, curpos, 0);
                     26:                        return 1;
                     27:                }
                     28:                if (back()) {
                     29:                        fseek(actfp, curpos, 0);
                     30:                        return 1;
                     31:                }
                     32:        }
                     33:        if (fgets(afline, BUFLEN, actfp) == NULL)
                     34:                return 1;
                     35:        sscanf(afline, "%s %ld", bfr, &nngsize);
                     36: #ifdef DEBUG
                     37:        fprintf(stderr, "bfr = '%s'\n", bfr);
                     38: #endif
                     39: 
                     40:        ngcat(bfr);
                     41:        if (!ngmatch(bfr, header.nbuf))
                     42:                goto next;
                     43:        ngdel(bfr);
                     44:        if (xflag)
                     45:                readmode = SPEC;
                     46:        else
                     47:                readmode = NEXT;
                     48:        if (selectng(bfr))
                     49:                goto next;
                     50:        return 0;
                     51: }
                     52: 
                     53: 
                     54: selectng(name)
                     55: char   *name;
                     56: {
                     57:        register char   *ptr, punct = ',';
                     58:        register int    cur = 0, i;
                     59:        register char   *p;
                     60:        int     next = 0;
                     61:        char    oldptr;
                     62:        long    findngsize();
                     63: 
                     64:        if (*groupdir)
                     65:                updaterc();
                     66:        last = 1;
                     67:        if (strcmp(name, bfr))
                     68:                ngsize = findngsize(name);
                     69:        else
                     70:                ngsize = nngsize;
                     71: #ifdef DEBUG
                     72:        fprintf(stderr, "selectng(%s) sets ngsize to %ld\n", name, ngsize);
                     73: #endif
                     74:        strcpy(groupdir, name);
                     75:        if (!xflag) {
                     76:                i = findrcline(name);
                     77:                if (i >= 0) {
                     78:                        if (index(rcline[i], '!')) {
                     79:                                groupdir[0] = 0;
                     80:                                return 1;
                     81:                        }
                     82:                        sprintf(rcbuf, "%s,%ld", rcline[i], ngsize+1);
                     83:                }
                     84:                else
                     85:                        sprintf(rcbuf, "ng: %ld", ngsize+1);
                     86:        }
                     87: 
                     88:        /*
                     89:         * Fast check for common case: 1-###
                     90:         */
                     91:        p = rcbuf;
                     92:        while (*p != ' ')
                     93:                p++;
                     94:        while (*p == ' ')
                     95:                p++;
                     96:        if (*p++ == '1' && *p++ == '-') {
                     97:                i = 0;
                     98:                while (isdigit(*p))
                     99:                        i = 10 * i + *p++ - '0';
                    100:                if (*p == ',' && i >= ngsize) {
                    101:                        groupdir[0] = 0;
                    102:                        return 1;
                    103:                }
                    104:        }
                    105: 
                    106: /*
                    107:  * The key to understanding this piece of code is that a bit is set iff
                    108:  * that article has NOT been read.  Thus, we fill in the holes when
                    109:  * commas are found (e.g. 1-20,30-35 will result in filling in the 21-29
                    110:  * hold), and so we assume the newsrc file is properly ordered, the way
                    111:  * we write it out. 
                    112:  */
                    113:        cur = 0;
                    114:        /* Zero out the bitmap */
                    115:        p = &bitmap[ngsize/8+1];
                    116:        for (ptr = bitmap; ptr <= p; ptr)
                    117:                *ptr++ = 0;
                    118: 
                    119:        /* Decode the .newsrc line indicating what we have read. */
                    120:        for (ptr = rcbuf; *ptr && *ptr != ':'; ptr++)
                    121:                ;
                    122:        while (*ptr) {
                    123:                while (!isdigit(*ptr) && *ptr)
                    124:                        ptr++;
                    125:                if (!*ptr)
                    126:                        break;
                    127:                sscanf(ptr, "%d", &next);
                    128:                if (punct == ',') {
                    129:                        while (++cur < next) {
                    130:                                set(cur);
                    131:                        }
                    132:                }
                    133:                cur = next;
                    134:                while (!ispunct(*ptr) && *ptr)
                    135:                        ptr++;
                    136:                punct = *ptr;
                    137:        }
                    138:        if (rflag)
                    139:                bit = ngsize+1;
                    140:        else
                    141:                bit = 0;
                    142:        nextbit();
                    143:        ngrp = 1;
                    144:        return 0;
                    145: }
                    146: 
                    147: /*
                    148:  * Figure out the number of the largest article in newsgroup ng,
                    149:  * and return that value.
                    150:  */
                    151: long
                    152: findngsize(ng)
                    153: char *ng;
                    154: {
                    155:        FILE *af;
                    156:        long s;
                    157:        char buf[100], n[100];
                    158: 
                    159:        af = xfopen(ACTIVE, "r");
                    160:        while (fgets(buf, sizeof buf, af)) {
                    161:                sscanf(buf, "%s %ld", n, &s);
                    162:                if (strcmp(n, ng) == 0) {
                    163:                        fclose(af);
                    164:                        return s;
                    165:                }
                    166:        }
                    167:        return 0;
                    168: }
                    169: 
                    170: #ifdef TMAIL
                    171: catchterm()
                    172: {
                    173:        unlink(infile);
                    174:        unlink(outfile);
                    175:        xxit(0);
                    176: }
                    177: 
                    178: 
                    179: /*
                    180:  * The -M (Mail) interface.  This code is a reasonably simple model for
                    181:  * writing other interfaces.  We write out all relavent articles to
                    182:  * a temp file, then invoke Mail with an option to have it tell us which
                    183:  * articles it read.  Finally we count those articles as really read.
                    184:  */
                    185: Mail()
                    186: {
                    187:        register FILE *fp = NULL, *ofp;
                    188:        struct hbuf h;
                    189:        register char   *ptr, *fname;
                    190:        int     news = 0;
                    191: 
                    192:        ofp = xfopen(mktemp(outfile), "w");
                    193:        if (aflag && *datebuf)
                    194:                if ((atime = cgtdate(datebuf)) == -1)
                    195:                        xerror("Cannot parse date string");
                    196:        while (!nextng())
                    197:                while (bit <= ngsize) {
                    198:                        sprintf(filename, "%s/%d", dirname(groupdir), bit);
                    199:                        if (access(filename, 4)
                    200:                        || ((fp = fopen(filename, "r")) == NULL)
                    201:                        || (hread(&h, fp, TRUE) == NULL)
                    202:                        || !select(&h, FALSE)) {
                    203: #ifdef DEBUG
                    204:                                fprintf(stderr, "Bad article '%s'\n", filename);
                    205: #endif
                    206:                                if (fp != NULL) {
                    207:                                        fclose(fp);
                    208:                                        fp = NULL;
                    209:                                }
                    210:                                clear(bit);
                    211:                                nextbit();
                    212:                                continue;
                    213:                        }
                    214:                        fname = ptr = index(h.from, '(');
                    215:                        if (fname) {
                    216:                                while (ptr && ptr[-1] == ' ')
                    217:                                        ptr--;
                    218:                                if (ptr)
                    219:                                        *ptr = 0;
                    220:                                fname++;
                    221:                                ptr = fname + strlen(fname) - 1;
                    222:                                if (*ptr == ')')
                    223:                                        *ptr = 0;
                    224:                        }
                    225:                        h.subtime = cgtdate(h.subdate);
                    226:                        fprintf(ofp, "From %s %s",
                    227: #ifdef INTERNET
                    228:                            h.from[0] ? h.from :
                    229: #endif
                    230:                            h.path, ctime(&h.subtime));
                    231:                        if (fname)
                    232:                                fprintf(ofp, "Full-Name: %s\n", fname);
                    233:                        fprintf(ofp, "Newsgroups: %s\n", h.nbuf);
                    234:                        fprintf(ofp, "Subject: %s\n", h.title);
                    235:                        fprintf(ofp, "Article-ID: %s/%d\n\n", groupdir, bit);
                    236:                        tprint(fp, ofp, TRUE);
                    237:                        putc('\n', ofp);
                    238:                        news = TRUE;
                    239:                        fclose(fp);
                    240:                        fp = NULL;
                    241:                        nextbit();
                    242:                }
                    243:        updaterc();
                    244:        fclose(ofp);
                    245:        if (!news) {
                    246:                fprintf(stderr, "No news.\n");
                    247:                unlink(outfile);
                    248:                return;
                    249:        }
                    250:        signal(SIGHUP, catchterm);
                    251:        signal(SIGTERM, catchterm);
                    252:        sprintf(bfr, "%s -f %s -T %s", TMAIL, outfile, mktemp(infile));
                    253:        fwait(fsubr(ushell, bfr, (char *)NULL));
                    254:        ofp = xfopen(infile, "r");
                    255:        fseek(actfp, 0L, 0);
                    256:        while (fgets(afline, BUFLEN, actfp) != NULL) {
                    257:                last = 0;
                    258:                sscanf(afline, "%s %ld", bfr, &nngsize);
                    259:                ngcat(bfr);
                    260:                if (!ngmatch(bfr, header.nbuf))
                    261:                        continue;
                    262:                ngdel(bfr);
                    263:                *groupdir = 0;
                    264:                if (selectng(bfr))
                    265:                        continue;
                    266:                fseek(ofp, 0L, 0);
                    267:                while (fgets(groupdir, BUFLEN, ofp) != NULL) {
                    268:                        nstrip(groupdir);
                    269:                        ptr = index(groupdir, '/');
                    270:                        *ptr = 0;
                    271:                        if (strcmp(bfr, groupdir))
                    272:                                continue;
                    273:                        sscanf(++ptr, "%d", &last);
                    274:                        clear(last);
                    275:                }
                    276:                if (last) {
                    277:                        strcpy(groupdir, bfr);
                    278:                        updaterc();
                    279:                }
                    280:        }
                    281:        unlink(infile);
                    282:        unlink(outfile);
                    283: }
                    284: #endif
                    285: 
                    286: updaterc()
                    287: {
                    288:        register int    cur = 1, next = 1, i;
                    289:        register char   *ptr;
                    290:        char    oldptr;
                    291: 
                    292:        sprintf(rcbuf, "%s%c ", groupdir, zapng ? '!' : ':');
                    293: 
                    294:        zapng = FALSE;
                    295: again:
                    296:        ptr = &rcbuf[strlen(rcbuf)];
                    297:        while (get(next))
                    298:                next++;
                    299:        cur = next;
                    300:        while (!(get(next)) && next <= ngsize)
                    301:                next++;
                    302:        if (cur == next) {
                    303:                next = 8193;
                    304:                goto skip;
                    305:        }
                    306:        if (cur + 1 == next)
                    307:                sprintf(ptr, "%d,", cur);
                    308:        else
                    309:                sprintf(ptr, "%d-%d,", cur, next - 1);
                    310: skip:
                    311:        if ((long) next > ngsize) {
                    312:                if (index(rcbuf, ',') != NULL)
                    313:                        ngdel(rcbuf);
                    314:                else if (index(rcbuf, '!') == NULL)
                    315:                        return;
                    316:                ptr = index(rcbuf, ' ');
                    317:                ptr--;
                    318:                oldptr = *ptr;
                    319:                ptr[0] = ':';
                    320:                ptr[1] = '\0';
                    321:                i = findrcline(groupdir);
                    322:                if (i >= 0) {
                    323:                        ptr[0] = oldptr;
                    324:                        ptr[1] = ' ';
                    325:                        rcline[i] = realloc(rcline[i], strlen(rcbuf) + 1);
                    326:                        if (rcline[i] == NULL)
                    327:                                xerror("Cannot realloc");
                    328:                        strcpy(rcline[i], rcbuf);
                    329:                        return;
                    330:                }
                    331:                if (++line > LINES)
                    332:                        xerror("Too many newsgroups\n");
                    333:                ptr[0] = oldptr;
                    334:                ptr[1] = ' ';
                    335:                if ((rcline[line] = malloc(strlen(rcbuf) + 1)) == NULL)
                    336:                        xerror("Not enough memory");
                    337:                strcpy(rcline[line], rcbuf);
                    338:                return;
                    339:        }
                    340:        cur = next;
                    341:        goto again;
                    342: }
                    343: 
                    344: 
                    345: newrc(rcname)
                    346: {
                    347:        register FILE *fp;
                    348: 
                    349:        if (close(creat(rcname, 0666))) {
                    350:                sprintf(bfr, "Cannot create %s", newsrc);
                    351:                xerror(bfr);
                    352:        }
                    353: 
                    354:        if ((fp = fopen(USERS, "a")) != NULL) {
                    355:                fprintf(fp, "%s\n", username);
                    356:                fclose(fp);
                    357:                chmod(USERS, 0666);
                    358:        }
                    359: }
                    360: 
                    361: 
                    362: xerror(message)
                    363: char   *message;
                    364: {
                    365:        fflush(stdout);
                    366:        fprintf(stderr, "readnews: %s.\n", message);
                    367:        xxit(1);
                    368: }
                    369: 
                    370: 
                    371: nextbit() 
                    372: {
                    373:        last = bit;
                    374:        if (readmode == SPEC || xflag) {
                    375:                if (rflag)
                    376:                        bit--;
                    377:                else
                    378:                        bit++;
                    379:                return;
                    380:        }
                    381:        if (rflag)
                    382:                while (--bit, !get(bit) && bit > 0)
                    383:                        ;
                    384:        else
                    385:                while (++bit, !get(bit) && bit <= ngsize)
                    386:                        ;
                    387: }
                    388: 
                    389: 
                    390: xxit(status)
                    391: int    status;
                    392: {
                    393:        unlink(infile);
                    394:        unlink(outfile);
                    395:        exit(status);
                    396: }
                    397: 
                    398: 
                    399: /*
                    400:  * Return TRUE if the user has not ruled out this article.
                    401:  */
                    402: select(hp, insist)
                    403: register struct hbuf *hp;
                    404: int    insist;
                    405: {
                    406:        if (insist)
                    407:                return TRUE;
                    408:        if (tflag && !titmat(hp, header.title))
                    409:                return FALSE;
                    410:        if (aflag && cgtdate(hp->recdate) < atime)
                    411:                return FALSE;
                    412:        if (index(hp->nbuf, ',') && seenbefore(hp->ident))
                    413:                return FALSE;
                    414:        if (fflag && isfol(hp))
                    415:                return FALSE;
                    416:        return TRUE;
                    417: }
                    418: 
                    419: 
                    420: /*
                    421:  * Return TRUE if this article is a followup to something.
                    422:  */
                    423: isfol(hp)
                    424: register struct hbuf *hp;
                    425: {
                    426:        if (hp->followid[0])
                    427:                return TRUE;
                    428:        if (strncmp(hp->title, "Re:", 3) == 0)
                    429:                return TRUE;
                    430:        return FALSE;
                    431: }
                    432: 
                    433: 
                    434: /*
                    435:  * Given an article ID, return TRUE if we have already seen that article ID
                    436:  * in this readnews session.  This should only be called for articles
                    437:  * with commas in the newsgroup name, and prevents the same article, which
                    438:  * was submitted to multiple newsgroups, from being shown to the same
                    439:  * person more than once.  Bug: if the user quits after seeing the first
                    440:  * copy, he'll see it again next time in the other newsgroup.
                    441:  */
                    442: #define NART   100     /* max # articles on multiple newsgroups */
                    443: static int     nbef = 0;
                    444: static char    *histbuf[NART];
                    445: static char    nextabuf[BUFLEN];
                    446: seenbefore(artid)
                    447: char   *artid;
                    448: {
                    449:        register int    i;
                    450: 
                    451:        for (i = 0; i < nbef; i++)
                    452:                if (strcmp(histbuf[i], artid) == 0)
                    453:                        return TRUE;
                    454:        if (nbef >= NART - 1) {
                    455:                return FALSE;
                    456:        }
                    457:        /* Remember the name, but don't record it as saved yet. */
                    458:        strcpy(nextabuf, artid);
                    459:        return FALSE;
                    460: }
                    461: 
                    462: /*
                    463:  * The current article has actually been looked at, so record it as such.
                    464:  */
                    465: itsbeenseen(artid)
                    466: char *artid;
                    467: {
                    468:        if (nextabuf[0] == '\0')
                    469:                return;
                    470:        if (strcmp(artid, nextabuf) == 0) {
                    471:                histbuf[nbef] = (char *) malloc(strlen(artid)+1);
                    472:                strcpy(histbuf[nbef++], artid);
                    473:        }
                    474:        nextabuf[0] = '\0';
                    475: }
                    476: 
                    477: back() 
                    478: {
                    479:        while (fseek(actfp, -2L, 1) != -1 && ftell(actfp) > 0L) {
                    480:                if (getc(actfp) == '\n')
                    481:                        return 0;
                    482:        }
                    483:        if (ftell(actfp) == 0L)
                    484:                return 0;
                    485:        return 1;
                    486: }
                    487: 
                    488: /*
                    489:  * Copy from one header structure to another.
                    490:  * Really should just copy memory, if we had a memcpy.
                    491:  */
                    492: hbufcp(hbuf2, hbuf1)
                    493: register struct hbuf *hbuf1, *hbuf2;
                    494: {
                    495:        strcpy(hbuf2->path, hbuf1->path);
                    496:        strcpy(hbuf2->from, hbuf1->from);
                    497:        strcpy(hbuf2->replyto, hbuf1->replyto);
                    498:        strcpy(hbuf2->nbuf, hbuf1->nbuf);
                    499:        strcpy(hbuf2->title, hbuf1->title);
                    500:        strcpy(hbuf2->ident, hbuf1->ident);
                    501:        strcpy(hbuf2->subdate, hbuf1->subdate);
                    502:        strcpy(hbuf2->recdate, hbuf1->recdate);
                    503:        strcpy(hbuf2->expdate, hbuf1->expdate);
                    504:        hbuf2->subtime = hbuf1->subtime;
                    505:        hbuf2->rectime = hbuf1->rectime;
                    506:        hbuf2->exptime = hbuf1->exptime;
                    507: }
                    508: 
                    509: 
                    510: /*
                    511:  * Trap interrupts.
                    512:  */
                    513: onsig(n)
                    514: int    n;
                    515: {
                    516:        signal(n, onsig);
                    517:        sigtrap = n;
                    518:        if (rcreadok < 2) {
                    519:                exit(0);
                    520:        }
                    521: }
                    522: 
                    523: /*
                    524:  * finds the line in your .newsrc file (actually the in-core "rcline"
                    525:  * copy of it) and returns the index into the array where it was found.
                    526:  * -1 means it didn't find it.
                    527:  *
                    528:  * We play clever games here to make this faster.  It's inherently
                    529:  * quadratic - we spend lots of CPU time here because we search through
                    530:  * the whole .newsrc for each line.  The "prev" variable remembers where
                    531:  * the last match was found; we start the search there and loop around
                    532:  * to the beginning, in the hopes that the calls will be roughly in order.
                    533:  */
                    534: int
                    535: findrcline(name)
                    536: char *name;
                    537: {
                    538:        register char *p, *ptr;
                    539:        register int cur;
                    540:        register int i;
                    541:        register int top;
                    542:        static int prev = 0;
                    543: 
                    544:        top = line; i = prev;
                    545: loop:
                    546:        for (; i <= top; i++) {
                    547:                for (p = name, ptr = rcline[i]; (cur = *p++); ) {
                    548:                        if (cur != *ptr++)
                    549:                                goto contin2;
                    550:                }
                    551:                if (*ptr != ':' && *ptr != '!')
                    552:                        continue;
                    553:                prev = i;
                    554:                return i;
                    555: contin2:
                    556:                ;
                    557:        }
                    558:        if (i > line && line > prev-1) {
                    559:                i = 0;
                    560:                top = prev-1;
                    561:                goto loop;
                    562:        }
                    563:        return -1;
                    564: }

unix.superglobalmegacorp.com

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