Logo Search packages:      
Sourcecode: xbuffy version File versions  Download package

nntp.c

/*******************************************************************************

     Copyright (c) 1994,1995    William Pemberton (wfp5p@virginia.edu)

     The X Consortium, and any party obtaining a copy of these files from
     the X Consortium, directly or indirectly, is granted, free of charge, a
     full and unrestricted irrevocable, world-wide, paid up, royalty-free,
     nonexclusive right and license to deal in this software and
     documentation files (the "Software"), including without limitation the
     rights to use, copy, modify, merge, publish, distribute, sublicense,
     and/or sell copies of the Software, and to permit persons who receive
     copies from any such party to do so.  This license includes without
     limitation a license to do the foregoing actions under any patents of
     the party supplying this software to the X Consortium.

*******************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <varargs.h>
#include <errno.h>
#include <sys/stat.h>

#include "xbuffy.h"

#define CR        (13)
#define LF        LINEFEED
#define NEWLINE   LF
#define CHUNK_SIZE      (1024L)

#define MAX_LINE (1024)



#ifdef TESTNEWS
FILE *NNTP_fIn, *NNTP_fOut;
int NNTPinit = 0;

#else
extern FILE *NNTP_fIn, *NNTP_fOut;
extern int NNTPinit;

#endif

void Fatal(va_alist)
{
      char *fmt;
      extern int errno;
      va_list p;

      va_start(p);

      fmt = va_arg(p, char *);
      vfprintf(stderr, fmt, p);
      fputc('\n', stderr);
      if (errno)
            perror("System error");
      va_end(p);
      exit(1);
}

void fputeol(FILE * NNTP_fOut)
{
      fputc(CR, NNTP_fOut);
      fputc(LF, NNTP_fOut);
      fflush(NNTP_fOut);
}


void initNNTP()
{
      char line[1024];
      int err;
      int sock;
      char *serverName;
      struct sockaddr_in server;
      struct hostent *hp;


      sock = socket(AF_INET, SOCK_STREAM, 0);
      if (sock < 0)
            Fatal("socket failed");

      server.sin_family = AF_INET;
      server.sin_port = htons(119); /* NNTP */
      serverName = getenv("NNTPSERVER");
      if (serverName == NULL)
#ifdef NNTP_SERVER
            serverName = NNTP_SERVER;
#else
            Fatal("Please set $NNTPSERVER to an appropriate news server.");
#endif

      hp = gethostbyname(serverName);

      if (hp == 0)
            Fatal("gethostbyname failed");

      bcopy(*hp->h_addr_list, (char *) &server.sin_addr, hp->h_length);

      err = connect(sock, (struct sockaddr*)&server, sizeof(server));

      if (err)
            Fatal("connect failed");

      if (!(NNTP_fIn = fdopen(sock, "r")))
            Fatal("fdopen(sock,\"r\") failed");

      if (!(NNTP_fOut = fdopen(sock, "w")))
            Fatal("fdopen(sock,\"w\") failed");

      /* get header line */
      fgets(line, sizeof(line), NNTP_fIn);
      if (atoi(line) != 200)
            Fatal("initial line unexpected: %s", line);

      NNTPinit = 1;


}


int getHeaders(long Article, char **from, char **subject)
{
      char line[CHUNK_SIZE];
      char *q;
      int x;

      fprintf(NNTP_fOut, "head %ld", Article);
      fputeol(NNTP_fOut);

      if (fgets(line, sizeof(line) - 1, NNTP_fIn) == 0)
            Fatal("getHeaders: premature EOF");

      if ((x = atoi(line)) != 221)
      {
            if (x == 423)                 /* then the article just don't exist */
                  return (0);
            else
                  Fatal("getHeaders: got a bad value: %s", line);
      }

      while ((line[0] != '.') && (line[1] != NEWLINE))
      {

            /* retrieve line */

            if (fgets(line, sizeof(line) - 1, NNTP_fIn) == 0)
                  Fatal("ReadBlock: premature EOF");

            /* look for CR LF at the end of the line then replace it with NEWLINE */

            q = line + NEWstrlen(line) - 1;

#ifdef DEBUG
            if (q[0] != LF)
                  Fatal("ReadBlock: didn't find LF at end-of-line:\n%s", line);
            if (q[-1] != CR)
                  Fatal("ReadBlock: didn't see CR near end-of-line:\n%s", line);
#endif

            q[-1] = NEWLINE;

            if (strincmp(line, "From:", 5) == 0)
                  *from = strdup(line);

            if (strincmp(line, "Subject:", 8) == 0)
                  *subject = strdup(line);


      }

      return (1);

}

static char *getNewsrc()
{
      static char fname[512];

      sprintf(fname, "%s/.newsrc", getenv("HOME"));

      return (fname);
}

void readNewsrcEntry(newsBox, firstArt, lastArt)
      BoxInfo_t *newsBox;
      long firstArt;
      long lastArt;
{
      FILE *newsrc;
      Boolean done = FALSE;
      char line[MAX_LINE];
      static Articles_t tempArt;


      newsrc = fopen(getNewsrc(), "r");
      if (newsrc == NULL)
            Fatal("Can't open .newsrc\n");

      while (DynSize(newsBox->articles))
            DynDelete(newsBox->articles, DynHigh(newsBox->articles));

      while ((!done) && (fgets(line, MAX_LINE - 1, newsrc) != 0))
      {
            char *tmp;
            char *backp;

            if (strincmp(line, newsBox->box, NEWstrlen(newsBox->box)) != 0)
                  continue;

            tmp = line + NEWstrlen(newsBox->box);
            while ((!isdigit(*tmp)) && (*tmp != '\n'))
                  tmp++;

            backp = tmp;
            while (*tmp != '\n')
            {

                  /* First number */
                  while (isdigit(*tmp))
                  {
                        tmp++;
                  }
                  tempArt.firstNum = atol(backp);
                  backp = tmp;

                  /* Is that it or is there another? */

                  if (*tmp == ',')
                  {
                        tempArt.lastNum = tempArt.firstNum;
                        tmp++;
                        backp++;
                  }
                  else if (*tmp == '\n')
                  {
                        tempArt.lastNum = tempArt.firstNum;
                  }

                  /* There IS more */

                  else
                  {
                        tmp++;
                        backp++;
                        while (isdigit(*tmp))
                        {
                              tmp++;
                        }
                        tempArt.lastNum = atol(backp);
                        backp = tmp;

                        if (*tmp != '\n')
                        {
                              tmp++, backp++;
                        }
                  }
                  if (tempArt.lastNum > firstArt)
                  {
                        if (tempArt.firstNum < firstArt)
                              tempArt.firstNum = firstArt;

                        DynAdd(newsBox->articles, &tempArt);
                  }
            }

      }
      fclose(newsrc);
      tempArt.firstNum = tempArt.lastNum = lastArt + 1;
      DynAdd(newsBox->articles, &tempArt);


}

int insideBox(x, firstNum, lastNum)
      long x;
      long firstNum;
      long lastNum;
{
      return ((x >= firstNum) && (x <= lastNum));
}



int CountNNTP(newsBox, headerString, beenTouched)
      BoxInfo_t *newsBox;
      DynObject headerString;
      Boolean *beenTouched;
{
      int sock, err, len;
      char line[1024];
      long ipaddr;
      char *from;
      char *subject;
      long firstScanArticle;
      long firstArticle;
      long lastArticle;
      long retVal;
      long count;
      long numberArticles;
      long x;
      int index;
      struct stat f_stat;
      Articles_t *artP;



      if (!NNTPinit)
            initNNTP();

      *beenTouched = FALSE;
      count = 0;

      /* send dummy group selection */
/*    fputs("group news.answers", NNTP_fOut);
      fputeol(NNTP_fOut); */

      /* get return line */
/*    fgets(line, sizeof(line), NNTP_fIn);
      if (atoi(line) != 211)
            Fatal("unexpected response to group line: %s", line);*/


      /* send group selection */
      sprintf(line, "group %s", newsBox->box);
      fputs(line, NNTP_fOut);
      fputeol(NNTP_fOut);

#ifdef DEBUG
   printf("countNNTP: send %s\n",line);
#endif    

        /* get return line */
      fgets(line, sizeof(line), NNTP_fIn);
      if (atoi(line) != 211)
            Fatal("unexpected response to group line: %s", line);
   
      if (4 != sscanf(line, "%ld %ld %ld %ld", &retVal, &numberArticles, &firstArticle, &lastArticle))
            Fatal("couldn't parse group line: %s", line);
#ifdef DEBUG
   printf("countNNTP: read %s\n",line);
#endif   

      stat(getNewsrc(), &f_stat);

      if ((f_stat.st_size != newsBox->st_size) ||
            (f_stat.st_mtime > newsBox->box_mtime))
      {
            newsBox->st_size = f_stat.st_size;
            newsBox->box_mtime = f_stat.st_mtime;
            *beenTouched = TRUE;
      }

      readNewsrcEntry(newsBox, firstArticle, lastArticle);


#ifdef DEBUG
      len = DynLow(newsBox->articles);
      while (len <= DynHigh(newsBox->articles))
      {

            artP = (Articles_t *) DynGet(newsBox->articles, len);

            printf("Pair %ld %ld\n", artP->firstNum, artP->lastNum);
            len++;
      }
#endif

      artP = (Articles_t *) DynGet(newsBox->articles, 0);

      index = 0;

      x = firstArticle;

      while (x <= lastArticle)
      {
            if (!insideBox(x, artP[index].firstNum, artP[index].lastNum))
            {
                  from = subject = NULL;
                  if (getHeaders(x, &from, &subject))
                  {
                        count++;
                        if (headerString != NULL)
                        {
                              from[NEWstrlen(from) - 1] = subject[NEWstrlen(subject) - 1] = '\0';
                              DynInsert(headerString, ((DynHigh(headerString) > 0) ? (DynHigh(headerString) + 1) : 0), from, NEWstrlen(from));
                              DynInsert(headerString, ((DynHigh(headerString) > 0) ? (DynHigh(headerString) + 1) : 0), subject, NEWstrlen(subject));
                        }

                        free(from);
                        free(subject);
                  }
            }
            else
            {
                  x = artP[index].lastNum;
                  index++;
            }

            x++;
      }
      return (count);

}

#ifdef TESTNEWS
void main()
{
      BoxInfo_t tempBox;
      Boolean dummy;

      tempBox.articles = DynCreate(sizeof(Articles_t), 2);

      while (1)
      {
            DynObject headers;
            char *hdrPtr;

            headers = DynCreate(sizeof(char), MAX_STRING);
            tempBox.box = "uva.general";

            printf("There are %i articles\n", CountNNTP(&tempBox, NULL, &dummy));

            CountNNTP(&tempBox, headers, &dummy);
            DynAdd(headers, '\0');
            hdrPtr = (char *) DynGet(headers, 0);

            printf("\n*********************\n%s\n", hdrPtr);

            printf("done\n");
            sleep(20);
      }

}

#endif

Generated by  Doxygen 1.6.0   Back to index