/*
 *
 *	DISCLAIMER:
 *
 *	This program is provided as a service to the programmer
 *	community to demonstrate one or more features of the Amiga
 *	personal computer.  These code samples may be freely used
 *	for commercial or noncommercial purposes.
 * 
 * 	Commodore Electronics, Ltd ("Commodore") makes no
 *	warranties, either expressed or implied, with respect
 *	to the program described herein, its quality, performance,
 *	merchantability, or fitness for any particular purpose.
 *	This program is provided "as is" and the entire risk
 *	as to its quality and performance is with the user.
 *	Should the program prove defective following its
 *	purchase, the user (and not the creator of the program,
 *	Commodore, their distributors or their retailers)
 *	assumes the entire cost of all necessary damages.  In 
 *	no event will Commodore be liable for direct, indirect,
 *	incidental or consequential damages resulting from any
 *	defect in the program even if it has been advised of the 
 *	possibility of such damages.  Some laws do not allow
 *	the exclusion or limitation of implied warranties or
 *	liabilities for incidental or consequential damages,
 *	so the above limitation or exclusion may not apply.
 *
 */

/* system software version: V1.1               */

#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/libraries.h"
#include "exec/ports.h"
#include "exec/interrupts.h"
#include "exec/io.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"

#include "workbench/startup.h"

#define PRIORITY 0
#define STACKSIZE 5000

extern struct Message *GetMsg();
extern int LoadSeg();
extern struct MsgPort *CreateProc();

struct mymess { 
   struct Message sysmess;
   int outpointer;
   int errpointer; 
};

struct mymess pmsg;
struct WBStartup wbm;	

main()
{
	struct WBStartup *msg;		/* message that we send to the
					 * process to wake it up */
	struct Message *reply;
	struct Process *myprocess;

	struct mymess *parms;	/* message to contain my own parameters
				 * to pass on to spawned process, sample
				 * only.  Just to prove that we correctly
				 * create a process, we are giving it
				 * something other than nil: as its
				 * stdout and stderr... in fact, giving
				 * it OUR values so we can share the
				 * same output window.
				 */

	/* The WBStartup message could be dynamically allocated or statically
  	 * as it is done in this case.  Because of the static allocation,
	 * poor main() has to go to sleep forever after starting up
	 * the daughter process, waiting for a message to arrive at
	 * its message port before it can actually exit.
	 */

	/* because main() is itself started as a process, it automatically
	 * has a message port allocated for itself.  Located at
	 *  &((struct Process *)FindTask(0))->pr_MsgPort 
	 */

	int littleSeg;

	struct MsgPort *mainport;	/* pointer to main's msg port */
	struct MsgPort *littleProc;     /* pointer to daughter's msg port */

/* LOAD THE PROGRAM TO BE STARTED FROM MAIN ****************************** */

	littleSeg = LoadSeg("littleproc");
	if(littleSeg == 0) 
	{
		printf("\nFile not found");
		exit(999);
	}

/* CREATE A PROCESS FOR THIS OTHER PROGRAM ******************************* */

	littleProc = CreateProc("littleguy",PRIORITY, littleSeg, STACKSIZE);
	if( littleProc == 0 ) 
	{
		printf("\Couldn't create the process");
		UnLoadSeg(littleSeg);
		exit( 1000 );
	}

/* ********************************************************************** */
/* locate the message port that is allocated as part of the process
   that started main() in the first place */

	myprocess = (struct Process *)FindTask(0);

	mainport = &myprocess->pr_MsgPort;

/* ********************************************************************** */
/* THIS CODE BLOCK STARTS THE PROCESS RUNNING, AS THOUGH CALLED FROM WBENCH */

	/* this message block is a wakeup call to the process we created. */
	msg = &wbm;

	/* preset the necessary arguments for message passing */

	msg->sm_Message.mn_ReplyPort = mainport;
	msg->sm_Message.mn_Length = sizeof(struct WBStartup);

	/* passing no workbench arguments to this process; we are not WBench */

	msg->sm_ArgList = NULL;

	/* if the process is being opened without a ToolWindow (Workbench
	 * sets this up) as a parent, we should simply go on to do main() */

	msg->sm_ToolWindow = NULL;

	PutMsg(littleProc,msg);	/* send the startup message */

/* ************************************************************************ */
/* just a sample message, still using the same message and reply ports      */

	parms = &pmsg;
	parms->sysmess.mn_ReplyPort = mainport;
	parms->sysmess.mn_Length = sizeof(struct mymess);
	parms->outpointer = Output();
	parms->errpointer = Output();

	PutMsg(littleProc,parms);	/* send him our parameters */

	WaitPort(mainport);	/* wait for the reply from parameter pass. */
	reply = GetMsg(mainport); /* value should be "parms" if checked */	



	WaitPort(mainport);	/* wait for the return of the wbstartup
			  	 * message before main itself is allowed
				 * to exit.  */

	reply = GetMsg(mainport); /* value should be "msg" if checked */

	/* NOTE: there should be checking here to see if the message
	 * received at this port was the string, or the wakeup call.
	 * This sample code only assumes that the string is received
	 * and replied first, then the wakeup call message is returned
	 * as the little task is exiting.  
	 */

	UnLoadSeg(littleSeg);

	printf("\nSlave process exited, master unloaded its code/data");

}	/* end of main */

