/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by MXM
 *
 *	Name .....: Null-Handler.c
 *	Created ..: Saturday 31-Mar-90 13:47
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	04-Apr-91       Olsen           Ported to SAS/C 5.10a
 *	15-Apr-90       Olsen           Ported to Aztec 'C' 5.0
 *	07-Jan-90       Olsen           Created this file!
 *
 *	Skeleton    handler    code   by   Phillip   Lindsay   (C)   1986
 *	Commodore-Amiga,  Inc.  You may freely distribute this source and
 *	use  it for Amiga Development, as long as the Copyright notice is
 *	left intact.
 *
 ****************************************************************************
 *
 *	This  is  an  example how a 'real' NIL:  handler could look like.
 *	It  is very loosely based on the 'my-handler' source code written
 *	by Phillip Lindsay.
 *
 * $Revision Header ********************************************************/

	/* Main includes. */

#include <libraries/filehandler.h>
#include <libraries/dosextens.h>
#include <exec/execbase.h>

#include <pragmas/exec.h>

	/* Prototypes for this module. */

LONG __saveds			HandlerEntry(VOID);
VOID __regargs			ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc);
struct DosPacket * __regargs	WaitPacket(struct Process *HandlerProc);

	/* Global pointer to ExecBase. */

struct ExecBase		*SysBase;

	/* HandlerEntry():
	 *
	 *	The entry point for this handler.
	 */

LONG __saveds
HandlerEntry()
{
	struct Process *HandlerProc;

		/* Set the ExecBase pointer. */

	SysBase = *(struct ExecBase **)4;

		/* Get a pointer to the process structure of the
		 * handler.
		 */

	HandlerProc = (struct Process *)SysBase -> ThisTask;

		/* If not called from CLI (you shouldn't do that)
		 * we'll start up as a DOS-handler.
		 */

	if(!HandlerProc -> pr_CLI)
	{
		struct DosPacket	*NullPacket;
		struct DeviceNode	*NullNode;

			/* Wait for startup packet (we aren't a
			 * BCPL module).
			 */

		NullPacket = WaitPacket(HandlerProc);

			/* Get pointer to handler device node. */

		NullNode = (struct DeviceNode *)BADDR(NullPacket -> dp_Arg3);

			/* Install handler task ID -> we're running. */

		NullNode -> dn_Task = &HandlerProc -> pr_MsgPort;

			/* Return the startup packet to DOS. */

		ReturnPacket(NullPacket,DOSTRUE,NullPacket -> dp_Res2,HandlerProc);

			/* Run forever - or until somebody lets us die. */

		for(;;)
		{
				/* Wait for a packet. */

			NullPacket = WaitPacket(HandlerProc);

				/* Check the type. */

			switch(NullPacket -> dp_Type)
			{
				case ACTION_FINDINPUT:
				case ACTION_FINDOUTPUT:
				case ACTION_FINDUPDATE:	
				case ACTION_END:	ReturnPacket(NullPacket,DOSTRUE,0,HandlerProc);
							break;

				case ACTION_WRITE:	ReturnPacket(NullPacket,NullPacket -> dp_Arg3,0,HandlerProc);
							break;

				case ACTION_READ:	ReturnPacket(NullPacket,0,0,HandlerProc);
							break;

				case ACTION_DIE:	ReturnPacket(NullPacket,DOSTRUE,0,HandlerProc);
							goto FallOff;

				default:		ReturnPacket(NullPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN,HandlerProc);
							break;
			}
		}

			/* Okay, we're done, zero the task ID field
			 * and fall through.
			 */
	
FallOff:	NullNode -> dn_Task = NULL;
	}
}

	/* ReturnPacket():
	 *
	 *	Returns a packet to DOS.
	 */

VOID __regargs
ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc)
{
	struct MsgPort *ReplyPort;

		/* Remember origin port. */

	ReplyPort = Packet -> dp_Port;

		/* Fill in the result fields. */

	Packet -> dp_Res1 = Res1;
	Packet -> dp_Res2 = Res2;

		/* Install our task ID. */

	Packet -> dp_Port = &HandlerProc -> pr_MsgPort;

		/* Initialize the packet node head. */

	Packet -> dp_Link -> mn_Node . ln_Name	= (char *)Packet;
	Packet -> dp_Link -> mn_Node . ln_Succ	= NULL;
	Packet -> dp_Link -> mn_Node . ln_Pred	= NULL;

		/* Return the packet to the sender. */

	PutMsg(ReplyPort,Packet -> dp_Link);
}

	/* WaitPacket():
	 *
	 *	Wait for a DOS packet.
	 */

struct DosPacket * __regargs
WaitPacket(struct Process *HandlerProc)
{
	struct Message *DOSMsg;

		/* Wait at the port... */

	WaitPort(&HandlerProc -> pr_MsgPort);

		/* Get the packet. */

	DOSMsg = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort);

		/* Return a pointer to its head. */

	return((struct DosPacket *)DOSMsg -> mn_Node . ln_Name);
}
