/*
 *	Copyright (C) 1992  TGV, Incorporated
 *
 *	CD Command
 *
 */

#include "comnd.h"
#include "vax-mm.h"
#include <errno.h>
#include <fab.h>
#include <nam.h>
#include <lnmdef.h>
#include <rmsdef.h>

	unsigned long int Field_Break_Mask[4] =
		{0x0,0x80000001,0x0,0x80000000}
;	/* Break mask for fields*/
static char Atom_Buffer[128];

CMD_Cd()
{
	
static struct comnd_function Field_LOCAL_3 = {
	COMND_FIELD,
	(COMND_SUPPRESS_DEFAULT_HELP | COMND_BREAK),
	0,
	(int)0,
	0,
	0,
	Field_Break_Mask};

static struct comnd_function Field_LOCAL_2 = {
	COMND_QUOTED_STRING,
	COMND_SUPPRESS_DEFAULT_HELP,
	&Field_LOCAL_3,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Field1 = {
	COMND_DIRECTORY,
	(COMND_HELP_VALID | COMND_SUPPRESS_DEFAULT_HELP),
	&Field_LOCAL_2,
	(int)0,
	"local directory string",
	0,
	0};

static struct comnd_function Field = {
	COMND_CONFIRM,
	COMND_SUPPRESS_DEFAULT_HELP,
	&Field1,
	(int)0,
	0,
	0,
	0};
	struct comnd_function *f;
	int Jfn;
	char Directory[256], Full_Directory[256];
	int Clear_Atom_Buffer;

	/*
	 *	Do noise
	 */
	Noise("to directory");

	/*
	 *	Add an atom buffer if not there
	 */
	Clear_Atom_Buffer = 0;
	if (!Command_State.atom_buffer) {
		Clear_Atom_Buffer = 1;
		Command_State.atom_buffer = Atom_Buffer;
		Command_State.atom_buffer_size = sizeof(Atom_Buffer);
	}

	/*
	 *	Get the directory
	 */
	COMND(&Command_State,&Field,&Jfn,&f);
	strcpy(Directory, Atom_Buffer);
	if (f->code == COMND_CONFIRM) {
		printf("? Missing local directory\n");
		Confirm();
		goto Done;
	}
	/*
	 *	Get confirmation
	 */
	Confirm();
	/*
	 *	Deal with directory specs
	 */
	if (f->code == COMND_DIRECTORY) rljfn_jsys(Jfn);
	/*
	 *	Do it
	 */
	if (Change_Directory(Directory, Full_Directory, 1) < 0) {
		socket_perror(Directory);
	} else {
		printf("Connected to %s.\n",Full_Directory);
	}

Done:
	/*
	 *	Remove the temp Atom Buffer if necessacary
	 */
	if (Clear_Atom_Buffer) {
		Command_State.atom_buffer = 0;
		Command_State.atom_buffer_size = 0;
	}
	return;
}


/*
 *	Change working directory
 */
int Change_Directory(Directory, Full_Directory_Name, Supervisor_Mode)
char *Directory;
char *Full_Directory_Name;
int Supervisor_Mode;
{
	register char *cp;
	struct {int Size; char *Ptr;} Table,Name;
	struct {
		short int Size;
		short int Type;
		char *Buffer;
		short int *Returned_Length;
		} Equiv[2];
	struct FAB Fab;				/* File access block	*/
	struct NAM Nam;				/* Nam block		*/
	char Es_String[256];			/* Expanded string	*/
	char Rs_String[256];			/* Resultant string	*/
    	int vmserrno;

	/*
	 *	Fill in the FAB/NAM
	 */
	bzero(&Fab,sizeof(struct FAB));
	Fab.fab$b_bid = FAB$C_BID;
	Fab.fab$b_bln = sizeof(struct FAB);
	Fab.fab$l_nam = &Nam;
	bzero(&Nam,sizeof(struct NAM));
	Nam.nam$b_bid = NAM$C_BID;
	Nam.nam$b_bln = sizeof(struct NAM);
	Nam.nam$l_esa = Es_String;
	Nam.nam$b_ess = 255;
	Nam.nam$l_rsa = Rs_String;
	Nam.nam$b_rss = 255;
	/*
	 *	Parse the directory spec!
	 */
	Fab.fab$l_fna = Directory;
	Fab.fab$b_fns = strlen(Fab.fab$l_fna);
	vmserrno = SYS$PARSE(&Fab);
	if (!(vmserrno & 1)) {
		return(-1);
	}
	Es_String[Nam.nam$b_esl] = 0;
	/*
	 *	Check to be sure we didn't get back a filename from
	 *	$PARSE. If we did, it might be the user accidently
	 *	doing a "CD FOO" when he meant "CD [.FOO]"
	 */
	if ((Nam.nam$b_name != 0) ||
	    (Nam.nam$b_type != 1) ||	    /* .; */
	    (Nam.nam$b_ver  != 1)) {
	    vmserrno = RMS$_DIR;
	    return(-1);
	}
	/*
	 *	Set the default disk
	 */
	Equiv[0].Size = (char *) Nam.nam$l_dir - Es_String /* - 1 */; /* Leave the ":"!! */
	if (Equiv[0].Size > 0) {
	    Equiv[0].Type = LNM$_STRING;
	    Equiv[0].Buffer = Es_String;
	    Equiv[0].Returned_Length = 0;
	    Equiv[1].Size = 0;
	    Equiv[1].Type = 0;
	    Table.Ptr = "LNM$PROCESS_TABLE";
	    Table.Size = 17;
	    Name.Ptr = "SYS$DISK";
	    Name.Size = 8;
	    if (Supervisor_Mode) {
		vmserrno = LIB$SET_LOGICAL(&Name, 0, &Table, 0, Equiv);
	    } else {
		vmserrno = SYS$CRELNM(0,&Table,&Name,0,Equiv);
	    }
	    if (!(vmserrno & 1)) {
		    return(-1);
	    }
	}
	/*
	 *	Set the default directory spec.
	 */
	Name.Ptr = (char *) Nam.nam$l_dir;
	Name.Size = Nam.nam$b_dir;
	vmserrno = SYS$SETDDIR(&Name,0,0);
	if (!(vmserrno & 1)) {
		return(-1);
	}

	/*
	 *	Done
	 */
	* (char *) Nam.nam$l_name = '\0';
	strcpy(Full_Directory_Name,Es_String);
	return(0);
}
