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
distmatch defined in line 389; used 1 times
get_histlist defined in line 475; used 1 times
get_nglist defined in line 506; used 3 times
getword defined in line 330; used 2 times
newnews defined in line 22; used 2 times
seekuntil defined in line 258; used 1 times

Defined variables

nn_told defined in line 9; used 4 times
nn_took defined in line 10; used 1 times
sccsid defined in line 2; never used
Last modified: 1988-02-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4382
Valid CSS Valid XHTML 1.0 Strict