1: /*
   2:  * nntpxfer
   3:  *
   4:  * Connects to the specified nntp server, and transfers all new news
   5:  * since the last successful invocation.
   6:  *
   7:  * last successful invocation date and time are stored in a file at
   8:  * /usr/spool/news/nntp.<hostname> as
   9:  *	groups YYMMDD HHMMSS distributions\n
  10:  * in case you need to edit it.  You can also override this on
  11:  * the command line in the same format, in which case the file won't
  12:  * be updated.
  13:  *
  14:  *	Brian Kantor, UCSD 1986
  15:  * (some bug fixes by ambar@athena.mit.edu)
  16:  */
  17: 
  18: #define DEBUG
  19: 
  20: /* you'd think that 4096 articles at one go is enough.... */
  21: #define MAXARTS 4096
  22: 
  23: #include <sys/types.h>
  24: #include <sys/dir.h>
  25: #include <sys/socket.h>
  26: #include <sys/stat.h>
  27: #include <sys/ioctl.h>
  28: #include <sys/file.h>
  29: #include <sys/time.h>
  30: #include <sys/wait.h>
  31: #include <sys/resource.h>
  32: 
  33: #include <net/if.h>
  34: #include <netinet/in.h>
  35: 
  36: #include <stdio.h>
  37: #include <errno.h>
  38: #include <ctype.h>
  39: #include <netdb.h>
  40: #include <signal.h>
  41: #include <dbm.h>
  42: 
  43: #define INEWS   "/usr/lib/news/inews -p"
  44: #define HIST    "/usr/lib/news/history"
  45: 
  46: char    *malloc();
  47: char    *strcpy();
  48: char    *strcat();
  49: long    time();
  50: u_long  inet_addr();
  51: 
  52: extern int errno;
  53: char *artlist[MAXARTS];
  54: int server;         /* stream socket to the nntp server */
  55: int newart, dupart, misart;
  56: 
  57: main(argc, argv)
  58: int argc;
  59: char *argv[];
  60:     {
  61:     FILE *dtfile;       /* where last xfer date/time stored */
  62:     char buf[BUFSIZ];
  63:     char lastdate[16];
  64:     char distributions[BUFSIZ];
  65:     char dtname[128];
  66:     char newsgroups[BUFSIZ];
  67:     char lasttime[16];
  68:     int connected = 0;      /* 1 = connected */
  69:     int i;
  70:     int omitupdate = 0;     /* 1 = don't update datetime */
  71:     long clock;
  72:     long newdate, newtime;
  73:     struct hostent *hp;
  74:     struct servent *sp;
  75:     struct sockaddr_in sin;
  76:     struct tm *now;
  77: 
  78:     /* OPTIONS
  79: 		argv[1] MUST be the host name
  80: 		argv[2-4] MAY be "newsgroups YYMMDD HHMMSS"
  81: 			argv[5] MAY be distributions
  82: 		(otherwise use 2-4/5 from the file
  83: 		"/usr/spool/news/nntp.hostname")
  84: 	*/
  85: 
  86:     if (argc != 2 && argc != 5 && argc != 6)
  87:         {
  88:         (void) printf("Usage: %s host [groups YYMMDD HHMMSS [<dist>]]\n",
  89:             argv[0]);
  90:         exit(1);
  91:         }
  92: 
  93:     if (argc > 2)
  94:         {
  95:         omitupdate++;
  96:         (void) strcpy(newsgroups, argv[2]);
  97:         (void) strcpy(lastdate, argv[3]);
  98:         (void) strcpy(lasttime, argv[4]);
  99:         (void) strcpy(distributions, "");
 100:         if (argc > 5)
 101:             (void) strcpy(distributions, argv[5]);
 102:         }
 103:     else
 104:         {
 105:         (void) strcpy(dtname, "/usr/spool/news/nntp.");
 106:         (void) strcat(dtname, argv[1]);
 107:         dtfile = fopen(dtname, "r");
 108:         if (dtfile == NULL)
 109:             {
 110:             (void) printf("%s not found; using * 860101 000000 \n",
 111:                 dtname);
 112:             (void) strcpy(newsgroups, "*");
 113:             (void) strcpy(lastdate, "860101");
 114:             (void) strcpy(lasttime, "000000");
 115:             (void) strcpy(distributions, "");
 116:             }
 117:         else
 118:             {
 119:             if (fscanf(dtfile, "%s %s %s %s",
 120:                 newsgroups, lastdate, lasttime, distributions) < 3)
 121:                 {
 122:                 (void) printf("%s invalid; using * 860101 000000\n",
 123:                     dtname);
 124:                 (void) strcpy(newsgroups, "*");
 125:                 (void) strcpy(lastdate, "860101");
 126:                 (void) strcpy(lasttime, "000000");
 127:                 (void) strcpy(distributions, "");
 128:                 }
 129:             (void) fclose(dtfile);
 130:             }
 131:         clock = time((long *)0);
 132:         now = gmtime(&clock);
 133:         newdate = (now->tm_year * 10000) +
 134:             ((now->tm_mon + 1) * 100) + now->tm_mday;
 135:         newtime = (now->tm_hour * 10000) +
 136:             (now->tm_min * 100) + now->tm_sec;
 137:         }
 138: 
 139: #ifdef DEBUG
 140:     (void) printf("newsgroups = '%s'\n", newsgroups);
 141:     (void) printf("date = '%s'\n", lastdate);
 142:     (void) printf("time = '%s'\n", lasttime);
 143:     (void) printf("distributions = '%s'\n", distributions);
 144:     (void) printf("now is = %06d %06d\n", newdate, newtime);
 145: #endif
 146: 
 147:     if (dbminit(HIST) < 0)
 148:         {
 149:         perror("couldn't open history file");
 150:         exit(1);
 151:         }
 152: 
 153:     sin.sin_addr.s_addr = inet_addr(argv[1]);
 154:     if (sin.sin_addr.s_addr != -1)
 155:         {
 156:         sin.sin_family = AF_INET;
 157:         }
 158:     else
 159:         {
 160:         hp = gethostbyname(argv[1]);
 161:         if (hp == NULL)
 162:             {
 163:             (void) printf("%s: unknown host\n", argv[1]);
 164:             exit(1);
 165:             }
 166: 
 167:         sin.sin_family = hp->h_addrtype;
 168: #ifdef  BSD43
 169:         bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
 170:             hp->h_length);
 171: #else   BSD43
 172:         bcopy(hp->h_addr, (caddr_t)&sin.sin_addr,
 173:             hp->h_length);
 174: #endif	BSD43
 175:         }
 176: 
 177:     sp = getservbyname("nntp", "tcp");
 178:     if (sp == NULL)
 179:         {
 180:         perror("nntp/tcp");
 181:         exit(1);
 182:         }
 183: 
 184:     sin.sin_port = sp->s_port;
 185: 
 186:     do  {
 187:         server = socket(AF_INET, SOCK_STREAM, 0);
 188:         if (server < 0)
 189:             {
 190:             perror("nntpxfer: socket");
 191:             exit(1);
 192:             }
 193: 
 194:         if (connect(server, (struct sockaddr *)&sin, sizeof (sin)) < 0)
 195:             {
 196: #ifdef  BSD43
 197:             if (hp && hp->h_addr_list[1])
 198:                 {
 199:                 hp->h_addr_list++;
 200:                 bcopy(hp->h_addr_list[0],
 201:                     (caddr_t)&sin.sin_addr, hp->h_length);
 202:                 (void) close(server);
 203:                 continue;
 204:                 }
 205: #endif	BSD43
 206:             perror("nntpxfer: connect");
 207:             exit(1);
 208:             }
 209:         connected++;
 210:         }
 211:     while (connected == 0);
 212: 
 213: #ifdef DEBUG
 214:     (void) printf("connected to nntp server at %s\n", argv[1]);
 215: #endif
 216:     /*
 217: 	* ok, at this point we're connected to the nntp daemon
 218: 	* at the distant host.
 219: 	*/
 220: 
 221:     /* get the greeting herald */
 222:     (void) sockread(buf);
 223: #ifdef DEBUG
 224:     (void) printf("%s\n", buf);
 225: #endif
 226:     if (buf[0] != '2')  /* uh-oh, something's wrong! */
 227:         {
 228:         (void) printf("protocol error: got '%s'\n", buf);
 229:         (void) close(server);
 230:         exit(1);
 231:         }
 232: 
 233: 
 234:     /* first, tell them we're a slave process to get priority */
 235:     sockwrite("SLAVE");
 236:     (void) sockread(buf);
 237: #ifdef DEBUG
 238:     (void) printf("%s\n", buf);
 239: #endif
 240:     if (buf[0] != '2')  /* uh-oh, something's wrong! */
 241:         {
 242:         (void) printf("protocol error: got '%s'\n", buf);
 243:         (void) close(server);
 244:         exit(1);
 245:         }
 246: 
 247:     /* now, ask for a list of new articles */
 248:     if (strlen(distributions))
 249:         (void) sprintf(buf,"NEWNEWS %s %s %s GMT <%s>",
 250:             newsgroups, lastdate, lasttime, distributions);
 251:     else
 252:         (void) sprintf(buf,"NEWNEWS %s %s %s GMT",
 253:             newsgroups, lastdate, lasttime);
 254:     sockwrite(buf);
 255:     (void) sockread(buf);
 256: #ifdef DEBUG
 257:     (void) printf("%s\n", buf);
 258: #endif
 259:     if (buf[0] != '2')  /* uh-oh, something's wrong! */
 260:         {
 261:         (void) printf("protocol error: got '%s'\n", buf);
 262:         (void) close(server);
 263:         exit(1);
 264:         }
 265:     /* and here comes the list, terminated with a "." */
 266: #ifdef DEBUG
 267:     (void) printf("data\n");
 268: #endif
 269:     while (1)
 270:         {
 271:         (void) sockread(buf);
 272:         if (!strcmp(buf,"."))
 273:             break;
 274:         if (wewant(buf))
 275:             {
 276:             if (newart > MAXARTS)
 277:                 {
 278:                 omitupdate++;
 279:                 continue;
 280:                 }
 281:             artlist[newart] = malloc((unsigned)(strlen(buf)+1));
 282:             (void) strcpy(artlist[newart], buf);
 283:             newart++;
 284:             }
 285:         else
 286:             dupart++;
 287:         }
 288: #ifdef DEBUG
 289:     (void) printf(".\n%d new, %d dup articles\n", newart, dupart);
 290: #endif
 291: 
 292:     /* now that we know which articles we want, retrieve them */
 293:     for (i=1; i < newart; i++)
 294:         (void) artfetch(artlist[i]);
 295: 
 296: #ifdef DEBUG
 297:     (void) printf("%d missing articles\n", misart);
 298: #endif
 299:     /* we're all done, so tell them goodbye */
 300:     sockwrite("QUIT");
 301:     (void) sockread(buf);
 302: #ifdef DEBUG
 303:     (void) printf("%s\n", buf);
 304: #endif
 305:     if (buf[0] != '2')  /* uh-oh, something's wrong! */
 306:         {
 307:         (void) printf("error: got '%s'\n", buf);
 308:         (void) close(server);
 309:         exit(1);
 310:         }
 311:     (void) close(server);
 312: 
 313:     /* do we want to update the timestamp file? */
 314:     if (!omitupdate)
 315:         {
 316:         (void) sprintf(buf, "%s %06d %06d %s\n",
 317:             newsgroups, newdate, newtime, distributions);
 318: #ifdef DEBUG
 319:         (void) printf("updating %s:\n\t%s\n", dtname, buf);
 320: #endif
 321:         dtfile = fopen(dtname, "w");
 322:         if (dtfile == NULL)
 323:             {
 324:             perror(dtname);
 325:             exit(1);
 326:             }
 327:         (void) fputs(buf,dtfile);
 328:         (void) fclose(dtfile);
 329:         }
 330:     exit(0);
 331: }
 332: 
 333: artfetch(articleid)
 334: char *articleid;
 335:     {
 336:     int lines = 0;
 337:     char buf[BUFSIZ];
 338:     FILE *inews;
 339: 
 340:     /* now, ask for the article */
 341:     (void) sprintf(buf,"ARTICLE %s", articleid);
 342:     sockwrite(buf);
 343:     (void) sockread(buf);
 344: #ifdef DEBUG
 345:     (void) printf("%s\n", buf);
 346: #endif
 347:     if (buf[0] == '4')  /* missing article, just skipit */
 348:         {
 349:         misart++;
 350:         return(0);
 351:         }
 352: 
 353:     if (buf[0] != '2')  /* uh-oh, something's wrong! */
 354:         {
 355:         (void) printf("protocol error: got '%s'\n", buf);
 356:         (void) close(server);
 357:         exit(1);
 358:         }
 359: #ifdef DEBUG
 360:     (void) printf("command: %s\n", INEWS);
 361: #endif
 362:     if ( (inews = popen(INEWS, "w")) == NULL)
 363:         {
 364:         perror(INEWS);
 365:         exit(1);
 366:         }
 367: 
 368:     /* and here comes the article, terminated with a "." */
 369: #ifdef DEBUG
 370:     (void) printf("data\n");
 371: #endif
 372:     while (1)
 373:         {
 374:         (void) sockread(buf);
 375:         if (buf[0] == '.' && buf[1] == '\0')
 376:             break;
 377:         lines++;
 378:         (void) strcat(buf,"\n");
 379:         (void) fputs(((buf[0] == '.') ? buf + 1 : buf),
 380:                inews);
 381:         }
 382: #ifdef DEBUG
 383:     (void) printf(".\n%d lines\n", lines);
 384: #endif
 385:     (void) fflush(inews);
 386:     (void) pclose(inews);
 387:     return(0);
 388:         }
 389: 
 390: int
 391: sockread(buf)
 392: char *buf;
 393:     {
 394:     char c;
 395:     int j = 0;
 396: #ifdef BSD43
 397:     fd_set rf;
 398: #else BSD43
 399:     int rf;
 400: #endif BSD43
 401:     struct timeval tv;
 402:     int r;
 403:     char *p = buf;
 404: 
 405:     while ( 1 )
 406:         {
 407:         tv.tv_sec = 1800;   /* 15 minutes */
 408:         tv.tv_usec = 0L;
 409: #ifdef BSD43
 410:         FD_ZERO(&rf);
 411:         FD_SET(server, &rf);
 412: #else BSD43
 413:         rf = 1 << server;
 414: #endif BSD43
 415:         r = select(20, (fd_set *)&rf, (fd_set *)0, (fd_set *)&rf, &tv);
 416: 
 417:         if (r < 0)
 418:             {
 419:             if (errno == EINTR)
 420:                 continue;
 421:             perror("getsock select");
 422:             exit(1);
 423:             }
 424:         if (r == 0)
 425:             {
 426:             printf("read timed out.\n");
 427:             exit(1);
 428:             }
 429: 
 430:         if (read(server, &c, 1) <= 0)
 431:             break;
 432: 
 433:         /* mask off any chance parity bits */
 434:         *p = c & 0x7f;
 435: 
 436:         /* look for end of line (== LF) */
 437:         if (c == 0x0a)
 438:             {
 439:             if (j > 0 && *(p-1) == 0x0d)
 440:                 *(p-1) = '\0';
 441:             else
 442:                 *p = '\0';
 443:             return(strlen(buf));
 444:             }
 445:         j++; p++;
 446:         }
 447:     perror("sockread");
 448:     (void) close(server);
 449:     exit(1);
 450:     /* NOTREACHED */
 451:     }
 452: 
 453: sockwrite(buf)
 454: char *buf;
 455:     {
 456:     register int sz;
 457:     char buf2[BUFSIZ];
 458: #ifdef DEBUG
 459:     (void) printf(">>> %s\n", buf);
 460: #endif
 461:     (void) strcpy(buf2,buf);
 462:     (void) strcat(buf2,"\r\n");
 463:     sz = strlen(buf2);
 464:     if (write(server,buf2,sz) != sz)
 465:         {
 466:         (void) printf("write error on server socket\n");
 467:         (void) close(server);
 468:         exit(1);
 469:         }
 470:     }
 471: 
 472: int
 473: wewant(articleid)
 474: char *articleid;
 475:     {
 476:     datum k, d;
 477:     char id[BUFSIZ];
 478:     char *p;
 479: 
 480:     /* remove any case sensitivity */
 481:     (void) strcpy(id, articleid);
 482:     p = id;
 483:     while (*p)
 484:         {
 485:         if (isupper(*p))
 486:             *p = tolower(*p);
 487:         p++;
 488:         }
 489: 
 490:     k.dptr = id;
 491:     k.dsize = strlen(articleid) + 1;
 492: 
 493:     d = fetch(k);
 494: 
 495:     if (d.dptr)
 496:         {
 497: #ifdef DEBUG
 498:         (void) printf("dup: '%s'\n", articleid);
 499: #endif
 500:         return(0);
 501:         }
 502: 
 503: #ifdef DEBUG
 504:     (void) printf("new: '%s'\n", articleid);
 505: #endif
 506:     return(1);
 507:     }

Defined functions

artfetch defined in line 333; used 1 times
main defined in line 57; never used
sockread defined in line 390; used 7 times
sockwrite defined in line 453; used 4 times
wewant defined in line 472; used 1 times

Defined variables

artlist defined in line 53; used 3 times
dupart defined in line 55; used 2 times
misart defined in line 55; used 2 times
newart defined in line 55; used 6 times
server defined in line 54; used 16 times

Defined macros

DEBUG defined in line 18; used 17 times
HIST defined in line 44; used 1 times
INEWS defined in line 43; used 3 times
MAXARTS defined in line 21; used 2 times
Last modified: 1987-10-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4794
Valid CSS Valid XHTML 1.0 Strict