

/*

   EasyTransfer. By Kamran Karimi.
   Compiled with Borlald C++ 3.1:  "C:\> bcc -ms <file name>"

   Transfers files from a IBM PC or compatible to an Amiga and vice versa,
   using a 3 wire serial link. This is the PC file. Another program
   should run on the Amiga.

*/

#ifdef __cplusplus
#undef __cplusplus
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <dir.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <bios.h>
#include <sys/stat.h>

#ifndef min
#define min(a,b) (a) <= (b) ? (a) : (b)
#endif

#ifdef NTRANS
struct FileTranslate
{
 char Aname[32];
 char Dname[14];
 struct FileTranslate *next,*prev;
};
struct FileTranslate FirstTranslate = { NULL,NULL,NULL,NULL };
struct FileTranslate *TransMark,*PrevFT; /* prev added entry */

FILE *TFile = NULL; /* translation file */
long Suffix; /* suffix for uniquing of names */

char *TransFile = "ETFile";
char *CheckSign = "This Is How We Do It!";
#endif

#define TRUE 1
#define FALSE 0

#define OK   1
#define FAIL 0

#define SERTESTLEN 255

#define NO_ERROR        0
#define ERROR_NoSynch   6
#define ERROR_Break     7
#define ERROR_SRFExists 10
#define ERROR_SendRFile 15
#define ERROR_Timeout   13
#define ERROR_RecFile   14
#define ERROR_SetSer    17
#define ERROR_NoSpeed   18
#define ERROR_Direc     19
#define ERROR_MKDIR     25
#define ERROR_CHDIR     24
#define ERROR_RMDIR     26
#define ERROR_FDelete   27
#define ERROR_NOMEM     32
#define ERROR_CheckSum  45

#define ERROR    0
#define QUIT    49
#define DIR     50
#define CD      51
#define RECEIVE 52
#define SEND    53
#define MKDIR   54
#define RMDIR   55
#define DELETE  56

#define MAXBIOSSPEED  6
#define MAXHARDSPEED 10
unsigned int BiosSpeed[MAXBIOSSPEED] =
			     { 0X40, 0X60, 0X80, 0XA0, 0XC0, 0XE0 };
unsigned int HardSpeed[MAXHARDSPEED] =
		{ 0X180, 0XC0, 0X60, 0X30, 0X18, 0XC, 0X6, 0X3, 0X2, 0X1 };
unsigned int ServerWait[MAXHARDSPEED] =
  { 30, 60, 120, 240, 480, 960, 1920, 3480, 5760, 11520 };

long CurrSpeed;
long Test = FALSE;
long DelayTime = 3;
long CheckSumTry = 0;

#define COM1 0
#define COM2 1

#define BIOS 0
#define HARD 1

int CurrPort = COM2;
int PortAddr[] = { 0X3F8, 0X2F8 };
int Method = -1;
int verb = FALSE;

#define SERSET     0
#define SERSEND    1
#define SERRECEIVE 2
#define SERSTATUS  3

#define TX  0
#define RX  0
#define IER 1
#define IIR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6

#define DLLSB 0
#define DLMSB 1

#define RCVRDY  0X01
#define OVRERR  0X02
#define PRTYERR 0X04
#define FRMERR  0X08
#define BRKINT  0X10
#define XMTRDY  0X40

#define DTR 1
#define RTS 2

#define TIMER 0X1C

#define ABORT 0

#define PACKET_SIZE 255
unsigned char Buffer[PACKET_SIZE],Temp[2 * PACKET_SIZE];
unsigned char CMDLen;

volatile long TimerCounter;
void interrupt (*OldHandler)(void);

struct text_info ti;   

union
{
 unsigned long Len;
 char Char[4];
} FileLen;

size_t FileBuffSize = 32000;

#ifdef NTRANS
long IsIllegal(char *Aname,char *Dname)
{
 char *dot,*dot2,dosname[14],Atemp[32],StrSuff[10];
 long dlen,SuffLen;

 ltoa(Suffix,StrSuff,10);
 SuffLen = 8 - strlen(StrSuff);
 strcpy(Atemp,Aname);
 SuffLen++;
 dot = strchr(Atemp,'.');
 dot2 = dot;
 while(dot)
 {
  dot2 = strchr(dot + 1,'.');
  if(!dot2) break;
  *dot = '_';
  dot = dot2;
 }
 /* dot has the last possible extension */
 strncpy(dosname,Atemp,8);
 if(strlen(Atemp) >= 8) dosname[8] = NULL;
 dlen = strlen(dosname);
 if(dot)
 {
  strncat(dosname,dot,4);
  if(strlen(dot) >= 4)  dosname[dlen + 4] = NULL;
 }
 if(strcmp(Aname,dosname))
 {
  strncpy(dosname,Atemp,SuffLen);
  if(strlen(Atemp) >= SuffLen) dosname[SuffLen] = NULL;
  dlen = strlen(dosname);
  strcat(dosname,StrSuff);
  if(dot)
  {
   strncat(dosname,dot,4);
   if(strlen(dot) >= 4) dosname[dlen + 4] = NULL;
  }
  strcpy(Dname,dosname);
  return TRUE;
 }
 else strcpy(Dname,Aname);
 return FALSE;
}

long AddName(char *Aname, char *Dname)
{
 struct FileTranslate *ft;

 if(!(ft = (struct FileTranslate *) 
 malloc(sizeof(struct FileTranslate))))
  return FAIL;
 ft->next = NULL;
 strcpy(ft->Aname,Aname);
 strcpy(ft->Dname,Dname);
 PrevFT->next = ft;
 ft->prev = PrevFT;
 PrevFT = ft;
 return OK;
}

char *GetAmigaName(char *Dname)
{
 struct FileTranslate *ft;

 ft = FirstTranslate.next;
 while(ft)
 {
  if(!stricmp(ft->Dname,Dname))
   { printf(" GetAmi  going with '%s'\n",ft->Aname); return ft->Aname; }
  ft = ft->next;
 }
 return Dname;
}

char *GetDosName(char *Aname)
{
 struct FileTranslate *ft;

 printf("getdosname with: '%s'\n",Aname);
 ft = FirstTranslate.next;
 while(ft)
 {
  if(!stricmp(ft->Aname,Aname)) return ft->Dname;
  ft = ft->next;
 }
 return Aname;
}

void OpenTranslateFile(void)
{
 char StrSuffix[10],Sign[80];
 char Aname[32];
 char Dname[14];

 PrevFT = &FirstTranslate;
 FirstTranslate.prev = NULL;
 FirstTranslate.next = NULL;
 TFile = fopen(TransFile,"r");
 if(!TFile) return;
 printf("trans file opened\n");
 if(!fgets(Sign,strlen(CheckSign) + 2,TFile)) { fclose(TFile); return; }
 Sign[strlen(Sign) - 1] = NULL;
 printf("checksum don!\n");

 if(stricmp(Sign,CheckSign)) { fclose(TFile); return; }
  printf("checksum matched! '%s'\n",Sign);
 if(!fgets(StrSuffix,10,TFile)) { fclose(TFile); return; }
 StrSuffix[strlen(StrSuffix) - 1] = NULL;
 Suffix = atol(StrSuffix);
 printf("suffix = %d   '%s'\n",Suffix,StrSuffix);
 if(Suffix <= 0) { fclose(TFile); return; }
 while(!feof(TFile))
 {
  if(!fgets(Dname,14,TFile)) break;
  Dname[strlen(Dname) - 1] = NULL;
  if(!fgets(Aname,34,TFile)) break;
  Aname[strlen(Aname) - 1] = NULL;
  printf("aname = '%s'  dname = '%s'\n",Aname,Dname);
  if(!AddName(Aname,Dname)) { fclose(TFile); return; }
 }
 TransMark = PrevFT->next; /* new entries added here */
 fclose(TFile);
 printf("trans don!\n");
 TFile = NULL;
}


void PrepareTrans(void)
{
 struct FileTranslate *ftemp,*ftemp2;

 printf("prep !\n");
 ftemp = FirstTranslate.next;
 while(ftemp)
 {
  ftemp2 = ftemp->next;
  free(ftemp);
  ftemp = ftemp2;
 }
 if(TFile) fclose(TFile);
 OpenTranslateFile();
}
#endif /* NTRANS */

int Handler(int errval,int ax,int bp,int si)
{
 if((errval > ax) && (bp > si)) ;
 hardretn(2);
 return 2;
}


void FillScreen(void)
{
 int count;
 
 clrscr();
 for(count = 1; count <= 25; count++)
 {
  gotoxy(1,count);
  printf(
"IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM IBM");
 }
}

void Wheel(void)
{
 static int prevx = 1,prevy = 1,dir,pos = 0;
 static char Amiga[8] = "AMIGA! ";
 int color = 0,x,y;

 gotoxy(prevx,prevy); putch(Amiga[(prevx - 1) % 7]);
 x = prevx;
 y = prevy;
 dir = (rand() + dir) % 80;
 color = (rand() + color) % 8;
 textcolor(color);
 switch(dir)
 {
  case 0:
  case 1: x++;
	  break;
  case 3:
  case 4: x--;
	  break;
  case 6:
  case 7: y++;
	  break;
  case 9:
  case 10: y--;
	   break;
  case 12:
  case 13: x++;y++;
	   break;
  case 15:
  case 16: x++;y--;
	   break;
  case 18:
  case 19: x--;y++;
	   break;
  case 21:
  case 22: x--;y--;
	   break;
  case 23: x = x + 7; y = y + 3; break;
  case 24: x = x - 7; y = y - 3; break;
  case 25: x = x + 7; y = y - 3; break;
  case 26: x = x - 7; y = y + 3; break;
  default:break;
 }

 if(x > 79) x = 1;
 if(y > 25) y = 1;
 if(x <= 0) x = 79;
 if(y <= 0) y = 25;

 prevx = x;
 prevy = y;
 gotoxy(prevx,prevy);

 pos = (++pos % 4);
 switch(pos)
 {
 case 0: printf("-");
    break;
 case 1: printf("\\");
    break;
 case 2: printf("|");
    break;
 case 3: printf("/");
    break;
 }
 delay(45);
}

void interrupt Timer()
{
 TimerCounter++;
 OldHandler();
}

void OpenTimer(void)
{
 OldHandler = getvect(TIMER);
 setvect(TIMER,Timer);
}

void CloseTimer(void)
{
 setvect(TIMER,OldHandler);
}

int c_break(void)
{
 textmode(ti.currmode);
 textattr(ti.attribute);
 CloseTimer();
 _setcursortype(_NORMALCURSOR);
 clrscr();  
 printf("\nEasyTransfer: User Break Encountered... Quitting\n");     
 return ABORT;
}

void ClrSer(void)
{
 if(Method == BIOS)
 {
  while(!(bioscom(SERSTATUS,0,CurrPort) & (XMTRDY << 8)));
  if(bioscom(SERSTATUS,0,CurrPort) & (RCVRDY << 8))
   bioscom(SERRECEIVE,0,CurrPort);
 }
 else
 {
  while(!(inportb(PortAddr[CurrPort] + LSR) & XMTRDY));
  if(inportb(PortAddr[CurrPort] + LSR) & RCVRDY)
   inportb(PortAddr[CurrPort] + RX);
 }
}

void SetSer(int Speed)
{
 char Setting = 0X03;    /* xxx 00 0 11 */
 if(Method == BIOS)
 {
  Setting |= BiosSpeed[Speed];
  bioscom(SERSET,Setting,CurrPort);
 }
 else
 {
  outportb(PortAddr[CurrPort] + IER, 0);
  outportb(PortAddr[CurrPort] + LCR, 0x80);
  outportb(PortAddr[CurrPort] + DLLSB, HardSpeed[Speed] & 0XFF);
  outportb(PortAddr[CurrPort] + DLMSB, HardSpeed[Speed] >> 8);
  outportb(PortAddr[CurrPort] + LCR, Setting);
 }
 ClrSer();
}

void ActualSendPacket(unsigned char *ToSend, int CharCount)
{
 int count;

 for(count = 0; count < CharCount; count++)
 {
  if(Method == BIOS)
  {
   bioscom(SERSEND,ToSend[count],CurrPort);
   while(!(bioscom(SERSTATUS,0,CurrPort) & (XMTRDY << 8)));
  }
  else
  {
   outportb(PortAddr[CurrPort] + TX,ToSend[count]);
   while(!(inportb(PortAddr[CurrPort] + LSR) & XMTRDY));
  }
 }
}

int RecNotReady(void)
{
 if(Method == HARD)
  return !(inportb(PortAddr[CurrPort] + LSR) & RCVRDY);
 else
  return !(bioscom(SERSTATUS,0,CurrPort) & (RCVRDY << 8));
}

long ActualReceivePacket(unsigned char *chr,unsigned int RecCount)
{
 long count;
 long threshold = DelayTime * 18.2 + RecCount * 18.2 / ServerWait[CurrSpeed];

 TimerCounter = 0;
 for(count = 0; count < RecCount; count++)
 {
  while(RecNotReady())
  {
   if(TimerCounter > threshold)
   {
    if(Test)
    {
     if(verb) printf("ReceivePacket(): Waiting For Workstation\n");
     TimerCounter = 0;
    }
    else
    {
     if(verb) printf("ReceivePacket(): Workstation Not Responding\n");
     return ERROR_Timeout;
    }
   }
  }
  if(Method == BIOS)
   chr[count] = bioscom(SERRECEIVE,0,CurrPort);
  else
   chr[count] = inportb(PortAddr[CurrPort] + RX);
 }
 return NO_ERROR;
}

void SendPacket(unsigned char *ToSend, unsigned int CharCount)
{
 unsigned char LocalBuff[PACKET_SIZE + 2];
 short count;
 short NumTry = 1;
 unsigned char temp;
 union Check
 {
  unsigned short CheckWord;
  unsigned char CheckByte[2];
 } CheckSum;

 if(CharCount > 1)
 {
  for(count = 0; count < CharCount; count++)
   LocalBuff[count] = ToSend[count];
  if(NumTry <= CheckSumTry) NumTry = CheckSumTry + 1;
  CheckSum.CheckWord = 0;
  for(count = 0; count < CharCount; count++)
   CheckSum.CheckWord += (unsigned short) ToSend[count];
  LocalBuff[CharCount] = CheckSum.CheckByte[1];
  LocalBuff[CharCount + 1] = CheckSum.CheckByte[0];
  while(NumTry > 0)
  {
   ActualSendPacket(LocalBuff,CharCount + 2);
   ActualReceivePacket(&temp,1);
   if(temp == 'Y')
   {
    ActualSendPacket(&temp,1);
    return;
   }
   else NumTry--;
  }
 }
 else ActualSendPacket(ToSend,CharCount);
}

long ReceivePacket(unsigned char *chr, unsigned int RecCount)
{
 unsigned char LocalBuff[PACKET_SIZE + 2];
 short count;
 long Error;
 short NumTry = 1;
 unsigned char temp;
 union Check
 {
  unsigned short CheckWord;
  unsigned char CheckByte[2];
 } CheckSum;

 if(RecCount > 1)
 {
  if(NumTry <= CheckSumTry) NumTry = CheckSumTry + 1;
  while(NumTry > 0)
  {
   Error = ActualReceivePacket(LocalBuff,RecCount + 2);
   if(Error) return Error;
   CheckSum.CheckWord = 0;
   for(count = 0; count < RecCount; count++)
   {
    CheckSum.CheckWord += (unsigned short) LocalBuff[count];
    chr[count] = LocalBuff[count];
   }
   if( (LocalBuff[RecCount] != CheckSum.CheckByte[1]) ||
       (LocalBuff[RecCount + 1] != CheckSum.CheckByte[0]) )
   {
    NumTry--;
    temp = 'N';
    ActualSendPacket(&temp,1);
   }
   else
   {
    temp = 'Y';
    ActualSendPacket(&temp,1);
    return ActualReceivePacket(&temp,1);
   }
  }
  return ERROR_CheckSum;
 }
 else return ActualReceivePacket(chr,RecCount);
}

void EstablishConnection(void)
{
 char chr;
 int Synched = FALSE;

 while(!Synched)
 {
  while(RecNotReady())
  {
   if(!verb) Wheel();
   else kbhit();
  }
  if(Method == BIOS)
   chr = bioscom(SERRECEIVE,0,CurrPort);
  else
   chr = inportb(PortAddr[CurrPort] + RX);
  if(chr == 'L')
  {
   SendPacket("!",1);
   if(verb) printf("EstablishConnection(): Link Availability Checked\n");
  }
  else if(chr != '?')
  { if(verb) printf("EstablishConnection(): Synchronization Lost\n"); }
  else Synched = TRUE;
 }
}                               

char ReceiveCommand(void)
{
 long Error;

 SendPacket("!",1);
 Error = ReceivePacket(&CMDLen,1);
 if(Error) return Error;
 SendPacket("!",1);
 Error = ReceivePacket(Buffer,CMDLen);
 if(Error) return ERROR;
 return Buffer[0];
}

long GetSynch(void)
{
 long Error;
 unsigned char Buff;

 Error = ReceivePacket(&Buff,1);
 if(Error) return Error;
 if(Buff != '?') return ERROR_NoSynch;
 else return NO_ERROR;
}

long SendFileToAmiga(char *Name);

long SendDirToAmiga(char *Name)
{
 long Error;
 int done;
 int Attrib = FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH;
 struct ffblk ffblk;
 unsigned char temp;

 if(verb) printf("SendDirToAmiga(): Dir Name = '%s'\n",Name);
 if(chdir(Name))
 {
  if(verb) printf("SendDirToAmiga(): Chdir Failed\n");
  temp = 150 + ERROR_CHDIR;
  SendPacket(&temp,1);
  return ERROR_Direc;
 }
#ifdef NTRANS
 PrepareTrans();
#endif
 SendPacket("D",1);
 Error = GetSynch();
 if(Error) { chdir(".."); return Error; }
 Buffer[0] = strlen(Name);
 SendPacket(Buffer,1);
 Error = GetSynch();
 if(Error) { chdir(".."); return Error; }
 SendPacket(Name,strlen(Name));
 Error = GetSynch();
 if(Error) { chdir(".."); return Error; }
 done = findfirst("*.*",&ffblk,Attrib);
 while(!done)
 {
  if(verb) printf("SendDirToAmiga(): Dir Entry = '%s'\n",ffblk.ff_name);
  if(strcmp(ffblk.ff_name,".") && strcmp(ffblk.ff_name,".."))
  {
   Error = SendFileToAmiga(ffblk.ff_name);
   if(Error) { chdir(".."); return Error; }
  }
  done = findnext(&ffblk);
 }
 SendPacket("E",1);
 Error = GetSynch();
 if(Error) { chdir(".."); return Error; } 
 chdir("..");
 if(verb) printf("SendDirToAmiga(): Sent Dir Successfully\n");
 SendPacket("!",1);
 return NO_ERROR;
}


long SendFileToAmiga(char *Name)
{
  unsigned char temp;
 int Attrib = FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH;
 struct ffblk ffblk;
 unsigned char SizeToSend;
 char Buff,SizeBuffer[4];
 FILE *File;
 int count;
 long Error,FileLength;
 char *PCName;

 if(!findfirst(Name,&ffblk,Attrib))
 {
  SendPacket("!",1);
  Error = GetSynch();
  if(Error) return Error;
 }
 else
 {
  temp = 150 + ERROR_RecFile;
  SendPacket(&temp,1);
  return ERROR_RecFile;
 }
 if(ffblk.ff_attrib & FA_DIREC) return SendDirToAmiga(Name);
 else
 {
  if(verb) printf("SendFileToAmiga(): Sendig File: '%s'\n",Name);
  SendPacket("F",1);
  Error = GetSynch();
  if(Error) return Error;
#ifdef NTRANS
  PCName = GetDosName(Name);
#else
  PCName = Name;
#endif
  File = fopen(PCName,"rb");

  if(File == NULL)
  {
   if(verb) printf("SendFileToAmiga(): Can Not Open File To Send: '%s'\n",Name);
   temp = 150 + ERROR_RecFile;
   SendPacket(&temp,1);
   return ERROR_RecFile;
  }
  setvbuf(File, NULL, _IOFBF, FileBuffSize);
  FileLength = filelength(fileno(File));
  FileLen.Len = FileLength;
  for(count = 3; count >= 0; count--)
   SizeBuffer[3 - count] = FileLen.Char[count];
  SendPacket(SizeBuffer,4);
  if(verb) printf("SendFileToAmiga(): File Length =  %ld\n",FileLen.Len);
  Error = GetSynch();
  if(Error) { fclose(File); return Error; }
  Buff = strlen(Name);
  SendPacket(&Buff,1);
  Error = GetSynch();
  if(Error) { fclose(File); return Error; }
  SendPacket(Name,strlen(Name));
  Error = GetSynch();
  if(Error) { fclose(File); return Error; }
  SendPacket("!",1);
  while(FileLength > 0)
  {
   Error = ReceivePacket(&SizeToSend,1);
   if(Error) { fclose(File); return Error; }
   if(fread(Temp,1,SizeToSend,File) != SizeToSend)
   {
    if(verb) printf("SendFileToAmiga(): Read Failed!\n");
    fclose(File);
    return ERROR_SendRFile;
   }
   SendPacket(Temp,SizeToSend);
   FileLength -= SizeToSend;
  }
  fclose(File);
 }
 if(verb) printf("SendFileToAmiga(): Sent File Successfully\n");
 return NO_ERROR;
}

long SendToAmiga(void)
{
 Buffer[CMDLen] = NULL;
 if(verb) printf("SendToAmiga(): Name = '%s'\n",&Buffer[1]);
 return SendFileToAmiga(&Buffer[1]);
}

long HandleM_R_Dir(long CMD)
{
 unsigned char temp;

 Buffer[CMDLen] = NULL;
 if(CMD == MKDIR)
 {
  if(!mkdir(&Buffer[1])) SendPacket("!",1);
  else { temp = 150 + ERROR_MKDIR; SendPacket(&temp,1); return ERROR_MKDIR; }
 }
 else if(CMD == RMDIR)
 {
  if(!rmdir(&Buffer[1])) SendPacket("!",1);
  else { temp = 150 + ERROR_RMDIR; SendPacket(&temp,1); return ERROR_RMDIR; }
 }
 return NO_ERROR;
}

long ReceiveFileFromAmiga(void);

long ReceiveDirFromAmiga(void)
{
 unsigned char temp;
 long Error;
 unsigned char len,Type;

 SendPacket("!",1);
 Error = ReceivePacket(&len,1);
 if(Error) return Error;
 SendPacket("!",1);
 Error = ReceivePacket(Buffer,len);
 if(Error) return Error;
 Buffer[len] = NULL;
 if(verb) printf("ReceiveDirFromAmiga(): Receiving Dir: '%s'\n",Buffer);
 if(mkdir(Buffer))
  { temp = 150 + ERROR_MKDIR; SendPacket(&temp,1); return ERROR_MKDIR; }
 if(chdir(Buffer))
  {temp = 150 + ERROR_CHDIR; SendPacket(&temp,1); return ERROR_CHDIR; }
#ifdef NTRANS
 PrepareTrans();
#endif
 if(verb) printf("ReceiveDirFromAmiga(): Mkdir And Chdir Successful\n");
 SendPacket("!",1);
 do
 {
  Error = ReceivePacket(&Type,1);
  if(Error) { chdir(".."); return Error; }
  if(Type == 'E') break;
  if(Type != '?') { chdir(".."); return ERROR_Direc; }
  Error = ReceiveFileFromAmiga();
  if(Error) { chdir(".."); return Error; }
 }while(1);
 SendPacket("!",1);
 chdir("..");
 if(verb) printf("ReceiveDirFromAmiga(): Directory Received Successfully\n");
 return NO_ERROR;
}


long ReceiveFileFromAmiga(void)
{
 long Error;
 FILE *file;
 int count,index;
 unsigned char len,Mode,Protect;
 char TBuff[2 * PACKET_SIZE];
 unsigned char temp;
 char *PCName;
#ifdef NTRANS
 char TempDName[34];
#endif

 SendPacket("!",1);
 Error = ReceivePacket(&Mode,1);
 if(Error) return Error;
 if(Mode == 'D') return ReceiveDirFromAmiga();
 else
 {
  SendPacket("!",1);
  Error = ReceivePacket(&Protect,1);
  if(Error) return Error;
  SendPacket("!",1);  
  Error = ReceivePacket(&len,1);
  if(Error) return Error;
  SendPacket("!",1);
  Error = ReceivePacket(Buffer,len);
  if(Error) return Error;
  Buffer[len] = NULL;
  if(verb) printf("ReceiveFileFromAmiga(): Receiving File '%s'\n",Buffer);
#ifdef NTRANS
  PCName = GetDosName(Buffer);
  IsIllegal(Buffer,TempDName);
  printf("Name changed to: '%s'\n",TempDName);
#else
  PCName = Buffer;
#endif
  if(Protect == 'P')
  {
   file = fopen(PCName,"r");
   if(file)
   {
    if(verb) printf("ReceiveFileFromAmiga(): Receiving File Already Exits\n");
    temp = 150 + ERROR_SRFExists;
    SendPacket(&temp,1);
    fclose(file);
    return ERROR_RecFile;
   }
  }  
  file = fopen(PCName,"wb");
  if(file == NULL)
  {
   if(verb) printf("ReceiveFileFromAmiga(): Can Not Create Receiving File\n");
   temp = 150 + ERROR_SendRFile;
   SendPacket(&temp,1);
   return ERROR_RecFile;
  }
  setvbuf(file, NULL, _IOFBF, FileBuffSize);
  SendPacket("!",1);
  Error = ReceivePacket(&FileLen.Char[0],4);
  if(Error) { fclose(file); return Error; }
  if(verb) printf("ReceiveFileFromAmiga(): File Length = %ld\n",FileLen.Len);
  while(FileLen.Len > 0)
  {
   len = min(FileLen.Len,PACKET_SIZE);
   FileLen.Len -= len;
   SendPacket(&len,1);
   Error = ReceivePacket(Temp,len);
   if(Error) { fclose(file); return Error; }
   index = 0;
   for(count = 0; count< len; count++)
   {
    if((Mode == 'T') && (Temp[count] == 10)) 
     { TBuff[index++] = 10; TBuff[index++] = 13; }
    else TBuff[index++] = Temp[count];
   }
   if(fwrite(TBuff,1,index,file) != index)
   {
    if(verb) printf("ReceiveFileFromAmiga(): Write Failed!\n");
    fclose(file);
    return ERROR_RecFile;
   }
  }
  fclose(file);
 }
 SendPacket("!",1); 
 if(verb) printf("ReceiveFileFromAmiga(): Received File Successfully\n");
 return NO_ERROR;
}

long HandleQuit(void)
{
 return NO_ERROR;
}

long DeleteServerFile(void)
{
 unsigned char temp;

 Buffer[CMDLen] = NULL;
 if(!unlink(&Buffer[1])) { SendPacket("!",1); return NO_ERROR; }
 else 
 { temp = 150 + ERROR_FDelete; SendPacket(&temp,1); return ERROR_FDelete; }
}

long ChangeServerDir(void)
{
 int pos;
 unsigned char temp, result = 150 + ERROR_CHDIR; /* assume failer */
 char buffer[PACKET_SIZE];
 long Error;

 Buffer[CMDLen] = NULL;
 pos = 1;
 if(Buffer[2] == ':')
 {
  setdisk(toupper(Buffer[1]) - 'A');
  if(Buffer[3] == NULL) strcat(Buffer,"\\");
 }
 if( (Buffer[strlen(Buffer) - 1] == '\\') &&
     (Buffer[strlen(Buffer) - 2] != ':'))
 Buffer[strlen(Buffer) - 1] = NULL;
 if(!chdir(&Buffer[pos]))
  result = '!';
#ifdef NTRANS
 PrepareTrans();
#endif
 SendPacket(&result,1);
 Error = GetSynch();
 if(Error) return Error;
 getcwd(buffer, PACKET_SIZE);
 temp = strlen(buffer);
 SendPacket(&temp,1);
 Error = GetSynch();
 if(Error) return Error;
 SendPacket(buffer,temp);
 Error = GetSynch();
 if(Error) return Error;
 SendPacket("!",1);
 if(result != '!') return ERROR_CHDIR;
 else return NO_ERROR;
}

long SendDirEntriesToAmiga(void)
{
 long Error;
 struct ffblk ffblk;
 int Attrib = FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH;
 unsigned int done;
 unsigned char len;
 unsigned int day,month,year,sec,minute,hour;
 char *AmName;

 done = findfirst("*.*",&ffblk,Attrib);
 while (!done)
 {
  if( !(ffblk.ff_attrib & FA_DIREC) ||
      (strcmp(".",ffblk.ff_name) && strcmp("..",ffblk.ff_name)) )
  {
   sec = (ffblk.ff_ftime & 0X001F) * 2;
   minute = (ffblk.ff_ftime & 0X07E0) >> 5;
   hour = (ffblk.ff_ftime & 0XF800) >> 11;

   day = ffblk.ff_fdate & 0X001F;
   month = (ffblk.ff_fdate & 0X01E0) >> 5;
   year = ((ffblk.ff_fdate & 0XFE00) >> 9) + 1980;
   if(!(ffblk.ff_attrib & FA_DIREC))
   {
#ifdef NTRANS
    AmName = GetAmigaName(ffblk.ff_name);
#else
    AmName = ffblk.ff_name;
#endif
    sprintf(Buffer," %8lu %-12.12s ",ffblk.ff_fsize, AmName);
    if(ffblk.ff_attrib & FA_HIDDEN) strcat(Buffer,"H");
    else strcat(Buffer,"-");
    if(ffblk.ff_attrib & FA_SYSTEM) strcat(Buffer,"S");
    else strcat(Buffer,"-");
    if(ffblk.ff_attrib & FA_RDONLY) strcat(Buffer,"R");
    else strcat(Buffer,"-");
    if(ffblk.ff_attrib & FA_ARCH) strcat(Buffer,"A");
    else strcat(Buffer,"-");
   }
   else sprintf(Buffer,"D         %-12.12s     ",ffblk.ff_name);
   sprintf(Temp,"  %02u/%02u/%u  %02u:%02u:%02u ",
					    day,month,year,hour,minute,sec);
   strcat(Buffer,Temp);
   len = strlen(Buffer);
   SendPacket(&len,1);
   Error = GetSynch();
   if(Error)
   {
    if(verb) printf("SendDirEntriesToAmiga(): Workstation Is Not Responding\n");
    return Error;
   }
   SendPacket(Buffer,len);
   Error = GetSynch();
   if(Error)
   {
    if(verb) printf("SendDirEntriesToAmiga(): Workstation Is Not Responding\n");
    return Error;
   }
  }
  done = findnext(&ffblk);
 }
 Buffer[0] = 0;
 SendPacket(Buffer,1);
 Error = GetSynch();
 if(Error)
 {
  if(verb) printf("SendDirEntriesToAmiga(): Workstation Is Not Responding\n");
  return Error;
 }
 SendPacket("!",1);
 return NO_ERROR;
}

long SetSerial(void)
{
 long Error,Rec_OK = FALSE,done = FALSE;
 unsigned char RecCount,count;

 do
 {
  if(verb) printf("SetSerial(): Trying Speed No. %d\n",CurrSpeed);
  Test = TRUE;
  SetSer(CurrSpeed);
  Error = GetSynch();
  if(Error) return Error;
  SendPacket("!",1);
  Test = FALSE;
  Error = ReceivePacket(Temp,SERTESTLEN);
  if(Error) RecCount = 1;
  else RecCount = SERTESTLEN;
  for(count = 0; count < SERTESTLEN; count++)
   if(Temp[count] != count) break;
  if(count == SERTESTLEN) Rec_OK = TRUE;
  else Rec_OK = FALSE;
  if((RecCount == SERTESTLEN) && (Rec_OK))
  {
   SendPacket("!",1);
   Error = GetSynch();
   if(Error) return Error;
   for(count = 0; count < SERTESTLEN; count++)
    Buffer[count] = SERTESTLEN - count - 1;
   SendPacket(Buffer,SERTESTLEN);
   Error = ReceivePacket(Temp,1);
   if(Error) return ERROR_SetSer;
   if(Temp[0] != '!') CurrSpeed--;
   else done = TRUE;
  }
  else
  {
   SendPacket("1",1);
   Error = GetSynch();
   if(Error) return Error;
   else CurrSpeed--;
  }
  ClrSer();
  SendPacket("!",1);
 }while((!done) && (CurrSpeed >= 0));
 if(CurrSpeed < 0) return ERROR_NoSpeed;
 if(verb) printf("SetSerial(): Speed Set At %d\n",CurrSpeed);
 return NO_ERROR;
}

int GetSpeedMethodDelay(void)
{
 unsigned char chr;
 int MinSpeed = 0,tempMethod;
 long tempCurrSpeed;

 Method = BIOS;

 SetSer(MinSpeed);
 while(RecNotReady())
 {
  if(!verb) Wheel();
  else kbhit();
 }
 chr = bioscom(SERRECEIVE,0,CurrPort);
 switch(chr)
 {
  case 'H': SendPacket("!",1); tempMethod = HARD; break;
  case 'B': SendPacket("!",1); tempMethod = BIOS; break;
  default: SendPacket("1",1); tempMethod = -1; break;
 }
 if(tempMethod < -1) return -1;
 while(RecNotReady())
 {
  if(!verb) Wheel();
  else kbhit();
 }
 chr = bioscom(SERRECEIVE,0,CurrPort);
 SendPacket("!",1);
 if(chr <= MAXHARDSPEED) tempCurrSpeed = chr;
 else return -1;
 Method = tempMethod;
 CurrSpeed = tempCurrSpeed;
 while(RecNotReady())
 {
  if(!verb) Wheel();
  else kbhit();
 }
 chr = bioscom(SERRECEIVE,0,CurrPort);
 SendPacket("!",1);
 DelayTime = chr;
 if(DelayTime < 1) return -1;
 if(DelayTime > 99) return -1;
 while(RecNotReady())
 {
  if(!verb) Wheel();
  else kbhit();
 }
 chr = bioscom(SERRECEIVE,0,CurrPort);
 SendPacket("!",1);
 CheckSumTry = chr;
 if(CheckSumTry < 0) return -1;
 if(CheckSumTry > 99) return -1;
 return 0;
}


void main(int argc, char **argv)
{
 long Error;
 unsigned char Command,NoQuit = TRUE;

 if((argv[1][0] == '?') ||
    ((argv[1][0] == '/') && (argv[1][1] == '?')))
 {
  printf("\nEasyTransfer V2.0 Beta. By Kamran Karimi\n\n");
  printf("Connects an Amiga and an IBM PC or compatible via a 3 wire null\n");
  printf("modem serial cable\n");
  printf("Another program should also run on the Amiga\n\n");
  printf("Options:\n");
  printf("        -v or -V   This will make the program verbose\n\n");
  printf("        -1 or -2   Use serial port 1 or 2. Default is port 2\n\n");
  exit(0);
 }

 while(--argc > 0)
 {
  if(argv[argc][0] == '-')
  {
   if((argv[argc][1] == 'v') || (argv[argc][1] == 'V')) verb = TRUE;
   if(argv[argc][1] == '1') CurrPort = COM1;
   if(argv[argc][1] == '2') CurrPort = COM2;
  }
 }
 harderr(Handler);
 gettextinfo(&ti);
 textmode(C80);
 clrscr();
 OpenTimer();
 setcbrk(1);
 ctrlbrk(c_break);
 _setcursortype(_NOCURSOR);
 printf("EasyTransfer V2.0 Beta (Invoke With ? Or /? For Information)\n");
 printf("By Kamran Karimi\n");
 printf("\nUsing Serial Port %d\n",CurrPort + 1);
 printf("Press Control-Break To Quit\n\n");
 printf("Press Return Key To Begin:");
 fgetchar();

 if(!verb) FillScreen();
 do
 {
  ClrSer();
  if(verb) printf("main(): Getting Communication Parameters...");
  if(GetSpeedMethodDelay() == -1)
  {
   if(verb) printf(" Failed\n",Method);
   continue;
  }
  if(verb) printf(" Done\n");
  ClrSer();
  Error = SetSerial();
  if(Error)
  {
   if(verb) printf("main(): Error = %d\n",Error);
  }
 }while(Error);

 while(NoQuit)
 {
  EstablishConnection();
  if(verb) printf("main(): Connection Established\n");
  Command = ReceiveCommand();
  if(verb) printf("main(): Command Received: ");
  switch (Command)
  {
   case ERROR: if(verb) printf("Error In Command...\n"); 
	       Error = TRUE;
	       break; /* error */

   case DIR: if(verb) printf("DIR...\n");
	     Error = SendDirEntriesToAmiga();
	     break;

   case RECEIVE: if(verb) printf("SendToAmiga...\n");
		 Error = SendToAmiga(); 
		 break;

   case SEND: if(verb) printf("ReceiveFromAmiga...\n");
	      Error = ReceiveFileFromAmiga();
	      break;

   case MKDIR: if(verb) printf("MakeDir...\n");
	       Error = HandleM_R_Dir(MKDIR);
	       break;

   case RMDIR: if(verb) printf("RemoveDir...\n");
	       Error = HandleM_R_Dir(RMDIR);
	       break;

   case DELETE: if(verb) printf("DeleteFile...\n");
		Error = DeleteServerFile();
		break;

   case CD: if(verb) printf("ChangeDir...\n");
	    Error = ChangeServerDir();
	    break;

   case QUIT: if(verb) printf("Quiting...\n");
	      Error = HandleQuit();
	      NoQuit = FALSE;
	      break;

   default : if(verb) printf("Unknown Command...\n"); 
	     Error = TRUE;    
	     break;
  }
  if(Error) 
  {
   ClrSer();
   if(verb) printf("main(): Failed\n\n");    
  }
  else if(verb) printf("main(): Done\n\n");    
 }
 CloseTimer();
 textmode(ti.currmode);
 textattr(ti.attribute);
 _setcursortype(_NORMALCURSOR);
 clrscr();
 printf("EasyTransfer: Quitted\n");
}
