/*
 *	Includes
 */
#include "comnd.h"
#include "gtjfn.h"				/* Topslib GTJFN	*/
#include <ctype.h>				/* Standard I/O		*/
#include "multinet_root:[multinet.include]errno.h"
#include <stdio.h>				/* Standard I/O		*/
#include <jpidef.h>				/* $GETJPI codes	*/
#include <clidef.h>

static 	unsigned long int Field_Break_Mask[4] =
		{0x0,0x80008001,0x0,0x80000000}
;
static char Atom_Buffer[128];


/*
 *	Spawn a DCL command
 */
CMD_Spawn(Comnd_State)
struct comnd_state *Comnd_State;
{

	
static struct {
	int current_entries;
	int maximum_entries;
	struct tbluk_keyword keywords[6];
	} Options = {
	6,6,
	{{0,	"Input",	(int)0},
	 {0,	"Nological_Names",	(int)1},
	 {0,	"Nosymbols",	(int)2},
	 {0,	"Nowait",	(int)3},
	 {0,	"Output",	(int)4},
	 {0,	"Process",	(int)5}}};
	
static struct comnd_function Confirm = {
	COMND_CONFIRM,
	(COMND_SUPPRESS_DEFAULT_HELP),
	0,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Switch_LOCAL_1 = {
	COMND_TEXT,
	0,
	&Confirm,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Switch = {
	COMND_SWITCH,
	0,
	&Switch_LOCAL_1,
	(int)&Options,
	0,
	0,
	0};
	
static struct comnd_function Field_LOCAL_1 = {
	COMND_FIELD,
	(COMND_SUPPRESS_DEFAULT_HELP | COMND_BREAK),
	0,
	(int)0,
	0,
	0,
	Field_Break_Mask};

static struct comnd_function Field = {
	COMND_QUOTED_STRING,
	(COMND_SUPPRESS_DEFAULT_HELP),
	&Field_LOCAL_1,
	(int)0,
	0,
	0,
	0};

	char *cp;
	struct tbluk_keyword *Host_Entry;
	struct comnd_function *f;
	struct tbluk_keyword *t;
	struct tbluk_keyword New_Entry;
	char Hostname[128];
	int Number_Of_Options, Clear_Atom_Buffer=0;
	char Input[256], Output[256], Process[64], DCL_Command[256];
	struct Descr {int Size; char *Ptr;}
		*In_Dp = 0, In_D = {0, Input},
		*Out_Dp=0,  Out_D = {0, Output},
		*Proc_Dp=0, Proc_D = {0, Process},
		*DCL_Dp=0, DCL_D = {0, DCL_Command};
	int	Flags=0, status;
	int	Saved_Comnd_State_Flags;
	static char *Help_Strings[] = {
		"infile",
		"No symbols flag",
		"Nowait flag" ,
		"No logicals flag",
		"outfile",
		"subprocess name",
		};

	/*
	 *	Save the original Comnd State flags and arrange to ignore "@" processing
	 */
	Saved_Comnd_State_Flags = Comnd_State->flags;
	Comnd_State->flags |= COMND_NO_INDIRECT_FILE;
	/*
	 *	Get the options
	 */
	Input[0] = '\0';
	Output[0] = '\0';
	Process[0] = '\0';

	__noise("command",Comnd_State);

	if (!Comnd_State->atom_buffer) {
	    Clear_Atom_Buffer=1;
	    Comnd_State->atom_buffer = Atom_Buffer;
	    Comnd_State->atom_buffer_size = sizeof(Atom_Buffer);
	}

	Number_Of_Options = 0;
	for (;;) {
		/*
		 *	Get the option
		 */
		if (COMND(Comnd_State,&Switch,&t,&f) < 0) goto Return;

		if ( f->code == COMND_TEXT ) {
			if (strlen(Comnd_State->atom_buffer) ) {
				strcpy(DCL_Command, Comnd_State->atom_buffer);
				DCL_D.Size = strlen(DCL_D.Ptr);
				DCL_Dp = &DCL_D;
			}
			break;
		}


		/*
		 *	If it is a confirm, break
		 */
		if (f->code == COMND_CONFIRM) break;
		/*
		 *	Process this option
		 */
		Number_Of_Options++;
		Field.help_string = Help_Strings[t->user_data];
		if (t->user_data  == 1 )  Flags |= CLI$M_NOLOGNAM;
		else if (t->user_data  == 2 )  Flags |= CLI$M_NOCLISYM;
		else if (t->user_data  == 3 )  Flags |= CLI$M_NOWAIT;
		else  {
			/* Any of the following cases we need to obtain and check  value (/XXX=value)
			 * The TOPS parser keeps the '=', which is evil in these cases.
			 */
			if (COMND(Comnd_State,&Field,0,0) < 0) goto Return;
			cp = Comnd_State->atom_buffer;
			if ( *cp == '=') cp++; /* Eat 1 '=' */
			switch(t->user_data) {
				case 0: strcpy(Input, cp);
					In_D.Size = strlen(Input);
					In_Dp = &In_D;
					break;
				case 4: strcpy(Output, cp);
					Out_D.Size = strlen(Out_D.Ptr);
					Out_Dp = &Out_D;
					break;
				case 5: strcpy(Process, cp);
					Proc_D.Size = strlen(Proc_D.Ptr);
					Proc_Dp = &Proc_D;
					break;
			}
		}
	}

	if (getenv("MULTINET_DISABLE_SPAWN")) goto Return;

	status = lib$spawn(DCL_Dp, In_Dp, Out_Dp, &Flags, Proc_Dp, 0, 0, 0, 0, 0 ,0 ,0, 0);
	if ( !(status & 1) ) {
		vmserrno = status;
		printf("%s\n",vms_errno_string());
	}
Return:
	Comnd_State->flags = Saved_Comnd_State_Flags;
	if (Clear_Atom_Buffer) {
	    Comnd_State->atom_buffer = 0;
	    Comnd_State->atom_buffer_size = 0;
	}
}

CMD_Push(Comnd_State)
struct comnd_state *Comnd_State;
{

	/*
	 *	Do noise and confirmation
	 */
	__noise("to exec",Comnd_State);
		__confirm(Comnd_State);
	/*
	 *	Push
	 */
#ifndef vax11c
	kill(0,SIGTSTP);
#else	vax11c
	suspend_program();
#endif	vax11c
}


/*
 *
 */

CMD_Attach(Comnd_State)
struct comnd_state *Comnd_State;
{
	
static struct comnd_function Process_Name_LOCAL_3 = {
	COMND_FIELD,
	(COMND_HELP_VALID | COMND_SUPPRESS_DEFAULT_HELP | COMND_BREAK),
	0,
	(int)0,
	"process name",
	0,
	Field_Break_Mask};

static struct comnd_function Process_Name_LOCAL_2 = {
	COMND_TEXT,
	(COMND_SUPPRESS_DEFAULT_HELP),
	&Process_Name_LOCAL_3,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Process_Name_LOCAL_1 = {
	COMND_CONFIRM,
	(COMND_SUPPRESS_DEFAULT_HELP),
	&Process_Name_LOCAL_2,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Process_Name = {
	COMND_QUOTED_STRING,
	(COMND_SUPPRESS_DEFAULT_HELP),
	&Process_Name_LOCAL_1,
	(int)0,
	0,
	0,
	0};

	
	static char __Default_Buffer[1024];

static struct comnd_state Comnd_State1 = {
	{0},
	(COMND_HANDLE_ERRORS | COMND_RAISE),
	0,0,
	0,
	__Default_Buffer,
	sizeof(__Default_Buffer),
	0,0,0,
	Atom_Buffer,
	sizeof(Atom_Buffer)};

	struct comnd_function *f;
	char process_name[256], *cp;
	struct {int Size; char *Ptr;} pd = {0, process_name};
	int	pid = 0, status, code=JPI$_PID, Clear_Atom_Buffer=0;

	/*
	 *	Do noise
	 */
	__noise("process name",Comnd_State);

	if (!Comnd_State->atom_buffer) {
	    Clear_Atom_Buffer=1;
	    Comnd_State->atom_buffer = Atom_Buffer;
	    Comnd_State->atom_buffer_size = sizeof(Atom_Buffer);
	}

	/*
	 *	Get the file
	 */
	COMND(Comnd_State,&Process_Name,0,&f);
	strcpy(process_name, Comnd_State->atom_buffer);

	/*
	 *	If there was no process name,  prompt for it
	 */
	if (f->code == COMND_CONFIRM) {
		Comnd_State1.prompt = " Process Name to attach to: ";
		COMND_INIT(&Comnd_State1);
		COMND(&Comnd_State1,&Process_Name,0,&f);
		strcpy(process_name, Atom_Buffer);
			__confirm(&Comnd_State1);
	} else
		/*
		 *	Confirm
		 */
			__confirm(Comnd_State);

	if (Clear_Atom_Buffer) {
	    Comnd_State->atom_buffer = 0;
	    Comnd_State->atom_buffer_size = 0;
	}

	if (getenv("MULTINET_DISABLE_SPAWN")) return;

	pd.Size = strlen(pd.Ptr);
	status = lib$getjpi(&code , &pid, &pd, 0, 0, 0);
	/* If it wasn't a quoted string try uppercasing the name they
	 * entered if it didn't work as they entered it*/
	if ( !(status & 1)  && f->code != COMND_QUOTED_STRING ) {
		cp = process_name;
		while (*cp)  {
			*cp = _toupper(*cp);
			cp++;
		}
		status = lib$getjpi(&code , &pid, &pd, 0, 0, 0);
	}
	if ( (status & 1) )
		status = lib$attach(&pid);
	if ( !(status & 1) ) {
	    vmserrno = status;
	    printf("%s\n", (char *)vms_errno_string());
	}
}
