|
|
1.1 ! root 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 [email protected]) ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.