/********************************************************************
 ** NETWORK FILESYSTEM - DOS HANDLER
 **
 ** (c) Spak, Darrell Tam, c9107253@ee.newcastle.edu.au (1994)
 ** phone (Australia) 049-829-710
 **                   +49-829-710
 ** (c) SST 1994
 **
 ** OPEN (ACTION_FINDINPUT | ACTION_FINDOUTPUT | ACTION_UPDATE)
 **
 ** Actions are sent to the network device
 **
 ** NOW supports shells on CON: type devices, 
 ** passes on the first "Open", consequent ones are simply ignored
 ** and returned with the same fh_Arg1. See interactive.s
 **
 ** TABS to 4
 ********************************************************************/

#include "/snd/everything.h"
#include "deadheads.h"
#include "root_protos.h"
#include "globs_protos.h"
#include "xtra_protos.h"
#include "interactive_protos.h"

#define OPEN_PKTMSG_SIZE sizeof(struct OpenPktMsg)

/** this is just a variation of the "doofus" format */
struct OpenPktMsg {
	struct	DoofusPktMsg	dpm;

	struct	NFSOpenFile			openreq;	/* request structure */
	struct	NFSOpenFileReturn	openret;	/* return structure */
	struct	FileArg1			*fa1;
};


/********************************************************************/
static long handle_openfile_net(struct OpenPktMsg *opm)
/********************************************************************/
{
struct DosPacket *dosmsg = opm->dpm.dp_original;
struct FileHandle *fh = BTOC(dosmsg->dp_Arg1);
struct FileArg1	*fa1 = opm->fa1;

{ unsigned char tt[100]; spf(tt, 100, "open: res1=%ld, res2=%ld",
		opm->openret.remote_res1, opm->openret.remote_res2); MyPrint(win1, tt); }

	dosmsg->dp_Res2 = opm->openret.remote_res2;
	if(opm->dpm.net.pm.smsg.result == PAR_OK &&
		(dosmsg->dp_Res1 = opm->openret.remote_res1) ) {

		fa1->remote.remote_ifh	= opm->openret.remote_ifh;
		fa1->remote.majic 		= opm->openret.remote_majic;

	/** IS THE FILE INTERACTIVE?? IF SO, GIVE IT ANOTHER PORT */
		if(*(long *)&fh->fh_Port = opm->openret.remote_ifh_Port) {
		struct InterPort *imp;
			if(imp = AllocRemember(&fa1->mem,
						INTER_MSGPORT_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
				imp->i.is_Code 			= handle_interactive_stuff;
				imp->i.is_Data 			= imp;
				imp->mp.mp_Node.ln_Type	= NT_MSGPORT;
				imp->mp.mp_Flags		= PA_SOFTINT;
				imp->mp.mp_SigTask		= (struct Task *)&imp->i;
				NewList(&imp->mp.mp_MsgList);
				imp->fa1 = fa1;
				imp->pass = localrepport;
				imp->opencount = 1;
				dosmsg->dp_Port = imp;			/* new port for every interactive */
			}
		}
		fh->fh_Type = dosmsg->dp_Port;			/* already contains "OurPort" */
		fh->fh_Arg1 = (long)fa1;
	}

/** ERROR ??? */
	else {
		REMOVE_FROM_LIST(fa1, first_fa1);		/* no longer open */
		FreeMem(fa1, FA1_SIZE);					/* gone */
		dosmsg->dp_Res1 = 0;
		if(opm->dpm.net.pm.smsg.result != PAR_OK) dosmsg->dp_Res2 = ERROR_NO_DISK;
	}
	return(AR_FLAG_RETURNDOSMSG | AR_FLAG_FREEDOOF);
}



/********************************************************************/
long action_openfile(struct DosPacket *dosmsg,
							struct MsgPort *dm_retport)
/********************************************************************/
{
unsigned char *fname = BTOC(dosmsg->dp_Arg3);	/* note, BCPL style string */
short	server;

{ unsigned char tt[60]; spf(tt,60,"fh=%lx, lock=%lx, task=%lx",
		dosmsg->dp_Arg1, dosmsg->dp_Arg2, dosmsg->dp_Port->mp_SigTask);
		MyPrint(win1, tt); }

/** IF THERE IS A LOCK */
	if(dosmsg->dp_Arg2) {
		dosmsg->dp_Res1 = 0; dosmsg->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
		return(AR_FLAG_RETURNDOSMSG);
	}
	else if(fname[0] == 1 && fname[1] == '*') {
		dosmsg->dp_Res1 = 0; dosmsg->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
		return(AR_FLAG_RETURNDOSMSG);
	}

/** CHECK OUT THE FILE NAME */
	MyPrintBCPL(win1,dosmsg->dp_Arg3);

	server = fname[6]-'0';
	if(fname[5] == ',' && server >=0 && server<=9 &&
								fname[0] > 7 && netservport[server]) {
	struct OpenPktMsg	*opm;
	struct FileArg1		*fa1;
	unsigned char		*send_name;
	short	send_name_len = fname[0] - 7+2;

		if(!(fa1 = AllocMem(FA1_SIZE, MEMF_PUBLIC)) ||
		   !(opm = AllocMem(OPEN_PKTMSG_SIZE + send_name_len, MEMF_PUBLIC)) ) {
			FreeMem(fa1, FA1_SIZE);
			dosmsg->dp_Res1 = 0; dosmsg->dp_Res2 = ERROR_NO_FREE_STORE;
			return(AR_FLAG_RETURNDOSMSG);
		}

		opm->fa1 = fa1;

		send_name		= (unsigned char *)&opm[1];
		send_name[0]	= fname[0] - 7;
		spf(&send_name[1], send_name_len-1, &fname[8]);

		opm->openreq.request 	= REQUEST_OPENFILE;
		opm->openreq.action 	= dosmsg->dp_Type;
		opm->openreq.internallock = NULL;				/* for the moment */

		ADD_HEAD(fa1, first_fa1);						/* add into the list */
		fa1->Type		= LK_REMOTE;
		fa1->fh 		= BTOC(dosmsg->dp_Arg1);		/* (don't really use it tho) */
		fa1->parent_lock = BTOC(dosmsg->dp_Arg2);		/* lock we're from */
		fa1->mem		= NULL;

		INIT_DOOFPKTMSG(&opm->dpm,
					handle_openfile_net,
					netrepport,
					fa1->fsys = netservport[server],
					dosmsg,
					dm_retport,
					OPEN_PKTMSG_SIZE+send_name_len,
					fa1->remote.machine = fname[7],
					fa1->remote.service = SERV_FILE,
					&opm->openreq, sizeof(struct NFSOpenFile),	/* request */
					send_name, send_name_len,					/* send-body */
					NULL, 0,									/* result-body */
					&opm->openret, sizeof(struct NFSOpenFileReturn));
																/* return codes */
	{ unsigned char tt[100]; spf(tt, 100, "port=%lx", opm->dpm.net.server); MyPrint(win1, tt); }

		PutMsg(opm->dpm.net.server, opm);
		return(0);
	}
	dosmsg->dp_Res1 = 0; dosmsg->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
	return(AR_FLAG_RETURNDOSMSG);
}
