/*
 *  FILE
 *	env-handler.c
 *
 *  VERSION
 *	V1.0
 *
 *  DESCRIPTION
 *	This program makes the env: environment variables compatible
 *	with the old MANX variables. (They said it couldn`t be done...)
 *
 *  AUTHOR
 *	Anders `ALi' Lindgren
 *	Malarblick 8
 *	S-161 51 Bromma
 *	Sweden
 *
 *  STATUS
 *	This program is in the Public Domain.
 *
 *  CODE HISTORY
 *	26-Sep-89   (07:50) Created the File.
 *	26-Sep-89   (10:30) File basically completed. :-)
 */

#include "env-handler.h"



/* Oh No, a global variable! */

struct ArpBase * ArpBase;

/*
 *  FUNCTION
 *	env_handler
 *
 *  DESCRIPTION
 *	This function initializes all.
 *
 *  NOTE
 *	Though this is the first function, I have not named it main().
 *	I can now see if there is any mistakes made at link time (ie. no
 *	startupcode shall be used.)
 */

static void __saveds
env_handler( void )
{
    register struct DosPacket	 * pkt; 	/* The actual packet	*/
    register struct MsgPort	 * port;	/* Process msg port	*/
	     struct Process	 * proc;	/* My process		*/
	     struct Message	 * msg; 	/* Messages from port	*/
	     struct DosList	 * node;	/* My devicenode	*/
	     char		   name[4];	/* Temporary name buffer */
	     int		   len;
	     char  		 * ident;	/* program identification */

	/*
	 * The following line simply embedds the text into the executable
	 * file, so the name of the project and the versionnumber
	 * can be seen.
	 */


    ident = 	"\0*** ENV2MANX Env-Handler V1.0, 1990-01-20,"
		"Written by Anders Lindgren ***";


    proc = (struct Process *)FindTask(NULL);

    WaitPort( port = & proc->pr_MsgPort );
    msg = GetMsg(port);
    pkt = (struct DosPacket *) msg->mn_Node.ln_Name;


    if ( ArpBase = (struct ArpBase *)OpenLibrary(ArpName, ArpVersion) ) {

	node = (struct DosList *) BTOC( pkt->dp_Arg3 );

	len = BtoCStr( & name[0] , node->dol_Name , 3);
	if ( (Strncmp(name, "env", 3) == 0) && (len == 3) ) {

		/* Inform AD that we are here by complement the dosnode */
	    node->dol_Task  = port;

	    pkt->dp_Res1    = DOS_TRUE;
	    pkt->dp_Res2    = 0;

	    ReplyPkt(pkt, port);

	    main_lupe(port, node);

	    node->dol_Task = NULL;
	}
	else {
			/* Started under other name than env: */
	    pkt->dp_Res1 = DOS_FALSE;
	    pkt->dp_Res2 = ERROR_BAD_STREAM_NAME;
	    ReplyPkt(pkt, port);
	}
	CloseLibrary((struct Library *)ArpBase);
    }
    else {	/* Arp did`t open */
	pkt->dp_Res1 = DOS_FALSE;
	pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
	ReplyPkt(pkt, port);
    }

    return;
}


/*
 *  FUNCTION
 *	main_lupe
 *
 *  DESCRIPTION
 *	This is the `waitloop' of the handler. It get`s the massage,
 *	interpreted it, executes the right functions and exits.
 */

static void
main_lupe(register struct MsgPort * port, register struct DosList * node)
{
    register struct DosPacket * pkt;
    register struct Message   * msg;
	     BOOL		quit;

    quit = FALSE;

    while (!quit) {

	WaitPort (port);
	while (msg = GetMsg(port)) {
	    pkt = (struct DosPacket *)msg->mn_Node.ln_Name;

	    pkt->dp_Res1 = DOS_FALSE;
	    pkt->dp_Res2 = 0;


	    switch(pkt->dp_Type) {

		    /* Exit the handler. Note that no error checking
		     * is made. If you send this packet YOU must first
		     * be sure of that no program is using the handler.
		     *	   This packet was ONLY implemented for testing
		     * purpose!
		     */
	    case ACTION_DIE:
		quit = TRUE;
		break;

	    case ACTION_FINDINPUT:
		action_input(pkt, port);
		break;

	    case ACTION_FINDOUTPUT:
		action_output(pkt, port);
		break;

	    case ACTION_END:
		action_end(pkt);
		break;

	    case ACTION_READ:
		action_read(pkt);
		break;

	    case ACTION_WRITE:
		action_write(pkt);
		break;

	    case ACTION_LOCATE_OBJECT:
		action_lock(pkt, port, node);
		break;

	    case ACTION_COPY_DIR:
		action_copy_lock(pkt);
		break;

	    case ACTION_FREE_LOCK:
		action_freelock(pkt);
		break;

	    case ACTION_DELETE_OBJECT:
		action_delete(pkt);
		break;

	    case ACTION_EXAMINE_OBJECT:
		action_examine_object(pkt);
		break;

	    case ACTION_EXAMINE_NEXT:
		action_examine_next(pkt);
		break;

		/* Fooling the client that we accept the following
		 * action types, so copy etc. won`t make a fuzz.
		 */
	    case ACTION_SET_PROTECT:
	    case ACTION_SET_COMMENT:
	    case ACTION_SET_DATE:
		pkt->dp_Res1 = DOS_TRUE;
		break;


	    default:
		pkt->dp_Res1 = DOS_FALSE;
		pkt->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
		break;

	    } /* switch */

	    ReplyPkt(pkt, port);

	} /* while */
    } /* while */

    return;

} /* main_lupe */


/*
 *  FUNCTION
 *	ReplyPkt
 *
 *  DESCRIPTION
 *	Replies the Packet back to the client.
 *
 *  NOTE
 *	This function is called even if Arp.Library didn`t open.
 */

static void
ReplyPkt(register struct DosPacket * pkt, register struct MsgPort * port)
{
    register struct Message * msg;
    register struct MsgPort * rport;

    rport = pkt->dp_Port;
    msg   = pkt->dp_Link;
    pkt->dp_Port = port;
    msg->mn_Node.ln_Name = (BYTE *)pkt;
    msg->mn_Node.ln_Succ = NULL;
    msg->mn_Node.ln_Pred = NULL;

    PutMsg(rport,msg);
    return;
} /* ReplyPkt */
