From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  4-AUG-1989 00:23
To:	MRGATE::"ARISIA::EVERHART"
Subj:	CD  FOR VMS    1 OF 1

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu,  3 AUG 89 20:48:55 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Thu, 3 Aug 89 20:31:16 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.37)
	id AA15548; Thu, 3 Aug 89 20:31:18 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 3 Aug 89 20:00:03 GMT
From: haven!aplcen!jhunix!ins_bxs@purdue.edu  (Xuning Shan)
Organization: The Johns Hopkins University - HCF
Subject: CD  FOR VMS    1 OF 1
Message-Id: <2197@jhunix.HCF.JHU.EDU>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

/*CD  V1.0  FOR VMS */

/* program:  CD V1.0         function: change directory and set prompt
					to current directory.
   Author: Xuning Shan  
	   Dept of Chemicnal Engineering
           The Johns Hopkins University, Baltimore, MD 21218
    Email: ins_bxs@jhuvms.BITNET

	CD accepts both UNIX and VMS syntaxes including VMS 
logical names.  Don't mix UNIX and VMS syntaxes  even though 
CD  accepts such syntax.  CD sets prompt to the current directory.
When the path is too long, CD will not set the prompt.
CD  supports one level "push" and "pop" directory function.
Type cd ?  for help.

The program has been tested under VMS V5.1 and VMS V4.7, C V2.2.
I did not find any bugs. If someone finds one, please 
report to ins_bxs@jhuvms. */

#include descrip
#include stdio
#define FALSE 0
#define NULL (char *)0
char *UP  = "[-]";
int dflag=FALSE;
char *malloc();
void descriptor();
void setdir();
int  setdev();
char newdir[80];
char device[20];
void parse();
main(argc,argv)
int argc;
char **argv;
{
	int status,i=0;
	char trans[80],*home;
	struct dsc$descriptor_s lognam;
	$DESCRIPTOR(r,trans);

	if(argc>3){
		help();
		exit();
	}
	if(argc>=2){
		if((strcmp(argv[1],"-p")==0) || (strcmp(argv[1],"-P")==0)){
			char *path,tmppath[40];
			$DESCRIPTOR(cdstack,"CDSTACK");
			$DESCRIPTOR(pathdesc,tmppath);
			path=getenv("PATH");
			UPPER(path);
			descriptor(&pathdesc,path);
			status=lib$set_logical(&cdstack,&pathdesc);	
			if(argc==3) strcpy(argv[1],argv[2]);
			if(argc==2) argc--; /*set to home directory*/
		}
	}
	if((argc==1) || (strcmp(argv[1],"~")==0)){
		home=malloc(80);   /*change to home directory */
		home=getenv("HOME");
		parse(home);
		setdev(device);
		setdir(newdir); 
		exit(); /*doesn't matter. It will return anyway!*/
	}
  	if(strcmp(argv[1],"..")==0){
		setdir(UP);
		exit();
	}
	if(strpbrk(argv[1],":[")!=NULL){ /*vms syntax*/
		 parse(argv[1]);
		 if(dflag) setdev(device);
		 setdir(newdir); exit();
	}
	if(strcmp(argv[1],"/")==0){
		strcpy(newdir,"[000000]");
		setdir(newdir);exit();
	}
	if(*argv[1]=='~'){
		char tmp[80]; i=0;
		home=malloc(80);
		home=getenv("HOME");
		while(*home!=']') tmp[i++]=(*home++);
		tmp[i++]='.'; /*replace ] with . */
		argv[1]++; /*get rid of ~ */
		if(*argv[1]=='/') argv[1]++;/*get rid of slash if present */
		while(*argv[1]) tmp[i++]=(*argv[1]++);
		tmp[i++]=']';tmp[i]='\0';
		parse(tmp);
		setdev(device);
		setdir(newdir); exit();
	}
	if(strcmp(argv[1],"+")==0){  /*pop up directory*/
		descriptor(&lognam,"CDSTACK");
		status=lib$sys_trnlog(&lognam,0,&r,0);
	 	parse(r.dsc$a_pointer);
		setdev(device);
		setdir(newdir);
		descriptor(&lognam,"CDSTACK");
/*		status=lib$delete_logical(&lognam,0); */
		exit();
	}

	if(strcmp(argv[1],"?")==0)help();

	UPPER(argv[1]);/*logical names should be upper!!*/
	descriptor(&lognam,argv[1]);
	status=lib$sys_trnlog(&lognam,0,&r,0); /*returned value in r*/
	/*status=1: logical name*/
	 parse(r.dsc$a_pointer);
	 if(dflag)setdev(device);
	 setdir(newdir);
	
		
}


void setdir(dir)
char *dir;
{
	struct dsc$descriptor_s desc;
	int status;
	char *cmd="set prompt=",curdir[80],*prompt,tmpstr[80];
	$DESCRIPTOR(setprompt,tmpstr);
	$DESCRIPTOR(tmp,curdir);

        desc.dsc$w_length=strlen(dir);      
        desc.dsc$b_dtype=DSC$K_DTYPE_T;        
        desc.dsc$b_class=DSC$K_CLASS_S;        
        desc.dsc$a_pointer=dir;    
	status=sys$setddir(&desc,0,0); /*set directory*/
	status=sys$setddir(0,0,&tmp); 
	prompt=strcat(cmd,tmp.dsc$a_pointer);
	descriptor(&setprompt,prompt);
	status=lib$do_command(&setprompt);
}

int setdev(dev)
char *dev;
{
	struct dsc$descriptor_s desc;
	$DESCRIPTOR(sysdisk,"SYS$DISK");
	int status;
	UPPER(dev);
        desc.dsc$w_length=strlen(dev);      
        desc.dsc$b_dtype=DSC$K_DTYPE_T;        
        desc.dsc$b_class=DSC$K_CLASS_S;        
        desc.dsc$a_pointer=dev;    
	status=lib$set_logical(&sysdisk,&desc);	
	return(status);
}




UPPER(str)
char *str;
{
	while(*str){
		*str=toupper(*str);
		str++;
	};
	return;
}


void parse(str)  /*most tricks are here*/
char *str;
{
	int i=0, vflag=FALSE;
	fixstr(str);/*get a string without spaces */
	if(strpbrk(str,"[")!=NULL)vflag=TRUE; /*vms syntax*/
	if((*str=='/') || (strpbrk(str,":")!=NULL)) {
		dflag=TRUE; /*need to set device as well*/
		if(*str=='/') str++; /*skip first slash*/
		while(*str){ /* get device*/
			if((*str=='/') || (*str==':')){
				str++;/*skip one char*/
				break; 
			}
			else
				device[i++]=(*str++);
		
		}
	
		device[i++]=':'; device[i]='\0'; i=0;
	}
	if(dflag){
		if(!vflag) newdir[i++]='[';
	}
	else {
		if(!vflag){
			newdir[i++]='[';
			newdir[i++]='.';
		}
	}
	while(*str){  /*get directory*/
		if((*str=='.') && (*(str+1)=='.') && (*(str+2)!='.')){
			newdir[i++]='-';
			str=str+2;
		}
		else if(*str=='/') {
			newdir[i++]='.';
			str++;
		}
		else {
			newdir[i++]=(*str++);
		}
	}
	if(!vflag)  newdir[i++]=']'; 
	newdir[i]='\0';
	return;
}




void descriptor(desc,str)    
struct dsc$descriptor_s *desc;
char *str; 
{
        desc->dsc$w_length=strlen(str);      
        desc->dsc$b_dtype=DSC$K_DTYPE_T;        
        desc->dsc$b_class=DSC$K_CLASS_S;        
        desc->dsc$a_pointer=str;    
}


#include ctype
fixstr(str)
char *str;
{
	while(*str){
		if(isspace(*str)){
			*str='\0';
			break;
		}
		str++;
	}
	return;
}

help()
{
	printf("\n\n\n\tcd  vms_directory_syntax\n");
	printf("\t\tChange to  specified directory\n");
	printf("\tcd unix_directory_syntax\n");
	printf("\t\tChange to specified directory\n");
	printf("\tcd -p directory_specification\n");
	printf("\t\tChange to specified directory\n");
	printf("\t\tand save current directory\n");
	printf("\tcd -p\n");
	printf("\t\tChange to login directory\n");
	printf("\t\tand save current directory\n");
	printf("\tcd +\n");
	printf("\t\t Change to previously saved directory\n");
	printf("\tcd\n");
	printf("\t\t Change to login directory\n\n");
	exit();
}

