Annotation of 43BSDTahoe/new/nntp/server/newnews.c, revision 1.1.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.