home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / nntp-1.5 / nntp-1 / nntp.1.5.11t / xfer / nntpxfer.c < prev   
Encoding:
C/C++ Source or Header  |  1993-10-17  |  12.6 KB  |  636 lines

  1. #ifndef lint
  2. static char * scsid = "@(#)$Header: nntpxfer.c,v 1.9 91/02/02 13:31:37 sob Exp $";
  3. #endif
  4. /*
  5.  * nntpxfer
  6.  *
  7.  * Connects to the specified nntp server, and transfers all new news
  8.  * since the last successful invocation.
  9.  *
  10.  * last successful invocation date and time are stored in a file at
  11.  * /usr/spool/news/nntp.<hostname> as 
  12.  *    groups YYMMDD HHMMSS distributions\n
  13.  * in case you need to edit it.  You can also override this on 
  14.  * the command line in the same format, in which case the file won't
  15.  * be updated.
  16.  *
  17.  *    Brian Kantor, UCSD 1986
  18.  * (some bug fixes by ambar@athena.mit.edu)
  19.  * Modified to use NNTP distribution conf.h file and nntpxmit's get_tcp_conn.c
  20.  * subroutines so that nntpxfer could be used on more systems.
  21.  * Stan Barber, November 7, 1989 <sob@bcm.tmc.edu>
  22.  *
  23.  */
  24.  
  25. #include "../common/conf.h"
  26. #ifdef DEBUG
  27. #undef SYSLOG
  28. #endif
  29.  
  30. #include <sys/types.h>
  31. #ifdef NDIR
  32. #ifdef M_XENIX
  33. #include <sys/ndir.h>
  34. #else
  35. #include <ndir.h>
  36. #endif
  37. #else
  38. #include <sys/dir.h>
  39. #endif
  40. #ifdef USG
  41. #include <time.h>
  42. #else
  43. #include <sys/time.h>
  44. #endif
  45.  
  46. #include <stdio.h>
  47. #include <errno.h>
  48. #include <ctype.h>
  49. #include <setjmp.h>
  50. #ifndef NONETDB
  51. #include <netdb.h>
  52. #endif
  53. #include <signal.h>
  54. #ifdef SYSLOG
  55. #ifdef FAKESYSLOG
  56. #include "../server/fakesyslog.h"
  57. #else
  58. #include <syslog.h>
  59. #endif
  60. #endif
  61.  
  62. #ifdef DBM
  63. # ifdef DBZ
  64. #   include <dbz.h>
  65. #else /* DBZ */
  66. # undef NULL
  67. # include <dbm.h>
  68. # undef NULL
  69. # define NULL    0
  70. #endif /* DBZ */
  71. #endif  /* DBM */
  72.  
  73. #ifdef NDBM
  74. #include <ndbm.h>
  75. #include <fcntl.h>
  76. static DBM *db = NULL;
  77. #endif
  78. #ifndef TIMEOUT
  79. #define TIMEOUT (30*60)
  80. #endif
  81. #ifndef MAX_ARTICLES
  82. #define MAX_ARTICLES 4096
  83. #endif
  84.  
  85. char    *malloc();
  86. char    *strcpy();
  87. char    *strcat();
  88. char    *rindex();
  89. long    time();
  90. u_long    inet_addr();
  91.  
  92. extern int errno;
  93. char *artlist[MAX_ARTICLES];
  94. int server;            /* stream socket to the nntp server */
  95. FILE * rd_fp, * wr_fp;
  96. int newart, dupart, misart;
  97. char * Pname;
  98.  
  99. main(argc, argv)
  100. int argc;
  101. char *argv[];
  102. {
  103.     FILE *dtfile;        /* where last xfer date/time stored */
  104.     char buf[BUFSIZ];
  105.     char lastdate[16];
  106.     char distributions[BUFSIZ];
  107.     char dtname[128];
  108.     char newsgroups[BUFSIZ];
  109.     char lasttime[16];
  110.     int i;
  111.     int omitupdate = 0;        /* 1 = don't update datetime */
  112.     long clock;
  113.     long newdate, newtime;
  114.     struct tm *now;
  115.     Pname = ((Pname = rindex(argv[0], '/')) ? Pname + 1 : argv[0]);
  116.     /* OPTIONS
  117.         argv[1] MUST be the host name
  118.         argv[2-4] MAY be "newsgroups YYMMDD HHMMSS"
  119.             argv[5] MAY be distributions
  120.         (otherwise use 2-4/5 from the file
  121.         "/usr/spool/news/nntp.hostname")
  122.     */
  123.  
  124.     if (argc != 2 && argc != 5 && argc != 6)
  125.         {
  126.         (void) printf("Usage: %s host [groups YYMMDD HHMMSS [<dist>]]\n",
  127.             argv[0]);
  128.         exit(1);
  129.         }
  130.     
  131.     if (argc > 2)
  132.         {
  133.         omitupdate=1;
  134.         (void) strcpy(newsgroups, argv[2]);
  135.         (void) strcpy(lastdate, argv[3]);
  136.         (void) strcpy(lasttime, argv[4]);
  137.         (void) strcpy(distributions, "");
  138.         if (argc > 5)
  139.             (void) strcpy(distributions, argv[5]);
  140.         }
  141.     else
  142.         {
  143.         (void) sprintf(dtname, "%s/nntp.%s",SPOOLDIR,argv[1]);
  144.         dtfile = fopen(dtname, "r");
  145.         if (dtfile == (FILE *) 0)
  146.             {
  147.             (void) printf("%s not found; using * 860101 000000 \n", 
  148.                 dtname);
  149.             (void) strcpy(newsgroups, "*");
  150.             (void) strcpy(lastdate, "860101");
  151.             (void) strcpy(lasttime, "000000");
  152.             (void) strcpy(distributions, "");
  153.             }
  154.         else
  155.             {
  156.             if (fscanf(dtfile, "%s %s %s %s",
  157.                 newsgroups, lastdate, lasttime, distributions) < 3)
  158.                 {
  159.                 (void) printf("%s invalid; using * 860101 000000\n",
  160.                     dtname);
  161.                 (void) strcpy(newsgroups, "*");
  162.                 (void) strcpy(lastdate, "860101");
  163.                 (void) strcpy(lasttime, "000000");
  164.                 (void) strcpy(distributions, "");
  165.                 }
  166.             (void) fclose(dtfile);
  167.             }
  168.         clock = time((long *)0);
  169.         now = gmtime(&clock);
  170.         newdate = (now->tm_year * 10000) +
  171.             ((now->tm_mon + 1) * 100) + now->tm_mday;
  172.         newtime = (now->tm_hour * 10000) +
  173.             (now->tm_min * 100) + now->tm_sec;
  174. #ifdef DEBUG
  175.     printf("server is %s\n",argv[1]);
  176.     printf("lastdate is %s\n",lastdate);
  177.     printf("lasttime is %s\n",lasttime);
  178.     printf("newsgroups is '%s'\n",newsgroups);
  179.     printf("distributions is '%s'\n",distributions);
  180. #endif
  181.         }
  182. #ifdef SYSLOG
  183. #ifdef BSD_42
  184.     openlog("nntpxfer", LOG_PID);
  185. #else
  186.     openlog("nntpxfer", LOG_PID, SYSLOG);
  187. #endif
  188. #endif
  189. #ifdef DBM
  190.     if (dbminit(HISTORY_FILE) < 0)
  191.         {
  192. #ifdef SYSLOG
  193.         syslog(LOG_ERR,"couldn't open history file: %m");
  194. #else
  195.         perror("nntpxfer: couldn't open history file");
  196. #endif
  197.         exit(1);
  198.         }
  199. #endif
  200. #ifdef NDBM
  201.      if ((db = dbm_open(HISTORY_FILE, O_RDONLY, 0)) == NULL) 
  202.          {
  203. #ifdef SYSLOG
  204.          syslog(LOG_ERR,"couldn't open history file: %m");
  205. #else
  206.          perror("nntpxfer: couldn't open history file");
  207. #endif
  208.          exit(1);
  209.          }
  210. #endif
  211.     if ((server = get_tcp_conn(argv[1],"119")) < 0) 
  212.         {
  213. #ifdef SYSLOG
  214.         syslog(LOG_ERR,"could not open socket: %m");
  215. #else
  216.         perror("nntpxfer: could not open socket");
  217. #endif
  218.         exit(1);
  219.         }
  220.     if ((rd_fp = fdopen(server,"r")) == (FILE *) 0){
  221. #ifdef SYSLOG
  222.         syslog(LOG_ERR,"could not fdopen socket: %m");
  223. #else
  224.         perror("nntpxfer: could not fdopen socket");
  225. #endif
  226.         exit(1);
  227.         }
  228.  
  229. #ifdef SYSLOG
  230.     syslog(LOG_DEBUG,"connected to nntp server at %s", argv[1]);
  231. #endif
  232. #ifdef DEBUG
  233.     printf("connected to nntp server at %s\n", argv[1]);
  234. #endif
  235.     /*
  236.     * ok, at this point we're connected to the nntp daemon 
  237.     * at the distant host.
  238.     */
  239.     /* get the greeting herald */
  240.     (void) sockread(buf);
  241. #ifdef DEBUG
  242.     (void) printf("%s\n", buf);
  243. #endif
  244.     if (buf[0] != '2')    /* uh-oh, something's wrong! */
  245.         {
  246. #ifdef SYSLOG
  247.         syslog(LOG_NOTICE,"protocol error: got '%s'\n", buf);
  248. #else
  249.         (void) printf("%s: protocol error: got '%s'\n", Pname,buf);
  250. #endif
  251.         (void) close(server);
  252.         exit(1);
  253.         }
  254.  
  255.  
  256.     /* first, tell them we're a slave process to get priority */
  257. #if 0 /* OLE */
  258.     sockwrite("SLAVE");
  259.     (void) sockread(buf);
  260. #ifdef DEBUG
  261.     (void) printf("%s\n", buf);
  262. #endif
  263.     if (buf[0] != '2')    /* uh-oh, something's wrong! */
  264.         {
  265. #ifdef SYSLOG
  266.         syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
  267. #else
  268.         (void) printf("%s: protocol error: got '%s'\n", Pname,buf);
  269. #endif
  270.         (void) close(server);
  271.         exit(1);
  272.         }
  273. #endif
  274.     
  275.     /* now, ask for a list of new articles */
  276.     if (strlen(distributions))
  277.         (void) sprintf(buf,"NEWNEWS %s %s %s GMT <%s>", 
  278.             newsgroups, lastdate, lasttime, distributions);
  279.     else
  280.         (void) sprintf(buf,"NEWNEWS %s %s %s GMT", 
  281.             newsgroups, lastdate, lasttime);
  282.     sockwrite(buf);
  283.     (void) sockread(buf);
  284. #ifdef DEBUG
  285.     (void) printf("%s\n", buf);
  286. #endif
  287.     if (buf[0] != '2')    /* uh-oh, something's wrong! */
  288.         {
  289. #ifdef SYSLOG
  290.         syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
  291. #else
  292.         (void) printf("%s: protocol error: got '%s'\n", Pname,buf);
  293. #endif
  294.         (void) close(server);
  295.         exit(1);
  296.         }
  297.     /* and here comes the list, terminated with a "." */
  298. #ifdef DEBUG
  299.     (void) printf("data\n");
  300. #endif
  301.     dupart = newart = 0;
  302.     while (1)
  303.         {
  304.         (void) sockread(buf);
  305.         if (!strcmp(buf,"."))
  306.             break;
  307.         if(!strrchr(buf, '>'))
  308.             strcat(buf, ">");    
  309.         if (wewant(buf))
  310.             {
  311.             if (newart >= MAX_ARTICLES)
  312.                 {
  313.                 omitupdate=1;
  314.                 continue;
  315.                 }
  316.             artlist[newart] = malloc((unsigned)(strlen(buf)+1));
  317.             (void) strcpy(artlist[newart], buf);
  318.             newart++;
  319.             }
  320.         else
  321.             dupart++;
  322.         }
  323. #ifdef DEBUG
  324.     (void) printf(".\n%d new, %d dup articles\n", newart, dupart);
  325. #endif
  326.  
  327.     /* now that we know which articles we want, retrieve them */
  328.     for (i=0; i < newart; i++)
  329.         (void) artfetch(artlist[i]);
  330.  
  331. #ifdef DEBUG
  332.     (void) printf("%d missing articles\n", misart);
  333. #endif
  334.     /* we're all done, so tell them goodbye */
  335.     sockwrite("QUIT");
  336.     (void) sockread(buf);
  337. #ifdef DEBUG
  338.     (void) printf("%s\n", buf);
  339. #endif
  340.     if (buf[0] != '2')    /* uh-oh, something's wrong! */
  341.         {
  342. #ifdef SYSLOG
  343.         syslog(LOG_NOTICE,"error: got '%s'", buf);
  344. #else
  345.         (void) printf("%s: error: got '%s'\n", Pname,buf);
  346. #endif
  347.         (void) close(server);
  348.         exit(1);
  349.         }
  350.     (void) close(server);
  351.  
  352.     /* do we want to update the timestamp file? */
  353.     if (!omitupdate)
  354.         {
  355.         (void) sprintf(buf, "%s %06d %06d %s\n",
  356.             newsgroups, newdate, newtime, distributions);
  357. #ifdef DEBUG
  358.         (void) printf("updating %s:\n\t%s\n", dtname, buf);
  359. #endif
  360.         dtfile = fopen(dtname, "w");
  361.         if (dtfile == (FILE *) 0)
  362.             {
  363.             perror(dtname);
  364.             exit(1);
  365.             }
  366.         (void) fputs(buf,dtfile);
  367.         (void) fclose(dtfile);
  368.         }
  369.     exit(0);
  370. }
  371.  
  372. artfetch(articleid)
  373. char *articleid;
  374.     {
  375. #ifdef DEBUG
  376.     int lines = 0;
  377. #endif
  378.     char buf[BUFSIZ];
  379.     FILE *inews;
  380.  
  381.     /* now, ask for the article */
  382.     (void) sprintf(buf,"ARTICLE %s", articleid);
  383.     sockwrite(buf);
  384.     (void) sockread(buf);
  385. #ifdef DEBUG
  386.     (void) printf("%s\n", buf);
  387. #endif
  388.     if (buf[0] == '4')    /* missing article, just skipit */
  389.         {
  390.         misart++;
  391.         return(0);
  392.         }
  393.  
  394.     if (buf[0] != '2')    /* uh-oh, something's wrong! */
  395.         {
  396. #ifdef SYSLOG
  397.         syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
  398. #else
  399.         (void) printf("%s: protocol error: got '%s'\n", Pname, buf);
  400. #endif
  401.         (void) close(server);
  402.         exit(1);
  403.         }
  404. #ifdef DEBUG
  405.     (void) printf("command: %s\n", RNEWS);
  406. #endif
  407.     if ( (inews = popen(RNEWS, "w")) == (FILE *) 0)
  408.         {
  409.         perror(RNEWS);
  410.         exit(1);
  411.         }
  412.  
  413.     /* and here comes the article, terminated with a "." */
  414. #ifdef DEBUG
  415.     (void) printf("data\n");
  416. #endif
  417.     while (1)
  418.         {
  419.         (void) sockread(buf);
  420.         if (buf[0] == '.' && buf[1] == '\0')
  421.             break;
  422. #ifdef DEBUG
  423.         lines++;
  424. #endif
  425.         (void) strcat(buf,"\n");
  426.         (void) fputs(((buf[0] == '.') ? buf + 1 : buf),
  427.                inews);
  428.         }
  429. #ifdef DEBUG
  430.     (void) printf(".\n%d lines\n", lines);
  431. #endif
  432.     (void) fflush(inews);
  433.     (void) pclose(inews);
  434.     return(0);
  435.         }
  436.  
  437. static    jmp_buf    SFGstack;
  438.  
  439. static SIGRET
  440. to_sfgets()
  441. {
  442.     longjmp(SFGstack, 1);
  443. }
  444.  
  445. int
  446. sockread(buf)
  447. char *buf;
  448. {
  449.     int    esave, rz;
  450.     char * ret;
  451.     if (setjmp(SFGstack)) {
  452.         (void) alarm(0);    /* reset alarm clock */
  453.         (void) signal(SIGALRM, SIG_DFL);
  454. /* OLE        rd_fp->_flag |= _IOERR;    /* set stdio error */
  455. #ifndef ETIMEDOUT
  456.         errno = EPIPE;        /* USG doesn't have ETIMEDOUT */
  457. #else
  458.         errno = ETIMEDOUT;        /* connection timed out */
  459. #endif
  460. #ifdef SYSLOG
  461.         syslog(LOG_ERR,"nntpxfer: read error on server socket: %m");
  462. #else
  463.         (void) perror("nntpxfer: read error on server socket");
  464. #endif
  465.         (void) close(server);
  466.         exit(1);
  467.     }
  468.     (void) signal(SIGALRM, to_sfgets);
  469.     (void) alarm(TIMEOUT);
  470.     ret  = fgets(buf, BUFSIZ, rd_fp);
  471.     esave = errno;
  472.     (void) alarm(0);            /* reset alarm clock */
  473.     (void) signal(SIGALRM, SIG_DFL);    /* reset SIGALRM */
  474.     errno = esave;
  475.     rz = strlen(buf);
  476.     buf[rz-2] = '\0';
  477.     if (ret  == (char * ) 0) {
  478. #ifdef SYSLOG
  479.             syslog(LOG_ERR,"nntpxfer: read error on server socket: %m");
  480. #else
  481.         (void) perror("nntpxfer: read error on server socket");
  482. #endif
  483.         (void) fclose(rd_fp);
  484.         exit(1);
  485.     }
  486.     return(0);
  487. }
  488.  
  489. sockwrite(buf)
  490. char *buf;
  491.     {
  492.     register int sz;
  493.     char buf2[BUFSIZ];
  494. #ifdef DEBUG
  495.     (void) printf(">>> %s\n", buf);
  496. #endif
  497.     (void) strcpy(buf2,buf);
  498.     (void) strcat(buf2,"\r\n");
  499.     sz = strlen(buf2);
  500.     if (write(server,buf2,sz) != sz)
  501.         {
  502. #ifdef SYSLOG
  503.         syslog(LOG_ERR,"nntpxfer: write error on server socket");
  504. #else
  505.         (void) printf("nntpxfer: write error on server socket\n");
  506. #endif
  507.         (void) close(server);
  508.         exit(1);
  509.         }
  510.     }
  511.  
  512. int
  513. wewant(articleid)
  514. char *articleid;
  515.     {
  516. #if defined(DBM) || defined(NDBM)
  517.     datum k, d;
  518. #else
  519.     FILE *k;
  520.     char *histfile();
  521.     FILE *histfp;        /* USG history file */
  522.     char line[BUFSIZ];
  523.     int len;
  524. #endif
  525.     char id[BUFSIZ];
  526.     char *p;
  527.  
  528.     /* remove any case sensitivity */
  529.     (void) strcpy(id, articleid);
  530.     p = id;
  531. #ifndef CNEWS
  532.     while (*p)
  533.         {
  534.         if (isupper(*p))
  535.             *p = tolower(*p);
  536.         p++;
  537.         }
  538. #endif
  539. #if defined(DBM) || defined(NDBM)
  540.     k.dptr = id;
  541.     k.dsize = strlen(articleid) + 1;
  542.  
  543. #ifdef DBM
  544.     d = fetch(k);
  545. #else
  546.      d = dbm_fetch(db, k);
  547. #endif
  548.     if (d.dptr)
  549.         {
  550. #ifdef DEBUG
  551.         (void) printf("dup: '%s'\n", articleid);
  552. #endif
  553.         return(0);
  554.         }
  555. #ifdef DEBUG
  556.     (void) printf("new: '%s'\n", articleid);
  557. #endif
  558.     return(1);
  559. #else
  560.     histfp = fopen(histfile(articleid), "r");
  561.     if (histfp == NULL) 
  562.         {
  563. #ifdef DEBUG
  564.         (void) printf("new: '%s'\n", articleid);
  565. #endif
  566.         return(1);
  567.         }
  568.     len = strlen(articleid);
  569.     while (fgets(line, sizeof (line), histfp))
  570.         if (!strncmp(articleid, line, len))
  571.             break;
  572.  
  573.     if (feof(histfp)) {
  574.         (void) fclose(histfp);
  575. #ifdef DEBUG
  576.         (void) printf("new: '%s'\n", articleid);
  577. #endif
  578.         return (1);
  579.     }
  580.     (void) fclose(histfp);
  581. #ifdef DEBUG
  582.     (void) printf("dup: '%s' %s\n", articleid,line);
  583. #endif
  584.     return(0);
  585. #endif
  586. }
  587.  
  588. #ifdef USGHIST
  589. /*
  590. ** Generate the appropriate history subfile name
  591. */
  592. char *
  593. histfile(hline)
  594. char *hline;
  595. {
  596.     char chr;    /* least significant digit of article number */
  597.     static char subfile[BUFSIZ];
  598.  
  599.     chr = findhfdigit(hline);
  600.     sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr);
  601.     return subfile;
  602. }
  603.  
  604. findhfdigit(fn)
  605. char *fn;
  606. {
  607.     register char *p;
  608.     register int chr;
  609.     extern char * index();
  610.  
  611.     p = index(fn, '@');
  612.     if (p != NULL && p > fn)
  613.         chr = *(p - 1);
  614.     else
  615.         chr = '0';
  616.     if (!isdigit(chr))
  617.         chr = '0';
  618.     return chr;
  619. }
  620. #endif
  621. char *
  622. errmsg(code)
  623. int code;
  624. {
  625.     extern int sys_nerr;
  626.     extern char *sys_errlist[];
  627.     static char ebuf[6+5+1];
  628.  
  629.     if (code > sys_nerr || code < 0) {
  630.         (void) sprintf(ebuf, "Error %d", code);
  631.         return ebuf;
  632.     } else
  633.         return sys_errlist[code];
  634. }
  635.  
  636.