# 2.11BSD#431 - /usr/src/new/nntp/xfer/nntpxfer.c

##### Functions

    artfetch          X
    main              X
    sockread          X
    sockwrite         X
    wewant            X

##### Variables

    artlist           X
    dupart            X
    misart            X
    newart            X
    server            X

##### Macros

    DEBUG             X
    HIST              X
    INEWS             X
    MAXARTS           X

       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

- in line 294

main defined in line 57; never used
sockread defined in line 390; used 7 times

- in line 222, 236, 255, 271, 301, 343, 374

sockwrite defined in line 453; used 4 times

- in line 235, 254, 300, 342

wewant defined in line 472; used 1 times

- in line 274

#### Defined variables

artlist defined in line 53; used 3 times

- in line 281-282(2), 294

dupart defined in line 55; used 2 times

- in line 286-289(2)

misart defined in line 55; used 2 times

- in line 297, 349

newart defined in line 55; used 6 times

- in line 276-283(4), 289-293(2)

server defined in line 54; used 16 times

- in line 187-188(2), 194, 202, 229, 243, 262, 308-311(2), 356, 411-413(2), 430, 448, 464-467(2)

#### Defined macros

DEBUG defined in line 18; used 17 times

- in line 139, 213, 223, 237, 256, 266, 288, 296, 302, 318, 344, 359, 369, 382, 458, 497, 503

HIST defined in line 44; used 1 times

- in line 147

INEWS defined in line 43; used 3 times

- in line 360-364(3)

MAXARTS defined in line 21; used 2 times

- in line 53, 276

Last modified: 1987-10-16 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2186 |