#include <stdio.h>

#include <pwd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <sys/time.h>

#include <sys/stat.h>

#include <unistd.h>

#include <fcntl.h>

#include <string.h>


#include "newsfetch.h"


extern int terminate, wait_after_articles, wait_for_time, articles_fetched;
extern int last_than_current, first_article, max_article, news_target;
extern int timeout, article_fetching;
extern char dirname[100], group[100], pipe_command[100];
extern FILE *rcfp, *rctmpfp, *socket_fp[2];

char *header;
#define MAXBUFSIZE 500

#define GROUP_FMT "%99s"
char command_buf[MAXBUFSIZE+1];

readNNTPdata()
{
	alarm(timeout);
	fgets(command_buf,MAXBUFSIZE,socket_fp[1]);
	alarm(0);
}

setReaderMode()
{
	/* dummy read to flush input */
	readNNTPdata();
	fprintf(socket_fp[0],"MODE READER\r\n");
	readNNTPdata();
return(get_error(command_buf));
}

get_error(char *buf)
{
int result;
	sscanf(buf,"%d",&result);
	if(result >= 200 && result < 300)
		return(1);
	
	/* Print error message */
	fprintf(stderr,"%s",buf);	
return(0); 
}

get_error1(char *buf)
{
int result;
	sscanf(buf,"%d",&result);
	if(result >= 200 && result < 300)
		return(1);
return(0); 
}

get_error2(char *buf)
{
int result, space=0x20;
char *errMsg; 

	sscanf(buf,"%d",&result);
	if(result >= 200 && result < 300)
		return(1);

	errMsg=strchr(buf, space);	
	/* Print error message with a leading space*/
	fprintf(stderr,"%s",errMsg);	
return(0); 
}


set_article_number(char *buf)
{
int result;
	sscanf(buf,"%d %d",&result, &first_article);
		return(1);
}

FILE * getNewsFileFd()
{
char news_filename[200];
FILE *newsfp;
	
	if(news_target == 2 || news_target == 3)
		return(stdout);
	
	if(news_target == 4 )
		{
		newsfp = popen(pipe_command, "w");
		if(newsfp == NULL)
			perror(pipe_command);

		return(newsfp);
		}

	strcpy(news_filename,dirname);
	if(strlen(dirname))
			strcat(news_filename,"/");
	strcat(news_filename,group);
	
	#ifdef DEBUG

		fprintf(stderr, "maildir %s\n",news_filename);
	#endif


	if((newsfp=fopen(news_filename,"a+"))==NULL)
                fprintf(stderr,"Can not create news file...aborting\n");

return(newsfp);
}

getNextGroup()
{

char *tmp;
int items_read,comment=1;
	
	max_article = -1;
	
while(comment)
	{
	tmp=fgets(command_buf, MAXBUFSIZE, rcfp);
	
	if(tmp == NULL)
		return(0);

	#ifdef DEBUG

		fprintf(stderr, "get_next_group: %s\n",command_buf);
	#endif


	for(items_read =0; command_buf[items_read] == 0x20 ; items_read++)
		;
	if(command_buf[items_read] != '#' && command_buf[items_read] != '\n')
		comment = 0;
	else
		fprintf(rctmpfp,"%s",command_buf);
	}
	items_read=sscanf(command_buf,GROUP_FMT "%d %d", group, &first_article, &max_article);
	group[sizeof(group)-1] = '\0';
	if(items_read < 2)
		return(0);
return(items_read);
}	

checkGroup()
{
int first_art, last_art, total_art, tmp ;

	fprintf(stderr,"%s: ",group);
	fprintf(socket_fp[0],"GROUP %s\r\n",group);
	readNNTPdata();
	
	#ifdef DEBUG

		fprintf(stderr,"fetch group: %s\n",command_buf);
	#endif

	
	if(!get_error2(command_buf))
		{
		first_article--;
		return(0);
		}

	sscanf(command_buf,"%d %d %d %d",&tmp,&total_art,&first_art,&last_art);
	if(first_article > last_art)
		{
		fprintf(stderr,"No new articles\n");	
		first_article = last_art;
		return(0); 
		}
	if(first_article < first_art)
		first_article = first_art;

	if(max_article != -1)
	{	
	if((last_art - first_article) + 1 > max_article)
		first_article = last_art - max_article + 1;
	}
	
	fprintf(socket_fp[0],"STAT %d\r\n",first_article);
	readNNTPdata();

	while(!get_error1(command_buf))
		{
		first_article++;

		/* Some news server appear to give the article number 
                of expired articles, check for the last_art */
		if(first_article > last_art)
			{
			fprintf(stderr,"No new articles: Should not happen\n");	
			first_article = last_art;
			return(0); 
			}

		fprintf(socket_fp[0],"STAT %d\r\n",first_article);
		readNNTPdata();
		}
	fprintf(stderr,"articles %d to %d\n",first_article,last_art);
return(1);
}

fetchGroup()
{
FILE *newsfp;
int tmp=1;
	
	if((newsfp = getNewsFileFd()) == NULL)
		{

	/* This is perfect even if article number became invalid since 
	   in next run ++ operation will make it valid article and save 
	   STAT time */

		first_article--;
		return(-1);
		}

	for(; tmp=fetchArticle(newsfp) && terminate ;);

	first_article = last_than_current;

	if(news_target < 3)
		fclose(newsfp);

	if(news_target == 4 )
		pclose(newsfp);

	#ifndef NO_STATUS_METER

	if(isatty(2))
		fprintf(stderr,"                                             %c",0xd);
	#endif


if(terminate)
	return(1);
return(-1);
}

fetchArticle(FILE *fp1)
{
int check_header = 1;
	
	/* Limit is article_fetched and wait_for articles are interger 
	   In rare case, article fetched can be wrap around 	
	*/
	if( wait_after_articles && articles_fetched == wait_after_articles )
	{
	if(isatty(2))
		fprintf(stderr,"Waiting for %d seconds%c",wait_for_time,0xd); 
	articles_fetched = 0;
	sleep(wait_for_time);
	if(isatty(2))
		fprintf(stderr,"                                    %c",0xd);
	}

	fprintf(socket_fp[0],"ARTICLE\r\n");
	readNNTPdata();
	if(!get_error(command_buf))
		return(0);	

	articles_fetched++;

	if(news_target == 3 )
		{
		/* forget about old fp1, make it more simple */
		fp1 = popen(pipe_command, "w");
		if(fp1 == NULL)
			{
			perror(pipe_command);
			return(-1);
			}
		}

	/* Make it little fast */
	fprintf(socket_fp[0],"NEXT\r\n");

	article_fetching=1;

#ifndef NO_STATUS_METER

if(isatty(2))
	{
	fprintf(stderr,"                                             %c",0xd);
	fprintf(stderr,"%d%c",first_article, 0xd);
	}
#endif


	readNNTPdata();

	/* Put any date, require by many mail reader */	
	fprintf(fp1,"From localhost Sat Apr 26 18:57:03 WAT 1997\n");
	while(command_buf[0] != '.' || command_buf[1] != 13 )/*|| command_buf[1] != 10)*/
		{
		
		if(command_buf[0] == '.' && command_buf[1] =='.')
			command_buf[1]=0x20;
		if(command_buf[strlen(command_buf)-2] == 0xd || command_buf[strlen(command_buf)-2] == 0x0a)
			command_buf[strlen(command_buf)-2] = '\0';
		if(command_buf[strlen(command_buf)-1] == 0xd || command_buf[strlen(command_buf)-1] == 0x0a)
			command_buf[strlen(command_buf)-1] = '\0';
		
		fprintf(fp1,"%s\n",command_buf);
		if(check_header && (strncasecmp(command_buf,"Newsgroups:",10)) == 0)
			{
			fprintf(fp1,"%s: %s\n",NEWSFETCH_HEADER_INCL, group);
			check_header = 0;
			}
		readNNTPdata();
		}
	fprintf(fp1,"\n");
	if(news_target == 3 )
		pclose(fp1);
	last_than_current = first_article;
	article_fetching=0;
	if(terminate)
	{
		readNNTPdata();
		if(!get_error1(command_buf))
			return(0);	
		set_article_number(command_buf);
	}
return(1);
}

getGroupList()
{
char groupname[100];

	fprintf(stderr, "\nList of NewsGroups:\n"); 
	fprintf(socket_fp[0],"LIST\r\n");
	readNNTPdata();
	if(!get_error2(command_buf))
		exit(1);	
	readNNTPdata();
	sscanf(command_buf,GROUP_FMT,groupname);
	groupname[sizeof(groupname)-1] = '\0';
	while(command_buf[0] != '.' || command_buf[1] != 13 )/*|| command_buf[1] != 10)*/
		{
		fprintf(stderr,"%s\n",groupname);
		readNNTPdata();
		sscanf(command_buf,GROUP_FMT,groupname);
		groupname[sizeof(groupname)-1] = '\0';
		}
exit(1);

}

sendQuit()
{

	fprintf(socket_fp[0],"QUIT\r\n");
	readNNTPdata();
}

fill_tmpfile()
{
char *tmp;

	while((tmp=fgets(command_buf, MAXBUFSIZE, rcfp)) != NULL)
        	fprintf(rctmpfp,"%s",command_buf);
 	
}


syntax highlighted by Code2HTML, v. 0.9.1