
/*
 *  DCMD-HANDLER.C
 *
 *  DICE COMPILATION
 */

#include "defs.h"

void
_main()
{
    XMsgPort *port;
    MsgPort *privatePort;
    long fh;

    {
	Process *proc = FindTask(NULL);
	port = FindPort(proc->pr_Task.tc_Node.ln_Name);
    }
    if (port == NULL)       /*  fall through    */
	return;
    privatePort = CreatePort(NULL, 0);

    /*
     *	The RAM disk has the unique ability that when writing to a file
     *	with a shared lock (1005), another process can load the file at
     *	any time getting the most up to date information.
     */

    if ((fh = Open(port->FileName, 1005)) == NULL) {
	if (fh = Open(port->FileName, 1006)) {
	    Close(fh);
	    fh = Open(port->FileName, 1005);
	}
    }

    if (fh) {
	Seek(fh, 0L, 1);
	Write(fh, "HANDLER-RUNNING\n", 16);
    }

    /*
     *	set-up
     */

    {
	Process *proc = port->Proc;	/*  CLI process     */

	port->Port.mp_Flags = PA_SIGNAL;
	port->Port.mp_SigBit= SIGBREAKB_CTRL_E;
	port->Port.mp_SigTask = FindTask(NULL);
    }

    for (;;) {
	Message *msg = GetMsg(port);
	DosPacket *packet;

	if (msg == NULL) {
	    long mask = Wait((1 << port->Port.mp_SigBit) | SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D);
	    if (mask & SIGBREAKF_CTRL_F)
		break;
	    if (mask & SIGBREAKF_CTRL_D) {      /*  close-re-open   */
		if (fh)
		    Close(fh);
		if (fh = Open(port->FileName, 1005))
		    Seek(fh, 0L, 1);
		continue;
	    }
	    continue;
	}
	packet = (DosPacket *)msg->mn_Node.ln_Name;

	switch(packet->dp_Type) {
	case ACTION_WRITE:
	    if (fh)
		Write(fh, packet->dp_Arg2, packet->dp_Arg3);
	    break;
	case ACTION_READ:	/*  re-arrange return path  */
	    {
		MsgPort *replyPort = packet->dp_Port;	/*  return port */

		packet->dp_Port = privatePort;		/*  redirect	*/
		PutMsg(port->OldConsoleTask, msg);
		WaitPort(privatePort);
		GetMsg(privatePort);
		if (packet->dp_Res2 == 0 && packet->dp_Res1 > 0) {
		    if (fh)
			Write(fh, packet->dp_Arg2, packet->dp_Res1);
		}
		PutMsg(replyPort, packet->dp_Link);     /*  -> original */
		packet = NULL;
	    }
	    break;
	}
	if (packet)
	    PutMsg(port->OldConsoleTask, msg);
    }

    if (fh)
	Close(fh);

    /*
     *	Until receive SIGBREAKF_CTRL_F, then handshake/exit
     */

    port->Proc->pr_ConsoleTask = port->OldConsoleTask;
    {
	FileHandle *fh;
	CLI *cli = BTOC(port->Proc->pr_CLI);

	if ((fh = BTOC(cli->cli_CurrentOutput)) && fh->fh_Type == (MsgPort *)port)
	    fh->fh_Type = port->OldConsoleTask;
	if ((fh = BTOC(cli->cli_CurrentInput)) && fh->fh_Type == (MsgPort *)port)
	    fh->fh_Type = port->OldConsoleTask;
    }

    DeletePort(privatePort);
    Forbid();
    {
	Task *task = port->Port.mp_SigTask;
	port->Port.mp_SigTask = NULL;
	Signal(task, SIGBREAKF_CTRL_E);
    }
}

