#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <devices/console.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <stdio.h>
#include <time.h>
#include <error.h>

#define ERROR		10
#define OK			0
#define NOCARRIER	32

int CXBRK(void) { return(0); }

BYTE OpenConsole (struct IOStdReq *,struct IOStdReq *,struct Window *);
BYTE OpenSerial (struct IOExtSer *,struct IOExtSer *);
BYTE OpenTimer (struct timerequest *);
void CloseConsole(struct IOStdReq *);
void CloseSerial(struct IOExtSer *);
void CloseTimer(struct timerequest *);
char gettekn(void);
char congettkn(char *);
char sergettkn(char *);
void eka(char);
void conreqtkn(char *);
void serreqtkn(char *);
int puttekn(char *,int);
int conputtekn(char *,int);
void modemcmd(char *,int);
void cleanup(int,char *);
int connection(void);
void sendfile(char *);
void paus(ULONG tid);
int chat(void);
void getconfig(void);
void spara(int);
void brevread(int);
void textdump(void);
void getpsw(char *);

struct NewWindow NiKnewwind = {
	0,0,
	640,256,
	-1,-1,
	CLOSEWINDOW,
	WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG | SMART_REFRESH | 
	NOCAREREFRESH | WINDOWSIZING,
	NULL,
	NULL,
	"ModemAnswer v1.1, © Niklas Lindholm 1990",
	NULL,
	NULL,
	50,50,
	~0,~0,
	WBENCHSCREEN
};

struct Library *IntuitionBase=NULL;
struct Window *NiKwind=NULL;
struct IOStdReq *conwritereq=NULL;
struct MsgPort *conwriteport=NULL;
struct IOStdReq *conreadreq=NULL;
struct MsgPort *conreadport=NULL;
struct IOExtSer *serwritereq=NULL;
struct MsgPort *serwriteport=NULL;
struct IOExtSer *serreadreq=NULL;
struct MsgPort *serreadport=NULL;
struct timerequest *timerreq=NULL;
struct MsgPort *timerport=NULL;
BOOL consoleyes = FALSE;
BOOL serialyes = FALSE;
BOOL timeryes = FALSE;
BOOL writeenabled=TRUE;
char coninput,serinput,conoutput,seroutput,buffer[51],backspace[]={ 8 , 32 , 8 , 0 },
	outbuffer[100],svara[17],init[32],hangup[32],password[31],device[31],brev[50][81];
int buftkn=0,highbaud,hst;

BYTE OpenConsole (writereq,readreq,window)
struct IOStdReq *writereq;
struct IOStdReq *readreq;
struct Window *window;
{
	BYTE error;
	writereq->io_Data = (APTR) window;
	writereq->io_Length = sizeof(struct Window);
	error=OpenDevice("console.device",0,writereq,0);
	readreq->io_Device=writereq->io_Device;
	readreq->io_Unit=writereq->io_Unit;
	return(error);
}

BYTE OpenSerial(writereq,readreq)
struct IOExtSer *writereq;
struct IOExtSer *readreq;
{
	BYTE error;
	writereq->io_SerFlags= SERF_7WIRE;
	error=OpenDevice(device,0,writereq,0);
	writereq->io_Baud=highbaud;
	writereq->io_ReadLen=8;
	writereq->io_WriteLen=8;
	writereq->io_StopBits=1;
	writereq->io_SerFlags |= SERF_XDISABLED;
	writereq->io_SerFlags &= ~SERF_PARTY_ON;
	writereq->IOSer.io_Command = SDCMD_SETPARAMS;
	DoIO(writereq);
	CopyMem(writereq,readreq,sizeof(struct IOExtSer));
	readreq->IOSer.io_Message.mn_ReplyPort = serreadport;
	return(error);
}

BYTE OpenTimer(struct timerequest *treq) {
	BYTE error;
	error=OpenDevice(TIMERNAME,UNIT_VBLANK,treq,0);
	return(error);
}

void CloseConsole(struct IOStdReq *writereq) 
{
	if(!(CheckIO(conreadreq))) {
		AbortIO(conreadreq);
		WaitIO(conreadreq);
	}
	if(!(CheckIO(conwritereq))) {
		AbortIO(conwritereq);
		WaitIO(conwritereq);
	}
	CloseDevice(writereq);
}

void CloseSerial(struct IOExtSer *writereq) {
	if(!(CheckIO(serreadreq))) {
		AbortIO(serreadreq);
		WaitIO(serreadreq);
	}
	if(!(CheckIO(serwritereq))) {
		AbortIO(serwritereq);
		WaitIO(serwritereq);
	}
	CloseDevice(writereq);
}

void CloseTimer(struct timerequest *treq) {
	if(!(CheckIO(timerreq))) {
		AbortIO(timerreq);
		WaitIO(timerreq);
	}
	CloseDevice(treq);
}

char gettekn(void)
{
	struct IntuiMessage *mymess;
	ULONG signals,conreadsig=1L << conreadport->mp_SigBit,windsig=1L << NiKwind->UserPort->mp_SigBit,
		serreadsig=1L << serreadport->mp_SigBit;
	char tkn=0,tmp[51];
	if(buftkn) {
		tkn=buffer[0];
		strcpy(tmp,&buffer[1]);
		strcpy(buffer,tmp);
		buftkn--;
	}
	else {
		while(!tkn) {
		signals=Wait(conreadsig|windsig|serreadsig);
		if(signals & conreadsig) {
			tkn=congettkn(&coninput);
		}
		if(signals & serreadsig) {
			tkn=sergettkn(&serinput);
		}
		if(signals & windsig) {
			mymess=(struct IntuiMessage *)GetMsg(NiKwind->UserPort);
			ReplyMsg(mymess);
			cleanup(OK,"");
		}
		}
	}
	return(tkn);
}

char congettkn(char *whereto)
{
	register temp;
	struct IOStdReq *treadreq;
	if(!(treadreq=(struct IOStdReq *)GetMsg(conreadport))) return(0);
	temp=*whereto;
	conreqtkn(&coninput);
	return((char)temp);
}

char sergettkn(char *whereto) {
	register temp;
	struct IOExtSer *treadreq;
	if(!(treadreq=(struct IOExtSer *)GetMsg(serreadport))) return(0);
	temp=*whereto;
	serreqtkn(&serinput);
	return((char)temp);
}

void coneka(char tecken) {
	conoutput=tecken;
	conwritereq->io_Command=CMD_WRITE;
	conwritereq->io_Data=(APTR)&conoutput;
	conwritereq->io_Length=1;
	DoIO(conwritereq);
}

void eka(char tecken) {
	conoutput=tecken;
	conwritereq->io_Command=CMD_WRITE;
	conwritereq->io_Data=(APTR)&conoutput;
	conwritereq->io_Length=1;
	DoIO(conwritereq);
	seroutput=tecken;
	serwritereq->IOSer.io_Command=CMD_WRITE;
	serwritereq->IOSer.io_Data=(APTR)&seroutput;
	serwritereq->IOSer.io_Length=1;
	DoIO(serwritereq);
}

void conreqtkn(char *whereto)
{
	conreadreq->io_Command= CMD_READ;
	conreadreq->io_Data = (APTR)whereto;
	conreadreq->io_Length = 1;
	SendIO(conreadreq);
}

void serreqtkn(char *whereto) {
	serreadreq->IOSer.io_Command=CMD_READ;
	serreadreq->IOSer.io_Data=(APTR)whereto;
	serreadreq->IOSer.io_Length=1;
	SendIO(serreadreq);
}

int conputtekn(char *pekare,int size) {
	struct IntuiMessage *mymess;
	APTR dummymsg;	
	int antal=1;
	int aborted=FALSE;
	ULONG signals,conwritesig = 1L << conwriteport->mp_SigBit,
		conreadsig = 1L << conreadport->mp_SigBit,windsig = 1L << NiKwind->UserPort->mp_SigBit;
	char tecken;
	conwritereq->io_Command=CMD_WRITE;
	conwritereq->io_Data=(APTR)pekare;
	conwritereq->io_Length=size;
	SendIO(conwritereq);
	while(antal) {
		signals=Wait(conwritesig|conreadsig|windsig);
		if(signals & conwritesig) {
			antal--;
			dummymsg=(APTR)GetMsg(conwriteport);
		}
		if(signals & conreadsig) if((tecken=congettkn(&coninput)) == 3) {
				AbortIO(conwritereq);
				aborted=TRUE;
			}
			else if(tecken && buftkn<50) {
				buffer[buftkn++]=tecken;
				buffer[buftkn]=0;
			}
		if(signals & windsig) {
			mymess=(struct IntuiMessage *)GetMsg(NiKwind->UserPort);
			ReplyMsg(mymess);
			cleanup(OK,"");
		}
	}
	return(aborted);
}

int puttekn(char *pekare,int size) {
	struct IntuiMessage *mymess;
	APTR dummymsg;	
	int antal=2;
	int aborted=FALSE;
	ULONG signals,conwritesig = 1L << conwriteport->mp_SigBit,
		conreadsig = 1L << conreadport->mp_SigBit,windsig = 1L << NiKwind->UserPort->mp_SigBit,
		serwritesig = 1L << serwriteport->mp_SigBit,
		serreadsig = 1L << serreadport->mp_SigBit;
	char tecken;
	conwritereq->io_Command=CMD_WRITE;
	conwritereq->io_Data=(APTR)pekare;
	conwritereq->io_Length=size;
	SendIO(conwritereq);
	serwritereq->IOSer.io_Command=CMD_WRITE;
	serwritereq->IOSer.io_Data=(APTR)pekare;
	serwritereq->IOSer.io_Length=size;
	SendIO(serwritereq);
	while(antal) {
		signals=Wait(conwritesig|conreadsig|windsig|serwritesig|serreadsig);
		if(signals & conwritesig) {
			antal--;
			dummymsg=(APTR)GetMsg(conwriteport);
		}
		if(signals & serwritesig) {
			antal--;
			dummymsg=(APTR)GetMsg(serwriteport);
		}
		if(signals & conreadsig) if((tecken=congettkn(&coninput)) == 3) {
				AbortIO(serwritereq);
				WaitIO(serwritereq);
				AbortIO(conwritereq);
				WaitIO(conwritereq);
				aborted=TRUE;
				antal=0;
			}
			else if(tecken && buftkn<50) {
				buffer[buftkn++]=tecken;
				buffer[buftkn]=0;
			}
		if(signals & serreadsig) if((tecken=sergettkn(&serinput)) == 3) {
				AbortIO(serwritereq);
				WaitIO(serwritereq);
				AbortIO(conwritereq);
				WaitIO(conwritereq);
				aborted=TRUE;
				antal=0;
			}
			else if(tecken && buftkn<50) {
				buffer[buftkn++]=tecken;
				buffer[buftkn]=0;
			}
		if(signals & windsig) {
			mymess=(struct IntuiMessage *)GetMsg(NiKwind->UserPort);
			ReplyMsg(mymess);
			cleanup(OK,"");
		}
	}
	return(aborted);
}

void modemcmd(char *pekare,int size) {
	serwritereq->IOSer.io_Command=CMD_WRITE;
	serwritereq->IOSer.io_Data=(APTR)pekare;
	serwritereq->IOSer.io_Length=size;
	DoIO(serwritereq);
}

void cleanup(int kod,char *text)
{
	if(consoleyes) CloseConsole(conwritereq);
	if(conreadreq) DeleteExtIO(conreadreq);
	if(conreadport) DeletePort(conreadport);
	if(conwritereq) DeleteExtIO(conwritereq);
	if(conwriteport) DeletePort(conwriteport);
	if(NiKwind) CloseWindow(NiKwind);
	if(serialyes) CloseSerial(serwritereq);
	if(serreadreq) DeleteExtIO(serreadreq);
	if(serreadport) DeletePort(serreadport);
	if(serwritereq) DeleteExtIO(serwritereq);
	if(serwriteport) DeletePort(serwriteport);
	if(timeryes) CloseTimer(timerreq);
	if(timerreq) DeleteExtIO(timerreq);
	if(timerport) DeletePort(timerport);
	if(IntuitionBase) CloseLibrary(IntuitionBase);
	printf("%s",text);
	exit(kod);
}

int chat(void) {
	int going=TRUE,retur=TRUE;
	UBYTE tecken;
	while(going) {
		tecken=gettekn();
		if((tecken>31 && tecken <128) || (tecken>159 && tecken<=255)) {
			eka(tecken);
		} else if(tecken==13) {
			eka((char)13);
			eka((char)10);
		} else if(tecken==10) {
			serwritereq->IOSer.io_Command=SDCMD_QUERY;
			DoIO(serwritereq);
			if(serwritereq->io_Status & NOCARRIER) going=retur=FALSE;
			else {
				eka((char)10);
				eka((char)13);
			}
		} else if(tecken==8) {
			puttekn(backspace,3);
		} else if(tecken==2) {
			sendfile("ModAns:Login.txt");
		} else if(tecken==26) {
			going=FALSE;
		}
	}
	return(retur);
}	

void sendfile(char *filnamn) {
	FILE *fp;
	int going=TRUE,cnt=0;
	char buff[200];
	if(fp=fopen(filnamn,"r")) {
		while(going) {
			if(!(fgets(buff,199,fp))) going=FALSE;
			else if(puttekn(buff,-1)) going=FALSE;
			eka((char)13);
			cnt++;
			if(cnt>24) {
				puttekn("<RETURN>",-1);
				if(gettekn()==3) going=FALSE;
				for(cnt=0;cnt<8;cnt++) puttekn(backspace,3);
				cnt=0;
			}
		}
		fclose(fp);
	} else {
		sprintf(buff,"Can't open %s",filnamn);
		puttekn(buff,-1);
	}
}

void paus(ULONG tid) {
	timerreq->tr_node.io_Command=TR_ADDREQUEST;
	timerreq->tr_node.io_Message.mn_ReplyPort=timerport;
	timerreq->tr_time.tv_secs=tid;
	timerreq->tr_time.tv_micro=0;
	DoIO(timerreq);
}

void getconfig(void) {
	FILE *fp;
	char buffer[100],*pekare;
	int going=TRUE,cnt;
	if(!(fp=fopen("ModAns:ModAns.cfg","r"))) {
		printf("Could not open ModAns.cfg , using defaults\n");
		strcpy(init,"ATES0=0\r");
		strcpy(svara,"ATA\r");
		strcpy(hangup,"ATH\r");
		highbaud=2400;
		hst=FALSE;
		strcpy(password,"modans");
		strcpy(device,"serial.device");
		return;
	}
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"INITSTRING",10))) {
			strncpy(init,&buffer[11],31);
			cnt=0;
			while(init[cnt++]!='\n' && cnt<32);
			init[cnt-1]='\r';
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"ANSWERSTRING",12))) {
			strncpy(svara,&buffer[13],16);
			cnt=0;
			while(svara[cnt++]!='\n' && cnt<17);
			svara[cnt-1]='\r';
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"HANGUPSTRING",12))) {
			strncpy(hangup,&buffer[13],31);
			cnt=0;
			while(hangup[cnt++]!='\n' && cnt<32);
			hangup[cnt-1]='\r';
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"HIGHBAUDRATE",12))) {
			highbaud=atoi(&buffer[13]);
			switch(highbaud) {
				case 300 :
				case 600 :
				case 1200 :
				case 2400 :
				case 4800 :
				case 9600 :
				case 14400 :
				case 19200 :
					break;
				default:
					printf("Bad highbaudrate, using 2400\n");
					highbaud=2400;
					break;
			}
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"FIXED",5))) {
			if(buffer[4]=='y' || buffer[6]=='Y') hst=TRUE;
			else hst=FALSE;
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"PASSWORD",8))) {
			strncpy(password,&buffer[9],30);
			cnt=0;
			while(password[cnt++]!='\n' && cnt<31);
			password[cnt-1]='\0';
			going=FALSE;
		}
	}
	going=TRUE;
	while(going) {
		if(!(pekare=fgets(buffer,99,fp)))
			cleanup(ERROR,"Invalid config-file\n");
		if(!(strncmp(buffer,"DEVICE",6))) {
			strncpy(device,&buffer[7],30);
			cnt=0;
			while(device[cnt++]!='\n' && cnt<31);
			device[cnt-1]='\0';
			going=FALSE;
		}
	}
	fclose(fp);
}

int connection(void) {
	int rad=0,kol=0,going=TRUE,x,cnt;
	UBYTE tecken;
	for(x=0;x<50;x++) brev[x][0]=0;
	while(going) {
		sprintf(outbuffer,"%2d: %s",rad+1,brev[rad]);
		puttekn(outbuffer,-1);
		kol=strlen(brev[rad]);
		while(kol<75) {
			tecken=gettekn();
			if((tecken>31 && tecken <128) || (tecken>159 && tecken<=255)) {
				brev[rad][kol++]=tecken;
				brev[rad][kol]=0;
				eka(tecken);
			} else if(tecken==13) break;
			else if(tecken==10) {
				serwritereq->IOSer.io_Command=SDCMD_QUERY;
				DoIO(serwritereq);
				if(serwritereq->io_Status & NOCARRIER) return(FALSE);
				else break;
			} else if(tecken==8) {
				if(kol==0) break;
				else {
					brev[rad][--kol]=0;
					puttekn(backspace,-1);
				}
			} else if(tecken==26) {
				spara(rad);
				puttekn("\r\n\n",-1);
				return(TRUE);
			} else if(tecken==1) {
				spara(rad);
				puttekn("\r\nEntering chat mode\r\n\n",-1);
				return(chat());
			}
		}
		if(kol>=75) {
			if(rad==49) {
				kol--;
				brev[rad][kol]=0;
				puttekn("\a\r",-1);
			} else {
				cnt=kol+1;
				while(brev[rad][--cnt]!=32 && cnt>0);
				if(cnt>0) {
					brev[rad][cnt]=0;
					strcpy(brev[rad+1],&brev[rad][cnt+1]);
					for(x=cnt+1;x<75;x++) puttekn(backspace,-1);
				} else {
					brev[rad+1][0]=brev[rad][74];
					brev[rad][74]=0;
					brev[rad+1][1]=0;
				}
				rad++;
				puttekn("\r\n",-1);
			}
		} else if(kol==0 && tecken==8) {
			if(rad>=1) {
				rad--;
				eka('\r');
			} else puttekn("\a\r",-1);
		} else {
			if(brev[rad][0]=='!') {
				brev[rad][0]=0;
				if(brev[rad][1]=='d' || brev[rad][1]=='D') rad=raddelete(atoi(&brev[rad][3]),rad);
				else if(brev[rad][1]=='i' || brev[rad][1]=='I') rad=radinsert(atoi(&brev[rad][3]),rad);
				else if(brev[rad][1]=='r' || brev[rad][1]=='R') brevread(rad);
				else if(brev[rad][1]=='m' || brev[rad][1]=='M') textdump();
				else if(brev[rad][1]=='q' || brev[rad][1]=='Q') return(TRUE);
				else if(brev[rad][1]=='l' || brev[rad][1]=='L') {
					puttekn("\r\n\n",-1);
					sendfile("ModAns:Login.txt");
					puttekn("\r\n",-1);
				}
				puttekn("\r\n",-1);
			} else if(rad==49) puttekn("\a\r",-1);
			else {
				rad++;
				puttekn("\r\n",-1);
			}
		}
	}
}

void spara(int rader) {
	FILE *fp;
	int cnt=0,going=TRUE,test;
	char namnbuf[50];
	long tid;
	while(going) {
		sprintf(namnbuf,"ModAns:Message%d",cnt);
		if((test=access(namnbuf,0))==-1) going=FALSE;
		cnt++;
	}
	if(!(fp=fopen(namnbuf,"w"))) {
		puttekn("Couldn't save message",-1);
		return;
	}
	for(cnt=0;cnt<rader+1;cnt++) {
		if(fputs(brev[cnt],fp)) {
			puttekn("Error while saving message",-1);
			break;
		}
		if(fputc('\n',fp)==EOF) {
			puttekn("Error while saving message",-1);
			break;
		}
	}
	time(&tid);
	fprintf(fp,"\n\nSaved file %s",ctime(&tid));
	fclose(fp);
}

int raddelete(int rad,int maxrad) {
	int x;
	if(rad<=0 || rad>maxrad) return(maxrad);
	for(x=rad-1;x<maxrad;x++) strcpy(brev[x],brev[x+1]);
	return(maxrad-1);
}

void brevread(int maxrad) {
	int x,cnt=0;
	puttekn("\r\n\n",-1);
	for(x=0;x<maxrad;x++) {
		sprintf(outbuffer,"%2d: %s\r\n",x+1,brev[x]);
		if(puttekn(outbuffer,-1)) break;
		cnt++;
		if(cnt>24) {
			puttekn("<RETURN>",-1);
			if(gettekn()==3) break;
			for(cnt=0;cnt<8;cnt++) puttekn(backspace,3);
			cnt=0;
		}
	}
}

int radinsert(int rad,int maxrad) {
	int x,kol=0;
	UBYTE tecken;
	if(rad<=0 || rad>maxrad) return(maxrad);
	if(maxrad==49) {
		eka('\a');
		return(maxrad);
	}
	rad--;
	for(x=maxrad;x>=rad;x--) strcpy(brev[x+1],brev[x]);
	sprintf(outbuffer,"\r\n%2d: ",rad+1);
	puttekn(outbuffer,-1);
	for(;;) {
		tecken=gettekn();
		if((tecken>31 && tecken <128) || (tecken>159 && tecken<=255)) {
			if(kol<75) {
				brev[rad][kol++]=tecken;
				brev[rad][kol]=0;
				eka(tecken);
			} else eka('\a');
		} else if(tecken==13) break;
		else if(tecken==10) {
			serwritereq->IOSer.io_Command=SDCMD_QUERY;
			DoIO(serwritereq);
			if(serwritereq->io_Status & NOCARRIER) return(FALSE);
			else break;
		} else if(tecken==8) {
			if(kol==0) eka('\a');
			else {
				brev[rad][--kol]=0;
				puttekn(backspace,-1);
			}
		} 
	}
	return(maxrad+1);
}

void textdump(void) {
	struct FileInfoBlock mininfo;
	int error,cnt;
	char filnamn[100],psw[31];
	puttekn("\r\n\nPassword: ",-1);
	getpsw(psw);
	if(strcmp(psw,password)) {
		puttekn("\r\nWrong password\r\n",-1);
		return;
	}
	if(error=dfind(&mininfo,"ModAns:Message#?",0)) {
		if(errno==2) puttekn("\r\n\nNo messagefile\r\n",-1);
		else puttekn("\r\n\nError while reading directory\r\n",-1);
		return;
	}
	sprintf(outbuffer,"\r\n\n***** File: %s *****\r\n\n",mininfo.fib_FileName);
	puttekn(outbuffer,-1);
	sprintf(filnamn,"ModAns:%s",mininfo.fib_FileName);
	sendfile(filnamn);
	while(!(error=dnext(&mininfo))) {
		puttekn("<RETURN>",-1);
		if(gettekn()==3) break;
		for(cnt=0;cnt<8;cnt++) puttekn(backspace,3);
		sprintf(outbuffer,"\r\n\n***** File: %s *****\r\n\n",mininfo.fib_FileName);
		puttekn(outbuffer,-1);
		sprintf(filnamn,"ModAns:%s",mininfo.fib_FileName);
		sendfile(filnamn);
	}
	if(errno==-1) {
		puttekn("-----Error while reading directory-----",-1);
	}
}

void getpsw(char *inmat) {
	int cnt=0;
	UBYTE tillftkn;
	while((tillftkn=gettekn())!=13 && cnt<30) {
		if((tillftkn>31 && tillftkn<128) || (tillftkn>159 && tillftkn<=255)) {
			inmat[cnt++]=tillftkn;
			eka('*');
		} else if(tillftkn==8) {
			if(cnt) {
				cnt--;
				puttekn(backspace,-1);
			}
		}
	}
	inmat[cnt]=0;
}

void main() {
	int error,going=TRUE,bufcnt=0;
	UBYTE temp,buf[50];
	if(!(IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0)))
		cleanup(ERROR,"Couldn't open intuition.library\n");
	getconfig();
	if(!(conwriteport=(struct MsgPort *)CreatePort("NiKconwrite",0)))
		cleanup(ERROR,"Couldn't create messageport\n");
	if(!(conwritereq=(struct IOStdReq *)CreateExtIO(conwriteport,(LONG)sizeof(struct IOStdReq))))
		cleanup(ERROR,"Couldn't create IO-message\n");
	if(!(conreadport=(struct MsgPort *)CreatePort("NiKconread",0)))
		cleanup(ERROR,"Couldn't create messageport\n");
	if(!(conreadreq=(struct IOStdReq *)CreateExtIO(conreadport,(LONG)sizeof(struct IOStdReq))))
		cleanup(ERROR,"Couldn't create IO-message\n");
	if(!(NiKwind=(struct Window *)OpenWindow(&NiKnewwind)))
		cleanup(ERROR,"Couldn't open window\n");
	if(error=OpenConsole(conwritereq,conreadreq,NiKwind))
		cleanup(ERROR,"Couldn't open console.device\n");
	else consoleyes=TRUE;
	if(!(serwriteport=(struct MsgPort *)CreatePort("NiKserwrite",0)))
		cleanup(ERROR,"Couldn't create messageport\n");
	if(!(serwritereq=(struct IOExtSer *)CreateExtIO(serwriteport,(LONG)sizeof(struct IOExtSer))))
		cleanup(ERROR,"Couldn't create IO-message\n");
	if(!(serreadport=(struct MsgPort *)CreatePort("NiKserread",0)))
		cleanup(ERROR,"Couldn't create messageport\n");
	if(!(serreadreq=(struct IOExtSer *)CreateExtIO(serreadport,(LONG)sizeof(struct IOExtSer))))
		cleanup(ERROR,"Couldn't create IO-message\n");
	if(error=OpenSerial(serwritereq,serreadreq))
		cleanup(ERROR,"Couldn't open user defined device\n");
	else serialyes=TRUE;
	if(!(timerport=(struct MsgPort *)CreatePort("NiKTimer",0)))
		cleanup(ERROR,"Couldn't create messageport\n");
	if(!(timerreq=(struct timerequest *)CreateExtIO(timerport,(LONG)sizeof(struct timerequest))))
		cleanup(ERROR,"Couldn't create IO-message\n");
	if(error=OpenTimer(timerreq)) cleanup(ERROR,"Couldn't open timer.device\n");
	else timeryes=TRUE;
	
	conreqtkn(&coninput);
	serreqtkn(&serinput);
	paus(1);
	puttekn(init,-1);
	while((temp=gettekn())!=10) coneka(temp);
	coneka((char)10);
	while((temp=gettekn())!=10) coneka(temp);
	coneka((char)10);
	conputtekn("Ready\n",-1);
	while(going) {
		buf[8]=0;
		bufcnt=0;
		while((temp=gettekn())!=10) {
			coneka(temp);
			buf[bufcnt++]=temp;
		}
		coneka((char)10);
		if(!(strncmp(buf,"RING",4))) {
			modemcmd(svara,-1);
			bufcnt=0;
			while((temp=gettekn())!=10);
			while((temp=gettekn())!=10) {
				coneka(temp);
				buf[bufcnt++]=temp;
			}
			coneka((char)10);
			if(!(strncmp(buf,"CONNECT",7))) {
				if(!hst) {
					AbortIO(serreadreq);
					WaitIO(serreadreq);
					if(!(strncmp(&buf[8],"2400",4))) serwritereq->io_Baud=2400;
					else if(!(strncmp(&buf[8],"1200",4))) serwritereq->io_Baud=1200;
					else if(!(strncmp(&buf[8],"600",3))) serwritereq->io_Baud=600;
					else if(!(strncmp(&buf[8],"300",3))) serwritereq->io_Baud=300;
					else if(!(strncmp(&buf[8],"4800",4))) serwritereq->io_Baud=4800;
					else if(!(strncmp(&buf[8],"9600",4))) serwritereq->io_Baud=9600;
					else if(!(strncmp(&buf[8],"14400",5))) serwritereq->io_Baud=14400;
					else serwritereq->io_Baud=300;
					serwritereq->IOSer.io_Command=SDCMD_SETPARAMS;
					DoIO(serwritereq);
					serreqtkn(&serinput);
				}
				sprintf(outbuffer,"Connection at %d bps\n",serwritereq->io_Baud);
				conputtekn(outbuffer,-1);
				sendfile("ModAns:Login.txt");
				if(connection()) {
					sendfile("Modans:Logout.txt");
					paus(2);
					eka('+');
					eka('+');
					eka('+');
					while((temp=gettekn())!=10) coneka(temp);
					coneka((char)10);
					while((temp=gettekn())!=10) coneka(temp);
					coneka((char)10);
					puttekn(hangup,-1);
					while((temp=gettekn())!=10) coneka(temp);
					coneka((char)10);
					while((temp=gettekn())!=10) coneka(temp);
					coneka((char)10);
				} else {
					conputtekn("Carrier dropped\n",-1);
				}
				if(!hst) {
					AbortIO(serreadreq);
					WaitIO(serreadreq);
					serwritereq->io_Baud=highbaud;
					serwritereq->IOSer.io_Command=SDCMD_SETPARAMS;
					DoIO(serwritereq);
					serreqtkn(&serinput);
				}
				paus(1);
				puttekn(init,-1);
				while((temp=gettekn())!=10) coneka(temp);
				coneka((char)10);
				while((temp=gettekn())!=10) coneka(temp);
				coneka((char)10);
				conputtekn("Ready\n",-1);
			}
		}
	}
}
