/*
 * Please credit gardian not for this startup module!
 * 
 * REMEBER: if you use someones work C R E D I T  HIM!!
 *
 */

#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 <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>

#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void) {return(0);} /* Disable Lattice CTRL-C handling */
int chkabort(void) {return(0);}
#endif

/* Function prototypes: */
int   CheckMessage(void);
int   PortStart(void);
void  TakeOffEh(int code);
void  ShutDown(void);

void  UserRoutine(int nodenumber);
void  UserCloseRoutine(void);

void  GetNumNodes(char *string);
void  GetString(char text[], int len);
void  PutString(char text[], int lf);
void  GetMenuArgs(char *string);

int   GetBaudRate(void);
int   GetNumDirs(void);

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;
struct DosLibrary *DOSBase = NULL;
ULONG usersig, portsig, signals;
STRPTR doorport[30]; /* Portname for AEDoorPort(n) */
int EXIT_FLAG=0; /* This is the global shutdown flag */
char instring[256];

void main(int argc, char *argv[])
 {
   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);
	}

        if((DOSBase =(struct DosLibrary *)OpenLibrary("dos.library",0))==NULL)
         TakeOffEh(10);

	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! */

        UserRoutine(atoi(argv[1]));

	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 = CreateMsgPort())
	{
		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((UBYTE *)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(DOSBase != NULL) CloseLibrary((struct Library *)DOSBase);
	if(XIM_Msg) FreeMem(XIM_Msg, sizeof(struct XIM));
	if(DoorReplyPort) DeleteMsgPort(DoorReplyPort);
	exit(code);
 }

/*****************************************************************************\
 This is the start of the general routines that you will probably want to use.
 Only two other functions are provided in addition to the ShutDown() funciton,
 for the purpose of examples:

 To use the other XIM commands available, look up the Msg->Command/Data fields
 from the doordocs file, set them up for the XIM_Msg struct, and then
 CheckMessage() it.  The contents of XIM_Msg->String will be copied into the
 global instring[] for you when the command returns, and CheckMessage() will
 return the contents of XIM_Msg->Data.  (Note that 'XIM_Msg' is simply called
 'Msg' in the doordocs file.

\*****************************************************************************/

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!
	*/

        UserCloseRoutine();
	TakeOffEh(0);
 }

void GetString(char *text, int len)
 {
	XIM_Msg->Command=0;
	XIM_Msg->Data=len;
        strcpy(XIM_Msg->String,"");
	CheckMessage();
        strcpy(text,instring);
 }

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

 }

int  GetBaudRate(void)
 {
   int baudrate = 0;
        XIM_Msg->Command=505;
        CheckMessage();
        baudrate=atoi(instring);
     return(baudrate);

 }

void GetNumNodes(char *string)
 {
        XIM_Msg->Command=123;
        CheckMessage();
        strcpy(string,XIM_Msg->String);
 }

void GetMenuArgs(char *string)
 {
        XIM_Msg->Command=131;
        CheckMessage();
        strcpy(string,XIM_Msg->String);
 }

int GetNumDirs()
 {
        char *location;
        char  buf[5];           /* A little x-tra space doesn't hurt */
        int   numdirs = 0;
        LONG fh = NULL;

        XIM_Msg->Command=127;
        XIM_Msg->Data=1;                /* Get location */
        CheckMessage();

        strcpy(location,XIM_Msg->string);
        strcat(location,"NDIRS");
  
        if(!(fh = Open(location,MODE_OLDFILE))
          return(0);
        
        Read((BPTR)fh,(BYTE *)buf,2);
        numdirs = atoi(buf);

        Close((BPTR)fh);
        return(numdirs);
 }

