Annotation of researchv10no/cmd/netnews/src/rfuncs.c, revision 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.