*****Listing 4*****

/*
 * UTIL.C:	Utility functions for CDE/RET package
 *
 *		These function rely on the "bdos" library function
 *		from your compiler's library. Prototype:
 *
 *		int bdos(int dosfn, unsigned dosdx, unsigned dosal);
 */

#include 	<stdio.h>
#include	<dos.h>
#include	<ctype.h>
#include	"util.h"

/*
 *	Print error msg and abort:
 */

void error(char *msg)
{
	cputs("cde: ");
	cputs(msg);
	putch('\n');
	exit(-1);
}

/*
 *	Change to specified drive/path, terminate program on error:
 */

void change_dir(char *new_path)
{
	int old_drive;
	
	old_drive = getdrive();

	while (*new_path && isspace(*new_path))	/* skip whitespace			*/
		new_path++;

	if (new_path[1] == ':')					/* if drive designator		*/
	{										/* given, then set drive	*/
		if (setdrive(tolower(*new_path) - 'a'))
			error("Can't select given drive\n");
		new_path += 2;
	}
	
	if (*new_path && chdir(new_path))	/* If path given, set new path.	*/
	{
		setdrive(old_drive);			/* If error, restore drive		*/
		error("Can't change to given path");
	}
}


/*
 *	DOS functions, written in terms of the "bdos" function:
 */

int cputs(char *txt)		/* display msg, console I/O only */
{
	char c;
	
	while (c = *txt++)
	{
		if (c == '\n')
			putch('\r');
		putch(c);
	}
	return 0;
}

int putch(char c)				/* display a char on console */
{
	return bdos(2, c, 0);
}

int setdrive(int drive_no)		/* set logical drive. Return */
{								/* non-zero on error.		*/
	int after;

	bdos(0x0E, drive_no, 0);
	after = bdos(0x19, 0, 0);
	if ((after & 0xff) == drive_no)    /* low 8 bits are new drive no. */
		return 0;			/* set correctly */
	else
		return -1;			/* error. */
}

int getdrive()					/* return current logical drive */
{
	return bdos(0x19, 0, 0);
}

