# 2.11BSD#431 - /usr/src/new/nntp/server/newnews.c

##### Functions

    compare           X
    distmatch         X
    get_histlist      X
    get_nglist        X
    getword           X
    newnews           X
    seekuntil         X

##### Variables

    nn_told           X
    nn_took           X

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

#### Defined functions

compare defined in line 317; used 2 times

- in line 281, 301

distmatch defined in line 389; used 1 times

- in line 207

get_histlist defined in line 475; used 1 times

- in line 190

get_nglist defined in line 506; used 3 times

- in line 64
- in /usr/src/new/nntp/server/misc.c line 290
- in /usr/src/new/nntp/server/serve.c line 145

getword defined in line 330; used 2 times

- in line 278, 298

newnews defined in line 22; used 2 times

- in /usr/src/new/nntp/server/serve.c line 24, 40

seekuntil defined in line 258; used 1 times

- in line 157

#### Defined variables

nn_told defined in line 9; used 4 times

- in line 218
- in /usr/src/new/nntp/server/newnews.c line 218
- in /usr/src/new/nntp/server/serve.c line 272-274(2)

nn_took defined in line 10; used 1 times

- in /usr/src/new/nntp/server/serve.c line 274

sccsid defined in line 2; never used

Last modified: 1988-02-07 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1635 |