#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <proto/dos.h>
#include <proto/exec.h>

#include "/lib/iomodes.h"
#include "rn.h"

#define MAXGROUPS	256
#define NAMELEN		80
#define MAXNAMELEN	256
#define MAXIDS		600
#define IDLEN		60
#define LOGINLINES	30	/* Max number of send-expect-lines */

#define MAXHOSTS	24	/* number of the hosts in the sys-file */
#define HOSTNAMELEN	32
#define MAXPATTERNS	48	/* max patterns for each host */
#define PATTERNLEN	32
#define CACHESIZE	8

static far char BatchHost[MAXHOSTS][HOSTNAMELEN];
static far char BatchCacheS[MAXHOSTS][CACHESIZE][MAXNAMELEN];
static far int  BatchCacheD[MAXHOSTS];
static far int  BatchHosts;
static far char BatchPattern[MAXHOSTS][MAXPATTERNS][PATTERNLEN];
static far int  BatchPatterns[MAXHOSTS];

#define BUFFERSIZE	32768	/* message save buffer */


char version[]="\0$VER: NNTPNews 1.22 (07.11.95)\n";

/*********************************************************************
	Add to rc.news: This is for news.cc.tut.fi ..

%nntplogin:		[send expect1 expect2]
\n						kaima-ts>	kummi-ts>
"term flow hard\n"		kaima-ts>	kummi-ts>
"term telnet-t\n"		kaima-ts>	kummi-ts>
"telnet news.cc.tut.fi 119\n"	200 201
#

%nntpdebug:		[debug level for nntpnews (2=log everything (SLOW!))]
0
*********************************************************************/

static int NumNNTP=0,NNTPHighs[MAXGROUPS],IDs=0,Loginlines=0,Debuglevel=0;
char *buffer=0,
		NNTPGroups[MAXGROUPS][NAMELEN],
		Timezone[10]="GMT",
		Host[NAMELEN]="pasbox"; /* %thismachine */
static far char ArticleIDs[MAXIDS][IDLEN];
static long receivedbytes=0,sentbytes=0;

char	Newshome[NAMELEN]=		"AXsh:usr/spool/news/",
		Batchfile[NAMELEN]=		"AXsh:usr/spool/news/%s.batch",
		Sysfile[NAMELEN]=		"AXsh:usr/spool/news/Sys",
		Postnews[NAMELEN]=		"internal",
		Netlogfile[NAMELEN]=	"AXsh:etc/adm/netlog",
		Newsgroupfile[NAMELEN]=	"AXsh:usr/spool/news/NewsGroups",
		Activefile[NAMELEN]=	"none",
		NNTPgroupfile[NAMELEN]=	"AXsh:usr/spool/news/NNTPGroups",
		NNTPlogin[LOGINLINES][NAMELEN]={"\n","\"telnet cc.tut.fi 119\"",""};
static struct DateStamp intime,outtime;


FILE *fopen();
void chkabort(void) {}
void __regargs __chkabort(void);
void __regargs __chkabort(void){}

int  readbatches(char *sysfile);
int  batchgroup(int host,char *group);

void read_NNTPGroups(void);
void write_NNTPGroups(void);
void read_config(void);
int  get_line(char *line,int maxlen,int timeout,int mode);	/* timeout in ms , 1000ms = 1sec*/
void hangup(void);
void cleanexit(char *reason);
int  haveid(char *newid);
void debug(int level,char *format,char *string);
void separateSE(char *,char *,char *,char *);


void separateSE(char *line,char *send,char *expect1,char *expect2)
{
	int i=0,j=0,linemode=0,mode=0;
	char temp[NAMELEN];

	send[0]=expect1[0]=expect2[0]='\0';
	while(1)
	{
		switch(line[i])
		{
		case '\\':
			switch(line[i+1])
			{
			case 'n':
				temp[j++]='\n';
				break;
			case 't':
				temp[j++]='\t';
				break;
			case 'r':
				temp[j++]='\r';
				break;
			case '\0':
				temp[j++]='\\';
				break;
			default:
				temp[j++]=line[i+1];
				break;
			}
			if(line[i+1])
				i+=2;
			else
				i++;
			break;
		case '\"':
			linemode=1-linemode;
			i++;
			break;
		case '\0':
		case ' ':
		case '\t':
			if(!linemode)
			{
				temp[j]=0;
				j=0;
				if(mode==0)
					strcpy(send,temp);
				else
				if(mode==1)
					strcpy(expect1,temp);
				else
				if(mode==2)
					strcpy(expect2,temp);

				while(line[i]=='\t' || line[i]==' ')
					i++;
				if(++mode>2 || !line[i])
					return;
				break;
			}
			/* else fall thru */
		default:
			temp[j++]=line[i++];
		}
	}
}

void debug(int level,char *format,char *string)
{
	FILE *fp;

	if(!format || Debuglevel<level)
		return;
	if(fp=fopen("AXsh:etc/adm/nntpnews.log","ab"))
	{
		fprintf(fp,format,string);
		fclose(fp);
	}
}


void cleanexit(char *reason)
{
	FILE *fp;
	long tim;
	char rivi[MAXNAMELEN];

	if(fp=fopen(Netlogfile,"a"))
	{
		DateStamp(&outtime);
		tim=((outtime.ds_Days-intime.ds_Days)*1440+outtime.ds_Minute-intime.ds_Minute)*60+(outtime.ds_Tick-intime.ds_Tick)/50;
		if(!tim)
			tim=1;
		fprintf(fp,"108 %d minutes with NNTP host\n",(tim+30)/60);

		if(receivedbytes+sentbytes)
		{
			fprintf(fp,"200 rz: %ld bytes, %ld cps, %06ld elapsed : NNTP data (interactive)\n",
					receivedbytes+sentbytes, (receivedbytes+sentbytes)/tim, tim);
			receivedbytes=sentbytes=0;
		}
		fprintf(fp,"105 %s (%s)\n",get_time(),reason);
		fclose(fp);
	}
	write_NNTPGroups();

	printf("exit\n");	/* exit whatever */
	tim=0;
	do
	{
		if(get_line(rivi,MAXNAMELEN,10000,0))
		{
			tim++;
			printf("exit\n");	/* exit whatever */
		}
	}
	while(strncmp(rivi,"NO CARRIER",10) && tim<4);

	hangup();
	if(buffer)
		FreeMem(buffer,BUFFERSIZE);

	setmode(MODE_CONSOLE);
	exit(0);
}

void hangup(void)
{
	setmode(MODE_RAW);
	Delay(200);
	Write(Output(),"+++",3);
	Delay(250);
	Write(Output(),"ath0\r",5);
	Delay(50);
}


#define BUFSIZE	512
int	get_line(char *line,int maxlen,int timeout,int mode)
{
	static char	buffer[BUFSIZE];
	static int	bufpos=0;
	register	int i,j,len,lf;

	lf=-1;
	for(i=0;i<bufpos;i++)
	{
		if(buffer[i]==0x0a)
		{
			lf=i;
			break;
		}
	}

	if(lf==-1 && bufpos<maxlen-1)
	{
		do
		{
			if(WaitForChar(Input(),1000*timeout))
			{
				len=Read(Input(),buffer+bufpos,BUFSIZE-bufpos);
				j=bufpos;
				if(len<0)
					break;

				bufpos+=len;
				receivedbytes+=len;
				while(len--)
				{
					if(buffer[j]==0x0a)
					{
						lf=j;
						break;
					}
					j++;
				}
			}
			else	/* timeout, give them everything we got */
			{
				i=j=0;
				/* Remove CR's while copying */
				while(j<bufpos)
				{
					if((line[i]=buffer[j++])!='\r')
						i++;
				}
				line[i]=0;
				bufpos = 0;

				debug(2,"# %s\n",line);
				return -1;
			}
		} while(lf==-1 && bufpos<maxlen-1);
	}

	if(lf!=-1)	/* we have a complete line */
	{
		if(lf<maxlen-1)
		{
			i=j=0;
			/* Remove CR's while copying */
			while(j<lf+1)
			{
				if((line[i]=buffer[j++])!='\r')
					i++;
			}
			line[i]=0;

			bufpos -= lf+1;
			memcpy(buffer, buffer+lf+1, bufpos);

			debug(2,"# %s\n",line);
			return 0;
		}
		else
		{
			i=j=0;
			/* Remove CR's while copying */
			while(j<maxlen-1)
			{
				if((line[i]=buffer[j++])!='\r')
					i++;
			}
			line[i]=0;

			bufpos -= maxlen-1;
			memcpy(buffer, buffer+maxlen-1, bufpos);

			debug(2,"# %s\n",line);
			return 0;
		}
	}
	if(bufpos>=maxlen-1)	/* we have enough to fill the request */
	{
		i=j=0;
		/* Remove CR's while copying */
		while(j<maxlen-1)
		{
			if((line[i]=buffer[j++])!='\r')
				i++;
		}
		line[i]=0;

		bufpos -= maxlen-1;
		memcpy(buffer, buffer+maxlen-1, bufpos);

		debug(2,"# %s\n",line);
		return 0;
	}
	return 0;
}


int haveid(char *newid)
{
	int k=0;

	if(!newid)
	{
		if(IDs)
			IDs--;
		return 0;
	}

	if(IDs)
	{
		while(k<IDs && strcmp(ArticleIDs[k],newid))
			k++;
	}
	if(k==IDs)
	{
		if(IDs<MAXIDS-1)
			strncpy(ArticleIDs[IDs++],newid,IDLEN);
		return 0;
    }
	else
		return -1;
}


void read_NNTPGroups()
{
	int i;
    char temp[MAXNAMELEN];
	FILE *handle;

	if(handle=fopen(NNTPgroupfile,"rb"))
	{
		while(!feof(handle))
		{
			if(fgets(temp,MAXNAMELEN-2,handle)==0)
				break;
			if(i=strlen(temp))
				temp[i-1]=0;

			i=0;
			while(temp[i] && temp[i]!=' ' && temp[i]!='\t')
				i++;

			if(temp[i] && i)	/* if don't have value or name, do not take it */
			{
				strncpy(NNTPGroups[NumNNTP],temp,i);
				NNTPGroups[NumNNTP][i]=0;
				NNTPHighs[NumNNTP++]=atoi(temp+i+1);
			}
		}
		fclose(handle);
	}
}


void write_NNTPGroups()
{
	int i;
	FILE *handle;

	if(handle=fopen(NNTPgroupfile,"wb"))
	{
		for(i=0;i<NumNNTP;i++)
			fprintf(handle,"%s %d\n",NNTPGroups[i],NNTPHighs[i]);
		fclose(handle);
	}
}


void read_config()
{
	FILE *handle;
	char line[NAMELEN];
	int i,found=0;

	if(handle=fopen("AXsh:etc/rc","rb"))	/* luetaan config */
	{
		while(!feof(handle))
		{
			if(fgets(line,NAMELEN-1,handle)==0)
				break;
			if(i=strlen(line))
				line[i-1]=0;

			if(found==0)
			{
				if(!strncmp(line,"%thismachine:",13))
					found=1;
				if(!strncmp(line,"%timezone:",10))
					found=2;
				if(!strncmp(line,"%news:",6))
					found=3;
			}
			else
			{
				if(found==1)
					strcpy(Host,line);
				if(found==2)
				{
					strncpy(Timezone,line,9);
					Timezone[9]=0;
				}
				if(found==3)
					strcpy(Newshome,line);
				found=0;
			}
		}
		fclose(handle);
	}
	else
	{
		fprintf(stderr,"Can't open AXsh:etc/rc");
	}

	if(handle = fopen("AXsh:etc/rc.news","rb"))	/* luetaan news-config */
	{
		while(!feof(handle))
		{
			if(fgets(line,NAMELEN-1,handle)==0)
				break;
			if(i=strlen(line))
				line[i-1]=0;

			if(found==0)
			{
				if(!strncmp(line,"%nntpdebug:",11))		found=1;
				if(!strncmp(line,"%batchfile:",11))		found=2;
				if(!strncmp(line,"%sysfile:",9))		found=3;
				if(!strncmp(line,"%postnews:",10))		found=5;
				if(!strncmp(line,"%netlogfile:",12))	found=8;
				if(!strncmp(line,"%newsgroupfile:",15))	found=9;
				if(!strncmp(line,"%nntpgroupfile:",15))	found=10;
				if(!strncmp(line,"%activefile:",12))	found=11;
				if(!strncmp(line,"%newshome:",10))		found=12;
				if(!strncmp(line,"%nntplogin:",11))
				{
					found=13;
					Loginlines=0;
				}
			}
			else
			{
				if(found==13)
				{
					if(line[0] && line[0]!='#')
					{
						strcpy(NNTPlogin[Loginlines++],line);
						if(Loginlines==LOGINLINES)
							found=0;
					}
					else
						found=0;
				}
				else
				{
					if(found==1)	Debuglevel=atoi(line);
					if(found==2)	strcpy(Batchfile,line);
					if(found==3)	strcpy(Sysfile,line);
					if(found==5)	strcpy(Postnews,line);
					if(found==8)	strcpy(Netlogfile,line);
					if(found==9)	strcpy(Newsgroupfile,line);
					if(found==10)	strcpy(NNTPgroupfile,line);
					if(found==11)	strcpy(Activefile,line);
					if(found==12)	strcpy(Newshome,line);
					found=0;
				}
			}
		}
		fclose(handle);
	}
	/* Settings in /etc/adm/rc.news override */
	if(handle = fopen("AXsh:etc/adm/rc.news","rb"))	/* luetaan news-config */
	{
		while(!feof(handle))
		{
			if(fgets(line,NAMELEN-1,handle)==0)
				break;
			if(i=strlen(line))
				line[i-1]=0;

			if(found==0)
			{
				if(!strncmp(line,"%nntpdebug:",11))		found=1;
				if(!strncmp(line,"%batchfile:",11))		found=2;
				if(!strncmp(line,"%sysfile:",9))		found=3;
				if(!strncmp(line,"%postnews:",10))		found=5;
				if(!strncmp(line,"%netlogfile:",12))	found=8;
				if(!strncmp(line,"%newsgroupfile:",15))	found=9;
				if(!strncmp(line,"%nntpgroupfile:",15))	found=10;
				if(!strncmp(line,"%activefile:",12))	found=11;
				if(!strncmp(line,"%newshome:",10))		found=12;
				if(!strncmp(line,"%nntplogin:",11))
				{
					found=13;
					Loginlines=0;
				}
			}
			else
			{
				if(found==13)
				{
					if(line[0] && line[0]!='#')
					{
						strcpy(NNTPlogin[Loginlines++],line);
						if(Loginlines==LOGINLINES)
							found=0;
					}
					else
						found=0;
				}
				else
				{
					if(found==1)	Debuglevel=atoi(line);
					if(found==2)	strcpy(Batchfile,line);
					if(found==3)	strcpy(Sysfile,line);
					if(found==5)	strcpy(Postnews,line);
					if(found==8)	strcpy(Netlogfile,line);
					if(found==9)	strcpy(Newsgroupfile,line);
					if(found==10)	strcpy(NNTPgroupfile,line);
					if(found==11)	strcpy(Activefile,line);
					if(found==12)	strcpy(Newshome,line);
					found=0;
				}
			}
		}
		fclose(handle);
	}
}


int readbatches(char *sysfile)
{
	char line[2*MAXNAMELEN],pat[MAXNAMELEN];
	FILE *handle;
	int i,j,curpos;

	BatchHosts=0;
	if(handle=fopen(sysfile,"rb"))
	{
		while(!feof(handle))
		{
			curpos = 0;
again:
			if(fgets(line+curpos,2*MAXNAMELEN-curpos,handle)==0)
				break;
			i=strlen(line)-1;
			if(i<0 || feof(handle))
				break;
			if(i<2*MAXNAMELEN-20 && line[i-1]=='\\')	/* Line continuation */
			{
				curpos = i-1;
				line[i-1] = '\0';
				goto again;
			}

			line[i] = '\0';

			if(i && line[0]!='#')
			{
				i=0;
				while(line[i] && line[i]!=':')
					++i;
				if(line[i])
					line[i]=0;
				else
					line[i+1]=0;
				strcpy(BatchHost[BatchHosts],line);		/* hostname */

				strcpy(pat,line+i+1);	/* newsgroup patterns */

				j=0;
				while(pat[j])		/* for each pattern */
				{
					i=j;
					while(pat[j] && pat[j]!=',')
						j++;

					strncpy(BatchPattern[BatchHosts][BatchPatterns[BatchHosts]],pat+i,j-i);
					BatchPattern[BatchHosts][BatchPatterns[BatchHosts]][j-i]='\0';

					BatchPatterns[BatchHosts]++;
					while(pat[j]==',' || pat[j]==' ' || pat[j]=='\t')
						j++;

				}	/* for all patterns */
				BatchHosts++;
			}
		}
		fclose(handle);
	}
	return 0;
}


int batchgroup(int host,char *group)
{
	int match,i;

	match=0;
	for(i=0;i<BatchPatterns[host];i++)	/* for each pattern */
	{
/*		for(k=0;k<numgrp;k++)
		{*/	/* for each x-posted group */

			if(BatchPattern[host][i][0]=='-')
			{
				if(simplepatternmatch(group,BatchPattern[host][i]+1))
				{	match=0;
				}
			}
			else
			{
				if(simplepatternmatch(group,BatchPattern[host][i]))
				{	match=-1;
				}
			}

/*		}*/
	}
	if(match)
		return -1;
	else
		return 0;
}

/*
news.cc.tut.fi

100 This server accepts the following commands:
ARTICLE     BODY         GROUP
HEAD        LAST         LIST
NEXT        POST         QUIT
STAT        NEWGROUPS    HELP
IHAVE       NEWNEWS      SLAVE

article 2400
423 Invalid article number: 2400.

*/

void main(int argc,char *argv[])
{
	char rivi[MAXNAMELEN+4],Path[MAXNAMELEN+2],name[2*NAMELEN];
	char send[NAMELEN],exp1[NAMELEN],exp2[NAMELEN];
	int tim,i,j,group,low,high,msgnum=0,grpmsg,crossposts,bufptr=0,number;
	long handle;
	short HostFlag[MAXHOSTS];
	FILE *fp;

	DateStamp(&intime);
	read_config();

	if(!(buffer=(char *)AllocMem(BUFFERSIZE,MEMF_CLEAR)))
	{
		if(fp=fopen(Netlogfile,"a"))
		{
			fprintf(fp,"000 %s Memory allocation failed!\n",get_time());
			fclose(fp);
		}
		exit(0);
	}
	setmode(MODE_RAW | MODE_NOCRLF);
	read_NNTPGroups();
	readbatches(Sysfile);

	for(i=0;i<Loginlines;i++)
	{
		separateSE(NNTPlogin[i],send,exp1,exp2);
		tim=0;

		sentbytes+=printf("%s",send);
		debug(1,"Sent: %s\n",send);
		do
		{
			if(get_line(rivi,200,2000,0))
			{
				tim++;
				if(tim==5)
				{
					sentbytes+=printf("%s",send);
					debug(1,"Sent: %s\n",send);
				}
			}
			debug(1,"Recv: %s\n",rivi);
		}
		while(	(exp1[0]=='\0' || !strstr(rivi,exp1)) &&
				(exp2[0]=='\0' || !strstr(rivi,exp2)) && tim<8);
		if(tim==8)
		{
			cleanexit("Timeout in login");
		}
	}

	if(fp=fopen(Netlogfile,"a"))
	{
		fprintf(fp,"100 %s\n",get_time());
		fclose(fp);
	}
	debug(1,"NNTP server responded.\n",NULL);

	for(group=0;group<NumNNTP;group++)
	{
		sentbytes+=printf("group %s\n",NNTPGroups[group]);
		tim=grpmsg=crossposts=0;
		do
		{
			if(tim==3)
			{
				sentbytes+=printf("group %s\n",NNTPGroups[group]);
			}
			if(get_line(rivi,200,10000,0))
			{
				tim++;
			}
		}
		while(strncmp(rivi,"411",3) && strncmp(rivi,"211",3) && tim<5);

		debug(1,"Response to group %s\n",NNTPGroups[group]);
		debug(1,"\t%s\n",rivi);

		if(!strncmp(rivi,"211",3))
		{
			if(!is_group(NNTPGroups[group]))
			{
				add_group(NNTPGroups[group],7,FLAG_READ_ONLY);
			}
			i=4;	/* "211 num low high" */
			while(rivi[i] && rivi[i]!=' ')	i++;
			low=atoi(rivi+i+1);
			i+=2;
			while(rivi[i] && rivi[i]!=' ')	i++;
			high=atoi(rivi+i+1);
			if(high<NNTPHighs[group])
				high=NNTPHighs[group];

			if(NNTPHighs[group]<0)
				NNTPHighs[group]=high;

			if(NNTPHighs[group]<high-50)
				NNTPHighs[group]=high-50;
			if(NNTPHighs[group]<low)
				NNTPHighs[group]=high-5;

			/* set the batch-flags */
			for(i=0;i<BatchHosts;i++)
			{
				if(batchgroup(i,NNTPGroups[group]))
					HostFlag[i]=TRUE;
				else
					HostFlag[i]=FALSE;
				BatchCacheD[i]=0;
			}

			sentbytes+=printf("stat %d\n",NNTPHighs[group]);
			if(get_line(rivi,MAXNAMELEN,10000,0))
				cleanexit("Timeout in get_line1");	/* get my line */
			if(get_line(rivi,MAXNAMELEN,40000,0))
				cleanexit("Timeout in get_line2");	/* get response */

			while(!strncmp(rivi,"423",3) && NNTPHighs[group]<high)
			{								/* 423 Bad article number */
				NNTPHighs[group]++;			/* Try the next one.. */
				sentbytes+=printf("stat %d\n",NNTPHighs[group]);
				if(get_line(rivi,MAXNAMELEN,10000,0))
					cleanexit("Timeout in get_line3");	/* get my line */
				if(get_line(rivi,MAXNAMELEN,10000,0))
					cleanexit("Timeout in get_line4");	/* get response */
			}

			while(strncmp(rivi,"241",3) && NNTPHighs[group]<high)
			{
				sentbytes+=printf("next\n");
				if(get_line(rivi,MAXNAMELEN,10000,0))
					cleanexit("Timeout in get_line5");	/* get my line */
				if(get_line(rivi,MAXNAMELEN,40000,0))
					cleanexit("Timeout in get_line6");	/* get response */
				if(strncmp(rivi,"223",3))
					break;
				i=4;	/* 223 num <id> blaablaa */
				while(rivi[i] && rivi[i]!='<')
					i++;

				strcpy(rivi,rivi+i);
				i=0;
				while(rivi[i] && rivi[i]!=' ')	i++;
				rivi[i]=0;	/* now we have just the article-ID */
				if(!haveid(rivi))
				{
					sentbytes+=printf("article\n");
					if(get_line(rivi,MAXNAMELEN,10000,0))
						cleanexit("Timeout in get_line7");	/* get my line */
					if(get_line(rivi,MAXNAMELEN,10000,0))
						cleanexit("Timeout in get_line8");	/* get response */
					if(!strncmp(rivi,"220",3))
					{
						Path[0]=0;
						number=inc_next(NNTPGroups[group]);
						articlename(name,NNTPGroups[group],number,0);
						i=atoi(rivi+4);
						if(i>NNTPHighs[group])
							NNTPHighs[group]=i;

						handle=Open(name,MODE_NEWFILE);
						grpmsg++;
						while(1)
						{
							if(get_line(rivi,MAXNAMELEN,6000,0))
								break;
							if(rivi[0]=='.')
							{
								if(rivi[1]==0 || (rivi[1]=='\n' && rivi[2]==0))
									break;
							}
							if(handle && strncmp(rivi,"Xref: ",6))
							{
								if(!strncmp(rivi,"Path:",5))
									strcpy(Path,rivi+6);
								if(!strncmp(rivi,"Newsgroups:",11))
								{
									if(!strstr(rivi,","))
									{
										/* If there is only one group, it   */
										/* is quite likely not a crosspost. */
										/* So, remove the ID from the cache.*/
										haveid(NULL);
									}
								}
								if(bufptr+strlen(rivi)+1<BUFFERSIZE)
								{
									if(rivi[0]=='.')
									{
										strcpy(buffer+bufptr,rivi+1);
										bufptr+=strlen(rivi+1);
									}
									else
									{
										strcpy(buffer+bufptr,rivi);
										bufptr+=strlen(rivi);
									}
									/*buffer[bufptr++]='\n';*/	/* add linefeed */
								}
								else
								{
									Write(handle,buffer,bufptr);
									if(rivi[0]=='.')
										Write(handle,rivi+1,strlen(rivi+1));
									else
										Write(handle,rivi,strlen(rivi));
									/*Write(handle,"\n",1);*/
									bufptr=0;
								}
							}
						}
						if(handle)
						{
							if(bufptr)
							{
								Write(handle,buffer,bufptr);
								bufptr=0;
							}
							Close(handle);
						}
						articlename(name,NNTPGroups[group],number,-1);
						for(i=0;i<BatchHosts;i++)
						{
							/* if match and no not-wanted group and host not in Path-line */
							sprintf(rivi,"%s!",BatchHost[i]);
							if(HostFlag[i] && strncmp(Path,rivi,strlen(rivi)))
							{
								sprintf(rivi,"!%s!",BatchHost[i]);
								if(!strstr(Path,BatchHost[i]))
								{
									sprintf(rivi,Batchfile,BatchHost[i]);
									if(BatchCacheD[i]==CACHESIZE)
									{
										if(fp=fopen(rivi,"ab"))
										{
											for(j=0;j<BatchCacheD[i];j++)
											{
												fprintf(fp,"%s\n",BatchCacheS[i][j]);
											}
											fprintf(fp,"%s\n",name);
											fclose(fp);
										}
										BatchCacheD[i]=0;
									}
									else
									{
										strcpy(BatchCacheS[i][BatchCacheD[i]],name);
										BatchCacheD[i]++;
									}
								}
							}
						}
					}
				}	/* else we have already received this message (cross-postings) */
				else
					crossposts++;
			}
		}
		else if(!strncmp(rivi,"411",3))
		{
			/* there was no such group, so we take it off the list.. :-) */
			NNTPGroups[group][0]='\0';	/* we cannot swap group positions, because we have already received some msgs */
		}
		else
		{
			cleanexit("Unknown response to group command");
		}

		if(grpmsg)
		{
			write_NNTPGroups();
			debug(1,"write_NNTPGroups() performed.\n",NULL);

			msgnum+=grpmsg;
			if(fp=fopen(Netlogfile,"a"))
			{
				fprintf(fp,"102 %d %s\n",grpmsg,NNTPGroups[group]);
				if(crossposts)
					fprintf(fp,"103 %d %s\n",crossposts,NNTPGroups[group]);
				fclose(fp);
			}
		}
	}

	/* Flush cache */
	for(i=0;i<BatchHosts;i++)
	{
		if(BatchCacheD[i])
		{
			sprintf(rivi,Batchfile,BatchHost[i]);
			if(fp=fopen(rivi,"ab"))
			{
				for(j=0;j<BatchCacheD[i];j++)
				{
					fprintf(fp,"%s\n",BatchCacheS[i][j]);
				}
				fclose(fp);
			}
			BatchCacheD[i]=0;
		}
	}

	debug(1,"Exiting NNTP server.\n",NULL);

	sentbytes+=printf("quit\n");	/* exit NNTP-server */
	tim=0;
	do
	{
		if(get_line(rivi,MAXNAMELEN,10000,0))
			tim++;
	}
	while(strncmp(rivi,"205",3) && tim<4);
	if(strncmp(rivi,"205",3))
		cleanexit("NNTP quit not worked");

	if(fp=fopen(Netlogfile,"a"))
	{
		fprintf(fp,"104 %d messages total\n",msgnum);
		DateStamp(&outtime);
		tim=((outtime.ds_Days-intime.ds_Days)*1440+outtime.ds_Minute-intime.ds_Minute)*60+(outtime.ds_Tick-intime.ds_Tick)/50;
		if(!tim)
			tim=1;
		fprintf(fp,"108 %d minutes with NNTP host\n",(tim+30)/60);
		fprintf(fp,"200 rz: %ld bytes, %ld cps, %06ld elapsed : NNTP data (interactive)\n",
					receivedbytes+sentbytes, (receivedbytes+sentbytes)/tim, tim);
		fprintf(fp,"106 %s\n\n",get_time());
		receivedbytes=sentbytes=0;
		fclose(fp);
	}

	write_NNTPGroups();
	printf("exit\n");	/* exit terminal server */
	tim=0;
	do
	{
		if(get_line(rivi,MAXNAMELEN,10000,0))
		{
			tim++;
			printf("exit\n");	/* exit terminal server */
		}
	}
	while(strncmp(rivi,"NO CARRIER",10) && tim<4);

	if(buffer)
		FreeMem(buffer,BUFFERSIZE);

	setmode(MODE_CONSOLE);
	exit(0);
}

