/* */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

/**************** Function prototypes: ************************/
/*void ShowDir(int dir);
void AddFlag(char Filename[]);
void Credits(void);
void ListHelp(void);
void Quit(void);
void StripCR(char *str);
void SetDoorName(void);
void GetFiles(void);
void Adir(void);
void MyCd(void);
void MyType(void);
void WhereAmI(void);
*/
int CheckMessage(void);
int PortStart(void);
void TakeOffEh(int code);
void ShutDown(void);
//void PRINT(char text[], int lf);
int FilesinList=0;
int autodir=0;

struct XIM   /* This has been taken directly from JH_Message */
{            /* structure in the doordocs file.  */

  struct Message Msg;	/* msg structure */
  char String[200];	/* info buffer */
  int Data;		/* Read/Write & result indicator */
  int Command;		/* Command sent from door. */
  int NodeID;		/* reserved */
  int LineNum;		/* reserved */
  unsigned long signal;	/* reserved */
  struct Process *task;	/* see BB_GETTASK in doordocs */
  APTR Semi;		/* See MULTICOM in doordocs */
};

struct MsgPort *DoorControlPort, *DoorReplyPort;
struct XIM *XIM_Msg, *reply;
ULONG usersig, portsig, signals;
char doorport[30]; /* Portname for AEDoorPort(n) */
int EXIT_FLAG=0; /* This is the global shutdown flag */
char instring[256];
char cname[1256];
int x;
int y;
int limit;
char str[10][80];
char st[80];
FILE *fp;
char cmd[256];
char num[255];
char SourceDir[255]="CD0:";
char tempdir[255]="tmp:";
char tempfile[255];
char path[255];
char Path[255]; // i LOVE case sensitivity...
char ShowmeFile[255];
char usernumber[100];
long lock=NULL;
int CheckDevName(char *String);

static void PRINT(char text[], int lf)
{
	XIM_Msg->Command=4;
	XIM_Msg->Data=lf;
	strcpy(XIM_Msg->String,text);
	CheckMessage();
}

static void ShowDir(int dir)
{
  PRINT("",1);
  
  if(dir==0) sprintf(cname,"DIR >%s",ShowmeFile);
   else      sprintf(cname,"%s >%s",tempfile,ShowmeFile);
  Execute(cname,0,0);
  XIM_Msg->Command=8;
  strcpy(XIM_Msg->String,ShowmeFile);
  CheckMessage();
  DeleteFile(ShowmeFile);
}

static void AddFlag(char Filename[])
{
  PRINT("Adding File(s) to Download List",1);
  XIM_Msg->Command=13;
  strcpy(XIM_Msg->String,Filename);
  CheckMessage();
  FilesinList++;
}

static void Credits(void)
{
PRINT("34m.----------------------------------------------------------------------------.[0m",1);
PRINT("[34m| [36mCD-Shell/FTP Emulator for CD-ROMs[0m, a [32mXIM Door[0m by [35mSiGMA SEVEN![0m  Version 1.2 |[0m",1);
PRINT("[34m`----------------------------------------------------------------------------'[0m\r\n",1);

}

static void ListHelp(void)
{
PRINT("Available Commands are:\r\n",1);
PRINT("Dos Operations:\r\n",1);

PRINT("TYPE             Types out the given Filename. (Do NOT Type Binaries)",1);
PRINT("DIR              Does a DIR Command on the CURRENT Directory",1);
PRINT("LIST             Does a normal AmigaDOS LIST Command on the CURRENT Directory",1);
PRINT("CD               Changes to the Directory you`ve given behind the CD Command",1);
PRINT("AUTODIR          Turns on/off the Automatic DIR Command after a CD Command",1);
PRINT("                 has been used.\r\n",1);

PRINT("File specific Operations:\r\n",1);
PRINT("GET              GETs the Filenames and adds them to the Download Qeue",1);
PRINT("                 (Wildcards (*) are allowed, The Download will be started",1);
PRINT("                 right after the Files have been put in the Temporary Dir",1);
PRINT("MGET             Same as GET but also works with multiple Files",1);
PRINT("LHA V <filename> View the Contents of a LHA Archive, VERBOSE.",1);
PRINT("LHA V <filename> View the Contents of a LHA Archive, SHORT.",1);
PRINT("LHA P <archive> <file_in_Archive>",1);
PRINT("                 View a File IN an Archive.\r\n",1);
PRINT("Misc. Operations:\r\n",1);
PRINT("VERSION          Prints out the Version Number & Credits Texts",1);
PRINT("QUIT             Leaves this Program.",1);

}

static void Quit(void)
{
PRINT("\r\nThank you for using CD-Shell/FTP-Emulator Version 1.0\r\n",1);
    XIM_Msg->Command=136;	  // There was a Bug in the last /X i know
    strcpy(XIM_Msg->String,"");   // where it was executing the PRV_COMMAND
    CheckMessage();		  // Twice... because it set it to RETURNCOMMAND
	  			  // This small Thing fixes that. 
ShutDown();
}

static void StripCR(char *str)
{
  register i;
  i=strlen(str)-1;
  while(i>0)
  { if(*(str+i)==13) *(str+i)='\0'; else if(*(str+i)==10) *(str+i)='\0'; else return;
    i -=1;
  }

}
static void SetDoorName(void)
{
  XIM_Msg->Command=177;		
  strcpy(XIM_Msg->String,"CD-Shell V1.2");   
  CheckMessage();		
}

static void GetFiles(void)
 {
  strmid(XIM_Msg->String,cname,5,205);
  if(CheckDevName(cname)==1) 
   {
     PRINT("Sorry, No Files from other Devices are allowed to be downloaded",1);
     return;
   } // This should fix a really NASTY Bug, I`m sorry for those that may have
     //  had "Difficulties" with the older Version 1.0

  sprintf(tempfile,"[35mCopying [0m%s[35m to Temporary Directory..",cname);
  PRINT(tempfile,0);
  sprintf(tempfile,"copy %s %s",cname,tempdir);
  Execute(tempfile,0,0);
  strcpy(tempfile,cname);
  PRINT(".Ready",1);
  AddFlag(cname);
  if(FilesinList!=0)
   {
    PRINT("Starting the Download of the CD ROM Files now.",1);
    XIM_Msg->Command=508;
    strcpy(XIM_Msg->String,"D");
    CheckMessage();

    PRINT("Cleaning up the Temporary Directory, Hold..",0);
    if(chdir(tempdir)==0) //Change to Temporary Dir for Deletion
    {
     sprintf(cname,"Delete %s%s >NIL:",tempdir,tempfile);
     Execute(cname,0,0);
    }
    chdir(path); // Change back to the Previous Directory
    PRINT("Done.",1);
    SetDoorName();
   }
 }
static void Adir(void)
{ if(autodir==0) { autodir=1; PRINT("AutoDir is turned OFF",1); }
  else          { autodir=0; PRINT("AutoDir is turned ON",1); }
}

static void MyCd(void)
 {
  strmid(XIM_Msg->String,cname,4,80);
  if(CheckDevName(cname)==0)
  {
   if(chdir(cname)==0) 
    { if(!autodir) ShowDir(0); }
   else PRINT("\r\nError: Directory doesn`t exist!\r\n",1);
  } else PRINT("Sorry, Its not allowed to change to a different DEVICE!\r\n",1);
 }

static void MyType(void)
 {
  strmid(XIM_Msg->String,cname,6,200);
  XIM_Msg->Command=8;
  getcd(0,path);
  strcat(path,"/");
  strcat(path,cname);
  strcpy(XIM_Msg->String,path);
  if(access(XIM_Msg->String,0)==0) CheckMessage();
   else PRINT("\r\nError: File not found!\r\n",1);
 }

static void WhereAmI(void)
{
getcd(0,path);
sprintf(cname,"[0;1m%s[0m> ",path);
PRINT(cname,0);
}

int CheckDevName(char *String)
{
  if(strchr(cname,':')==0) return(0);
  else return(1);
}




void main(int argc, char *argv[])
{
int i;
int line_num;

	if(argc<2) /* AmiExpress will supply line_num on command line */
	{
		printf("Sorry, %s must be called from AmiExpress.\n",argv[0]);
		exit(0);
	}

	line_num=atoi(argv[1]);

	/* Don't know what Jon Radoff's problem was.. This works fine.. */
	sprintf((STRPTR)doorport,"AEDoorPort%d",line_num);

	if(PortStart()!=0) TakeOffEh(40); /* You must use this before you start! */
/**************************************************************************/
/*                      Place your own code in here..                     */
/**************************************************************************/


SetDoorName();
XIM_Msg->Command=104;
XIM_Msg->Data   = 1;
CheckMessage();	// Get the Users User Number.

sprintf(ShowmeFile,"T:SIGMA.%s",XIM_Msg->String); // Smart Name for a ReDirection File huh?
strcpy(usernumber,XIM_Msg->String);
strcpy(Path,argv[0]);
i=strlen(Path)-1;
while(Path[i]!='/' && Path[i]!=':') i--;// Get the Pathame of where the Door
Path[i+1]='\0';				// has been placed.
sprintf(cname,"%sLockme",Path);
if(access(cname,0)!=0) { fp=fopen(cname,"w"); fclose(fp); }
if(!(lock=Lock(cname,ACCESS_WRITE)))
  {
   PRINT("",1);
   PRINT("[32mSorry but the Door is in use at the Moment.[0m",1);
   PRINT("[32mPlease try again in a few minutes[0m",1);
   ShutDown();
  }

PRINT("",1);
Credits();
sprintf(cname,"%sCDSHELL.CFG",Path);	// Open the Config File.
if((fp=fopen(cname,"r"))==NULL) PRINT("No Configuration found, using default Values",1);
else 	{
	PRINT("Reading Configuration File",0);
	fgets(SourceDir, 80, fp);	// Read in the Source Dirs Path
        StripCR(SourceDir);
	fgets(tempdir, 80, fp);		// Read in the Temporary Dirs Path
        StripCR(tempdir);
	fgets(cname, 80, fp);		// Default AutoDir ?
	autodir=atoi(cname);
	fclose(fp);
	PRINT("...Done",1);
	}
//strcat(tempdir,usernumber); // Merge UserNumber & TempDir to create the REAL TempDir
//mkdir(tempdir);             // MAKE the REAL TempDir

PRINT("\r\nAvailable Commands can be viewed by entering [35m?[0m",1);

if(chdir(SourceDir)!=0)
 { sprintf(cname,"Source Dir (%s) not found. Exiting Door.\r\n",SourceDir);
   PRINT(cname,1); ShutDown();
 }

PRINT("\r\nViewing Directory: ",1);
ShowDir(0);
WhereAmI();

while((strnicmp(XIM_Msg->String,"",1)))	// This is just a DUMMY Routine.
						// to keep it looping. Lame huh?
{
XIM_Msg->Command=0;
XIM_Msg->Data=255;

strcpy(XIM_Msg->String,"");

CheckMessage();	// This Ones gets me what the User enters in the Shell

if(!(strnicmp(XIM_Msg->String,"CD..",3)))   { strcpy(XIM_Msg->String,"CD /"); MyCd(); } //To make sure those Dumb PC Users can use their CD Command
if(!(strnicmp(XIM_Msg->String,"CD ..",4)))  { strcpy(XIM_Msg->String,"CD /"); MyCd(); } //just the Way they are used to.
if(!(strnicmp(XIM_Msg->String,"CD ",2)))      MyCd();
if(!(strnicmp(XIM_Msg->String,"QUIT",3)))     Quit();
if(!(strnicmp(XIM_Msg->String,"AUTODIR",6)))  Adir();
if(!(strnicmp(XIM_Msg->String,"VERSION",6)))  Credits();
if(!(strnicmp(XIM_Msg->String,"LIST",3)))   { strcpy(tempfile,XIM_Msg->String); ShowDir(1); }
if(!(strnicmp(XIM_Msg->String,"LHA V ",5))) { strcpy(tempfile,XIM_Msg->String); ShowDir(1); }
if(!(strnicmp(XIM_Msg->String,"LHA L ",5))) { strcpy(tempfile,XIM_Msg->String); ShowDir(1); }
if(!(strnicmp(XIM_Msg->String,"LHA P ",5))) { strcpy(tempfile,XIM_Msg->String); ShowDir(1); }
if(!(strnicmp(XIM_Msg->String,"DIR",2)))    { strcpy(tempfile,XIM_Msg->String); ShowDir(1); }
if(!(strnicmp(XIM_Msg->String,"MGET ",3)))  { strmid(XIM_Msg->String,cname,5,205); strcpy(XIM_Msg->String,"GET "); strcat(XIM_Msg->String,cname); }
if(!(strnicmp(XIM_Msg->String,"GET ",3)))     GetFiles();
if(!(strnicmp(XIM_Msg->String,"TYPE ",4)))    MyType();
if(!(strnicmp(XIM_Msg->String,"?",1)))        ListHelp();
/*
if(!(strnicmp(XIM_Msg->String,"STATUS",5)))
 {
  sprintf(cname,"You have %d Files in your List to Download",FilesinList);
  PRINT(cname,1);
 }
*/
WhereAmI();

}
ShutDown(); /* NEVER quit with exit() as it will cause AmiExpress
                       to wait around forever on you. */

}

/**********************************************************************/
/* This function does all of the message passing, and signal checking */
/**********************************************************************/
int CheckMessage(void)
{
int ret=0;

	if(DoorControlPort)
	{
		Forbid();
		PutMsg(DoorControlPort, (struct Message *)XIM_Msg);
		Permit();

		signals = Wait(usersig|portsig);
		if(signals & portsig)
		{
			if(reply = (struct XIM *) GetMsg(DoorReplyPort))
			{
				strcpy(instring,XIM_Msg->String);
				if(XIM_Msg->Data == -1) EXIT_FLAG=1;
				ret=XIM_Msg->Data;
			}
		}
		if(signals & usersig) EXIT_FLAG=1; /* CTRL-C was received */
	}
	else
	{
		printf("Error! Can no longer locate doorport!!\n");
		EXIT_FLAG=1;
	}
	if(EXIT_FLAG) ShutDown();
	return(ret);
}

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

int PortStart(void)
{
int error=0;

	if(DoorReplyPort = CreatePort(0,0))
	{
		portsig = 1<<DoorReplyPort->mp_SigBit; /* setup signal bits */
		usersig = SIGBREAKF_CTRL_C;

		if(XIM_Msg = (struct XIM *) AllocMem(sizeof(struct XIM), MEMF_PUBLIC |MEMF_CLEAR))
		{
			/* Setup stuff for exec.. */
			XIM_Msg->Msg.mn_Node.ln_Type = NT_MESSAGE;
			XIM_Msg->Msg.mn_Length = sizeof(struct XIM);
			XIM_Msg->Msg.mn_ReplyPort = DoorReplyPort;

			XIM_Msg->Command = 1; /* Register Door with AmiExpress */

			Forbid();
			DoorControlPort = FindPort(doorport);
			Permit();

			if(DoorControlPort==NULL)
			{
				printf("Can't find doorport \"%s\"\n",doorport);
				error=3;
			}
			else CheckMessage();
		}
		else
		{
			printf("Can't allocate memory for XIM Message Structure!\n");
			error=2;
		}
	}
	else
	{
		printf("Can't setup reply port!\n");
		error=1;
	}

return(error);
}

void TakeOffEh(int code) /* Notify AmiExpress of shutdown, and then exit safely */
{
	XIM_Msg->Command=2;
	if(DoorControlPort) CheckMessage();

	if(XIM_Msg) FreeMem(XIM_Msg, sizeof(struct XIM));
	if(DoorReplyPort) DeletePort(DoorReplyPort);
	exit(code);
}


void ShutDown(void)
{
	/* This routine will be call automatically by CheckMessage if
           AmiExpress says to shut down, or if it receives a CTRL-C signal.
           This allows you to save any data before shutdown.

           IF YOU HAVE ANYTHING TO SAVE, DO IT HERE!!  THIS NEVER RETURNS!
	*/
        if(lock) UnLock(lock); /* ADDED to remove the Lock i put on before */
	TakeOffEh(0);
}
/***************************************************************************/
/*                            FUNCTIONS HERE:                              */
/***************************************************************************/

