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