Annotation of 43BSDTahoe/new/nntp/server/newnews.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char    *sccsid = "@(#)newnews.c        1.16    (Berkeley) 7/17/87";
        !             3: #endif
        !             4: 
        !             5: #include "common.h"
        !             6: #include "time.h"
        !             7: 
        !             8: #ifdef LOG
        !             9: int    nn_told = 0;
        !            10: int    nn_took = 0;
        !            11: #endif
        !            12: 
        !            13: 
        !            14: /*
        !            15:  * NEWNEWS newsgroups date time ["GMT"] [<distributions>]
        !            16:  *
        !            17:  * Return the message-id's of any news articles past
        !            18:  * a certain date and time, within the specified distributions.
        !            19:  *
        !            20:  */
        !            21: 
        !            22: newnews(argc, argv)
        !            23:        register int    argc;
        !            24:        char            *argv[];
        !            25: {
        !            26:        register char   *cp, *ngp;
        !            27:        char            *key;
        !            28:        char            datebuf[32];
        !            29:        char            line[MAX_STRLEN];
        !            30:        char            **distlist, **histlist;
        !            31:        static char     **nglist;
        !            32:        int             distcount, ngcount, histcount;
        !            33:        int             all;
        !            34:        FILE            *fp;
        !            35:        long            date;
        !            36:        long            dtol();
        !            37:        char            *ltod();
        !            38: 
        !            39:        if (argc < 4) {
        !            40:                printf("%d Usage: NEWNEWS newsgroups yymmdd hhmmss [\"GMT\"] [<distributions>].\r\n",
        !            41:                        ERR_CMDSYN);
        !            42:                (void) fflush(stdout);
        !            43:                return;
        !            44:        }
        !            45: 
        !            46: #ifdef LOG
        !            47:        sprintf(line, "%s newnews %s %s %s %s %s",
        !            48:                hostname,
        !            49:                argv[1],
        !            50:                argv[2],
        !            51:                argv[3],
        !            52:                (argc >= 5 && *argv[4] == 'G') ? "GMT" : "local",
        !            53:                (argc >= 5 && *argv[argc-1] == '<') ? argv[argc-1] : "none");
        !            54:        syslog(LOG_INFO, line);
        !            55: #endif
        !            56: 
        !            57:        all = streql(argv[1], "*");
        !            58:        if (!all) {
        !            59:                ngcount = get_nglist(&nglist, argv[1]);
        !            60:                if (ngcount == 0) {
        !            61:                        printf("%d Bogus newsgroup specifier: %s\r\n",
        !            62:                                ERR_CMDSYN, argv[1]);
        !            63:                        (void) fflush(stdout);
        !            64:                        return;
        !            65:                }
        !            66:        }
        !            67: 
        !            68:        /*          YYMMDD                  HHMMSS      */
        !            69:        if (strlen(argv[2]) != 6 || strlen(argv[3]) != 6) {
        !            70:                printf("%d Date/time must be in form YYMMDD HHMMSS.\r\n",
        !            71:                        ERR_CMDSYN);
        !            72:                (void) fflush(stdout);
        !            73:                return;
        !            74:        }
        !            75: 
        !            76:        (void) strcpy(datebuf, argv[2]);
        !            77:        (void) strcat(datebuf, argv[3]);
        !            78: 
        !            79:        argc -= 4;
        !            80:        argv += 4;
        !            81: 
        !            82:        /*
        !            83:         * Flame on.  The history file is not stored in GMT, but
        !            84:         * in local time.  So we have to convert GMT to local time
        !            85:         * if we're given GMT, otherwise we need only chop off the
        !            86:         * the seconds.  Such braindamage.
        !            87:         */
        !            88: 
        !            89:        key = datebuf;          /* Unless they specify GMT */
        !            90: 
        !            91:        if (argc > 0) {
        !            92:                if (streql(*argv, "GMT")) {     /* Which we handle here */
        !            93:                        date = dtol(datebuf);
        !            94:                        if (date < 0) {
        !            95:                                printf("%d Invalid date specification.\r\n",
        !            96:                                        ERR_CMDSYN);
        !            97:                                (void) fflush(stdout);
        !            98:                                return;
        !            99:                        }
        !           100:                        date = gmt_to_local(date);
        !           101:                        key = ltod(date);
        !           102:                        ++argv;
        !           103:                        --argc;
        !           104:                }
        !           105:        }
        !           106: 
        !           107:        /* So, key now points to the local time, but we need to zap secs */
        !           108: 
        !           109:        key[10] = '\0';
        !           110: 
        !           111:        distcount = 0;
        !           112:        if (argc > 0) {
        !           113:                distcount = get_distlist(&distlist, *argv);
        !           114:                if (distcount < 0) {
        !           115:                        printf("%d Bad distribution list: %s\r\n", ERR_CMDSYN,
        !           116:                                *argv);
        !           117:                        (void) fflush(stdout);
        !           118:                        return;
        !           119:                }
        !           120:        }
        !           121: 
        !           122:        fp = fopen(historyfile, "r");
        !           123:        if (fp == NULL) {
        !           124: #ifdef SYSLOG
        !           125:                syslog(LOG_ERR, "newnews: fopen %s: %m", historyfile);
        !           126: #endif
        !           127:                printf("%d Cannot open history file.\r\n", ERR_FAULT);
        !           128:                (void) fflush(stdout);
        !           129:                return;
        !           130:        }
        !           131: 
        !           132:        printf("%d New news by message id follows.\r\n", OK_NEWNEWS);
        !           133: 
        !           134:        if (seekuntil(fp, key, line, sizeof (line)) < 0) {
        !           135:                printf(".\r\n");
        !           136:                (void) fflush(stdout);
        !           137:                (void) fclose(fp);
        !           138:                return;
        !           139:        }
        !           140: 
        !           141: /*
        !           142:  * History file looks like:
        !           143:  *
        !           144:  * <[email protected]>   01/22/86 09:19  net.micro.att/899 ucb.general/2545 
        !           145:  *                  ^--tab            ^--tab            ^--space         ^sp\0
        !           146:  * Sometimes the newsgroups are missing; we try to be robust and
        !           147:  * ignore such bogosity.  We tackle this by our usual parse routine,
        !           148:  * and break the list of articles in the history file into an argv
        !           149:  * array with one newsgroup per entry.
        !           150:  */
        !           151: 
        !           152:        do {
        !           153:                if ((cp = index(line, '\t')) == NULL)
        !           154:                        continue;
        !           155: 
        !           156:                if ((ngp = index(cp+1, '\t')) == NULL)  /* 2nd tab */
        !           157:                        continue;
        !           158:                ++ngp;                  /* Points at newsgroup list */
        !           159:                if (*ngp == '\n')
        !           160:                        continue;
        !           161:                histcount = get_histlist(&histlist, ngp);
        !           162:                if (histcount == 0)
        !           163:                        continue;
        !           164: 
        !           165:                /*
        !           166:                 * For each newsgroup on this line in the history
        !           167:                 * file, check it against the newsgroup names we're given.
        !           168:                 * If it matches, then see if we're hacking distributions.
        !           169:                 * If so, open the file and match the distribution line.
        !           170:                 */
        !           171: 
        !           172:                if (!all)
        !           173:                        if (!ngmatch(restreql, 0, nglist, ngcount,
        !           174:                            histlist, histcount))
        !           175:                                continue;
        !           176: 
        !           177:                if (distcount)
        !           178:                        if (!distmatch(distlist, distcount, histlist, histcount))
        !           179:                                continue;
        !           180: 
        !           181:                *cp = '\0';
        !           182:                putline(line);
        !           183: #ifdef LOG
        !           184:                nn_told++;
        !           185: #endif
        !           186:        } while (fgets(line, sizeof(line), fp) != NULL);
        !           187: 
        !           188:        putchar('.');
        !           189:        putchar('\r');
        !           190:        putchar('\n');
        !           191:        (void) fflush(stdout);
        !           192:        (void) fclose(fp);
        !           193: }
        !           194: 
        !           195: 
        !           196: /*
        !           197:  * seekuntil -- seek through the history file looking for
        !           198:  * a line with date "key".  Get that line, and return.
        !           199:  *
        !           200:  *     Parameters:     "fp" is the active file.
        !           201:  *                     "key" is the date, in form YYMMDDHHMM (no SS)
        !           202:  *                     "line" is storage for the first line we find.
        !           203:  *
        !           204:  *     Returns:        -1 on error, 0 otherwise.
        !           205:  *
        !           206:  *     Side effects:   Seeks in history file, modifies line.
        !           207:  */
        !           208: 
        !           209: seekuntil(fp, key, line, linesize)
        !           210:        FILE            *fp;
        !           211:        char            *key;
        !           212:        char            *line;
        !           213:        int             linesize;
        !           214: {
        !           215:        char            datetime[32];
        !           216:        register int    c;
        !           217:        register long   top, bot, mid;
        !           218: 
        !           219:        bot = 0;
        !           220:        (void) fseek(fp, 0L, 2);
        !           221:        top = ftell(fp);
        !           222:        for(;;) {
        !           223:                mid = (top+bot)/2;
        !           224:                (void) fseek(fp, mid, 0);
        !           225:                do {
        !           226:                        c = getc(fp);
        !           227:                        mid++;
        !           228:                } while (c != EOF && c!='\n');
        !           229:                if (!getword(fp, datetime, line, linesize)) {
        !           230:                        return (-1);
        !           231:                }
        !           232:                switch (compare(key, datetime)) {
        !           233:                case -2:
        !           234:                case -1:
        !           235:                case 0:
        !           236:                        if (top <= mid)
        !           237:                                break;
        !           238:                        top = mid;
        !           239:                        continue;
        !           240:                case 1:
        !           241:                case 2:
        !           242:                        bot = mid;
        !           243:                        continue;
        !           244:                }
        !           245:                break;
        !           246:        }
        !           247:        (void) fseek(fp, bot, 0);
        !           248:        while(ftell(fp) < top) {
        !           249:                if (!getword(fp, datetime, line, linesize)) {
        !           250:                        return (-1);
        !           251:                }
        !           252:                switch(compare(key, datetime)) {
        !           253:                case -2:
        !           254:                case -1:
        !           255:                case 0:
        !           256:                        break;
        !           257:                case 1:
        !           258:                case 2:
        !           259:                        continue;
        !           260:                }
        !           261:                break;
        !           262:        }
        !           263: 
        !           264:        return (0);
        !           265: }
        !           266: 
        !           267: 
        !           268: compare(s, t)
        !           269:        register char *s, *t;
        !           270: {
        !           271:        for (; *s == *t; s++, t++)
        !           272:                if (*s == 0)
        !           273:                        return(0);
        !           274:        return (*s == 0 ? -1:
        !           275:                *t == 0 ? 1:
        !           276:                *s < *t ? -2:
        !           277:                2);
        !           278: }
        !           279: 
        !           280: 
        !           281: getword(fp, w, line, linesize)
        !           282:        FILE            *fp;
        !           283:        register char   *w;
        !           284:        char            *line;
        !           285:        int             linesize;
        !           286: {
        !           287:        register char   *cp;
        !           288: 
        !           289:        if (fgets(line, linesize, fp) == NULL)
        !           290:                return (0);
        !           291:        if (cp = index(line, '\t')) {
        !           292: /*
        !           293:  * The following gross hack is present because the history file date
        !           294:  * format is braindamaged.  They like "mm/dd/yy hh:mm", which is useless
        !           295:  * for relative comparisons of dates using something like atoi() or
        !           296:  * strcmp.  So, this changes their format into yymmddhhmm.  Sigh.
        !           297:  *
        !           298:  * 12345678901234      ("x" for cp[x])
        !           299:  * mm/dd/yy hh:mm      (their lousy representation)
        !           300:  * yymmddhhmm          (our good one)
        !           301:  * 0123456789          ("x" for w[x])
        !           302:  */
        !           303:                *cp = '\0';
        !           304:                (void) strncpy(w, cp+1, 15);
        !           305:                w[0] = cp[7];           /* Years */
        !           306:                w[1] = cp[8];
        !           307:                w[2] = cp[1];           /* Months */
        !           308:                w[3] = cp[2];
        !           309:                w[4] = cp[4];           /* Days */
        !           310:                w[5] = cp[5];
        !           311:                w[6] = cp[10];          /* Hours */
        !           312:                w[7] = cp[11];
        !           313:                w[8] = cp[13];          /* Minutes */
        !           314:                w[9] = cp[14];
        !           315:                w[10] = '\0';
        !           316:        } else
        !           317:                w[0] = '\0';
        !           318:        return (1);
        !           319: }
        !           320: 
        !           321: 
        !           322: /*
        !           323:  * distmatch -- see if a file matches a set of distributions.
        !           324:  * We have to do this by (yech!) opening the file, finding
        !           325:  * the Distribution: line, if it has one, and seeing if the
        !           326:  * things match.
        !           327:  *
        !           328:  *     Parameters:     "distlist" is the distribution list
        !           329:  *                     we want.
        !           330:  *                     "distcount" is the count of distributions in it.
        !           331:  *                     "grouplist" is the list of groups (articles)
        !           332:  *                     for this line of the history file.  Note that
        !           333:  *                     this isn't quite a filename.
        !           334:  *                     "groupcount" is the count of groups in it.
        !           335:  *                     
        !           336:  *     Returns:        1 if the article is in the given distribution.
        !           337:  *                     0 otherwise.
        !           338:  */
        !           339: 
        !           340: distmatch(distlist, distcount, grouplist, groupcount)
        !           341:        char            *distlist[];
        !           342:        int             distcount;
        !           343:        char            *grouplist[];
        !           344:        int             groupcount;
        !           345: {
        !           346:        register char   c;
        !           347:        register char   *cp;
        !           348:        register FILE   *fp;
        !           349:        register int    i, j;
        !           350:        char            buf[MAX_STRLEN];
        !           351: 
        !           352:        (void) strcpy(buf, spooldir);
        !           353:        (void) strcat(buf, "/");
        !           354:        (void) strcat(buf, grouplist[0]);
        !           355: 
        !           356:        for (cp = buf; *cp; cp++)
        !           357:                if (*cp == '.')
        !           358:                        *cp = '/';
        !           359: 
        !           360:        fp = fopen(buf, "r");
        !           361:        if (fp == NULL) {
        !           362: #ifdef SYSLOG
        !           363:                syslog(LOG_ERR, "distmatch: fopen %s: %m", buf);
        !           364: #endif
        !           365:                return (0);
        !           366:        }
        !           367: 
        !           368:        while (fgets(buf, sizeof (buf), fp) != NULL) {
        !           369:                if ((c = buf[0]) == '\n')               /* End of header */
        !           370:                        break;
        !           371:                if (c != 'd' && c != 'D')
        !           372:                        continue;
        !           373:                cp = index(cp + 1, '\n');
        !           374:                if (cp)
        !           375:                        *cp = '\0';
        !           376:                cp = index(buf, ':');
        !           377:                if (cp == NULL)
        !           378:                        continue;
        !           379:                *cp = '\0';
        !           380:                if (streql(buf, "distribution")) {
        !           381:                        for (i = 0; i < distcount; ++i) {
        !           382:                                if (streql(cp + 2, distlist[i])) {
        !           383:                                        (void) fclose(fp);
        !           384:                                        return (1);
        !           385:                                }
        !           386:                        }
        !           387:                        (void) fclose(fp);
        !           388:                        return (0);
        !           389:                }
        !           390:        }
        !           391: 
        !           392:        (void) fclose(fp);
        !           393: 
        !           394:        /*
        !           395:         * We've finished the header with no distribution field.
        !           396:         * So we'll assume that the distribution is the characters
        !           397:         * up to the first dot in the newsgroup name.
        !           398:         */
        !           399: 
        !           400:        for (i = 0; i < groupcount; i++) {
        !           401:                cp = index(grouplist[i], '.');
        !           402:                if (cp)
        !           403:                        *cp = '\0';
        !           404:                for (j = 0; j < distcount; j++)
        !           405:                        if (streql(grouplist[i], distlist[j]))
        !           406:                                return (1);
        !           407:        }
        !           408:                
        !           409:        return (0);
        !           410: }
        !           411: 
        !           412: 
        !           413: /*
        !           414:  * get_histlist -- return a nicely set up array of newsgroups
        !           415:  * (actually, net.foo.bar/article_num) along with a count.
        !           416:  *
        !           417:  *     Parameters:             "array" is storage for our array,
        !           418:  *                             set to point at some static data.
        !           419:  *                             "list" is the history file newsgroup list.
        !           420:  *
        !           421:  *     Returns:                Number of group specs found.
        !           422:  *
        !           423:  *     Side effects:           Changes static data area.
        !           424:  */
        !           425: 
        !           426: get_histlist(array, list)
        !           427:        char            ***array;
        !           428:        char            *list;
        !           429: {
        !           430:        register int    histcount;
        !           431:        register char   *cp;
        !           432:        static  char    **hist_list = (char **) NULL;
        !           433: 
        !           434:        cp = index(list, '\n');
        !           435:        if (cp)
        !           436:                *cp-- = '\0';
        !           437:        histcount = parsit(list, &hist_list);
        !           438:        *array = hist_list;
        !           439:        return (histcount);
        !           440: }
        !           441: 
        !           442: 
        !           443: /*
        !           444:  * get_nglist -- return a nicely set up array of newsgroups
        !           445:  * along with a count, when given an NNTP-spec newsgroup list
        !           446:  * in the form ng1,ng2,ng...
        !           447:  *
        !           448:  *     Parameters:             "array" is storage for our array,
        !           449:  *                             set to point at some static data.
        !           450:  *                             "list" is the NNTP newsgroup list.
        !           451:  *
        !           452:  *     Returns:                Number of group specs found.
        !           453:  *
        !           454:  *     Side effects:           Changes static data area.
        !           455:  */
        !           456: 
        !           457: get_nglist(array, list)
        !           458:        char            ***array;
        !           459:        char            *list;
        !           460: {
        !           461:        register char   *cp;
        !           462:        register int    ngcount;
        !           463: 
        !           464:        for (cp = list; *cp != '\0'; ++cp)
        !           465:                if (*cp == ',')
        !           466:                        *cp = ' ';
        !           467: 
        !           468:        ngcount = parsit(list, array);
        !           469: 
        !           470:        return (ngcount);
        !           471: }

unix.superglobalmegacorp.com

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