*****Listing 2*****

/*
 *	CDE.C: Extended "cd" command for MS-DOS.
 *	Written by Leor Zolman, 9/20/89
 *
 *	Features:
 *		1)	Allows changing to another drive and dirctory in one step
 *		2)	Supports directory aliasing through environment variables
 *		3)	With no arguments, optionally switches to 'home' directory
 *			(if the HOME environment variable is currently defined)
 *		3)	Manages a "previous directory" stack through environment
 *			variables. The number of entries in the stack is dynamically
 *			configurable through a special controlling environment variable.
 *		4)	For special case of stack size = 1, toggling back and forth
 *			between two directories is supported
 *		  
 *	 Usage:
 *		cde [d:][path]		(changes to given drive/directory)
 *		cde <env-var-name>	(indirect dir change on environment variable)
 *		cde					(changes to HOME directory, if defined, or
 *								returns current working directory otherwise)
 *
 *	Compile/Link:
 *		cl /Ox cde.c util.c envlib	(where ENVLIB.OBJ is Master Env. Pkg.)
 *
 *	Uses the Master Environment library from CUJ 7/89.
 *
 */

#include	<stdio.h>
#include	<dos.h>
#include	<string.h>
#include	<stdlib.h>
#include	"util.h"
	
main(int argc, char **argv)
{
	char	*pathp;
	char	cwdbuf[MAX_DIRNAME_SIZE];		/* buffer for current dir name	*/

	int		chaincnt;						/* size of dir stack			*/
	char	chaincnt_txt[10], *chaincntp;
	char	chnevar1[MAX_EVARNAME_SIZE],	/* env var names built here		*/
			chnevar2[MAX_EVARNAME_SIZE];
	char	chndname_save[MAX_DIRNAME_SIZE], *chndname;
	char	itoabuf[10];					/* used by itoa() function		*/
	int		i;
	
								/* Get current dir. name and current drive:	*/
	getcwd(cwdbuf, MAX_DIRNAME_SIZE);
	
	if (argc == 1)						/* if no args given,				*/
		if (pathp = m_getenv(HOME_NAME))	/* if HOME directory defined,	*/
		{
			change_dir(pathp);              /* then try to change to it.    */
			strcpy(chnevar1, CHAIN_BASE);   /* set top-stack env var        */
			strcat(chnevar1, "1");
			if (m_putenv(chnevar1, cwdbuf))   /* to old dir                */
				error("Error setting environment variable");
			return 0;
		}
		else
		{								/* just print current working dir	*/
			cputs(cwdbuf);
			putch('\n');
			return 0;
		}

	if (argc != 2)
		error("Usage: cde [d:][newpath] or <environment-var-name>\n");
	
	pathp = argv[1];					/* skip whitespace in pathname	*/
	
	if (chndname = m_getenv(pathp))		/* if env-var-name given,		*/
		pathp = chndname;				/* use its value as new path	*/

	change_dir(pathp);

					/* Read or initialize master chain length variable:	*/
	if ((chaincntp = m_getenv(CHAINS_VAR)) == NULL)
		if (m_putenv(CHAINS_VAR,
					strcpy(chaincntp = chaincnt_txt, DEFAULT_CHAINS)))
			error("Error creating environment variable");
	
							/* Update the environment directory chain:	*/
	chaincnt = atoi(chaincntp);
	for (i = chaincnt; i > 0; i--)
	{					/* construct name of previous dirname variable:	*/
		if (i != 1)
		{
			strcpy(chnevar2, CHAIN_BASE);
			strcat(chnevar2, itoa(i-1, itoabuf, 10));
		}

		if (chndname = ((i != 1) ? m_getenv(chnevar2) : cwdbuf))
		{							/* copy value of prev. to current	*/
			strcpy(chndname_save, chndname);	/* m_putenv() bashes it	*/
			strcpy(chnevar1, CHAIN_BASE);
			strcat(chnevar1, itoa(i, itoabuf, 10));
			if (m_putenv(chnevar1, chndname_save))
				error("Error setting environment variable");
		}
	}
	return 0;
}

