Annotation of 43BSDTahoe/new/nntp/xfer/nntpxfer.c, revision 1.1.1.1

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:        }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.