Annotation of 43BSD/contrib/nntp/server/newnews.c, revision 1.1

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

unix.superglobalmegacorp.com

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