Metropoli BBS
VIEWER: main.c MODE: TEXT (ASCII)
/****************************************************************/
/*								*/
/*			      main.c				*/
/*			      DOS-C				*/
/*								*/
/*			Main IPL Functions			*/
/*								*/
/*			Copyright (c) 1991			*/
/*			Pasquale J. Villani			*/
/*			All Rights Reserved			*/
/*								*/
/* This file is part of DOS-C.					*/
/*								*/
/* DOS-C is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License	*/
/* as published by the Free Software Foundation; either version	*/
/* 2, or (at your option) any later version.			*/
/*								*/
/* DOS-C is distributed in the hope that it will be useful, but	*/
/* WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	*/
/* the GNU General Public License for more details.		*/
/*								*/
/* You should have received a copy of the GNU General Public	*/
/* License along with DOS-C; see the file COPYING.  If not,	*/
/* write to the Free Software Foundation, 675 Mass Ave,		*/
/* Cambridge, MA 02139, USA.					*/
/****************************************************************/


#define MAIN
#include "../../hdr/portab.h"
#include "globals.h"

/* $Logfile:   C:/dos-c/src/ipl/main.c_v  $ */
#ifndef IPL
static BYTE *mainRcsId = "$Header:   C:/dos-c/src/ipl/main.c_v   1.2   01 Sep 1995 17:44:38   patv  $";
#endif

/*
 * $Log:   C:/dos-c/src/ipl/main.c_v  $
 *	
 *	   Rev 1.2   01 Sep 1995 17:44:38   patv
 *	First GPL release.
 *	
 *	   Rev 1.1   30 Jul 1995 20:48:10   patv
 *	Eliminated version strings in ipl
 * 
 *    Rev 1.0   02 Jul 1995  8:25:52   patv
 * Initial revision.
 *
 */

COUNT ver(), help(), dir(), type(), prompt(), boot_kernel(), mon86();
COUNT unknown();
VOID init_ipl(), signon(), ipl();

struct table
{
	BYTE	*entry;
	COUNT	(*func)();
};

struct table  commands[] =
{
	{"?", help},
	{"help", help},
	{"ver", ver},
	{"dir", dir},
	{"type", type},
	{"prompt", prompt},
	{"boot", boot_kernel},
	{"", unknown}
};

static COUNT BlockIndex = 0;
static BYTE *tail;		/* an MS-DOS wart emulation		*/

static BYTE pr_string[LINESIZE];
static BYTE *dflt_pr_string = "\n$n$g ";
static BYTE *psignon = "\nDOS-C IPL v%d.%02d\n";
BYTE *id = "wb2gbf";
static BYTE *szDefaultKernel = "kernel.exe";


/* function protypes				*/
#ifdef PROTO
VOID signon(VOID);
VOID init_ipl(VOID);
VOID init_device(struct dhdr FAR *);
struct dhdr FAR *link_dhdr(struct dhdr FAR *, struct dhdr FAR *);
COUNT boot_kernel(VOID);
VOID ipl(VOID);
struct table *lookup(struct table *, BYTE *);
COUNT unknown(VOID);
COUNT ver(VOID);
COUNT help(VOID);
COUNT type(COUNT, BYTE *[]);
COUNT dir(COUNT, BYTE *[]);
#else
VOID signon();
VOID init_ipl();
VOID init_device();
struct dhdr FAR *link_dhdr();
COUNT boot_kernel();
VOID ipl();
struct table *lookup();
COUNT unknown();
COUNT ver();
COUNT help();
COUNT type();
COUNT dir();
#endif
VOID init_ipl(), signon(), ipl();


VOID main()
{
	BYTE szDrive[2] =
		{ '@', 0 };

#ifdef DEBUG
	MarkStack();
	printf("\n*** IPL started ***\nStack at 0x%04x:%04x\n",
		MarkSS, MarkSP);
#endif
	init_ipl();
#ifdef DEBUG
	MarkStack();
	printf("\n*** IPL initialized ***\nStack at 0x%04x:%04x\n",
		MarkSS, MarkSP);
#endif
	signon();
	szDrive[0] += BootDrive;
	printf("\nIPL Booting %s from drive %s\n", szDefaultKernel, szDrive);
	boot_kernel();
	ipl();
}

static VOID signon()
{
	printf(psignon, MAJOR_RELEASE, MINOR_RELEASE);
}


static VOID init_ipl()
{
	REG struct dhdr FAR *dhp = (struct dhdr FAR *)&nul_dev;
	REG COUNT i;
	struct dhdr FAR *link_dhdr();

	/* Initialize driver chain			*/
#ifdef DEBUG
	MarkStack();
	printf("Initialize driver chain\nStack at 0x%04x:%04x\n",
		MarkSS, MarkSP);
	printf("Device driver chain starts at 0x%04x:%04x\n",
		FP_SEG(dhp), FP_OFF(dhp));
#endif
	dhp = link_dhdr(dhp, (struct dhdr FAR *)&con_dev);
	dhp = link_dhdr(dhp, (struct dhdr FAR *)&blk_dev);
	syscon = (struct dhdr FAR *)&con_dev;

	/* Initialize the screen handler for backspaces			*/
#ifdef DEBUG
	MarkStack();
	printf("Initialize the screen handler for backspaces\n");
#endif
	scr_pos = 0;

	/* Initialize the file tables					*/
#ifdef DEBUG
	printf("Initialize the file tables\n");
#endif
	for(i = 0; i < NFILES; i++)
		f_nodes[i].f_count = 0;
	/* Log-in the default drive.					*/
	default_drive = 0;

	/* Initialzie the current directory structures			*/
	for(i = 0; i < NDEVS; i++)
		scopy("\\", blk_devices[i].dpb_path);

	/* Initialze the disk buffer management functions		*/
	init_buffers();

	/* Now to initialize all special flags, etc.			*/
	mem_access_mode = FIRST_FIT;
	break_ena = TRUE;
	verify_ena = FALSE;
	InDOS = 0;
	version_flags = 0;

	/* Figure out 'A' or 'C' drive					*/
	if(BootDrive != 0)
		BootDrive = 3;
	else
		BootDrive = 1;
}


VOID init_device(dhp)
struct dhdr FAR *dhp;
{
	request rq;

	rq.r_unit = 0;
	rq.r_status = 0;
	rq.r_command = C_INIT;
	rq.r_length = sizeof(request);
#ifdef DEBUG
	printf("init_device: Initializing device with packet at 0x%04x:%04x\n",
		FP_SEG(&rq), FP_OFF(&rq));
#endif
	execrh((request FAR *)&rq, dhp);
#ifdef DEBUG
	printf("init_device: execrh returned with status = 0x%04x\n",
		rq.r_status);
#endif

	/* check for a block device and update device control block	*/
	if(!(dhp -> dh_attr & ATTR_CHAR) && (rq.r_nunits != 0))
	{
		REG COUNT Index;

		for(Index = 0; Index < rq.r_nunits; Index++, BlockIndex++)
		{
#ifdef DEBUG
			printf("init_device: building blk_devices[%d]\n",
				lastdrive);
#endif
			blk_devices[lastdrive].dpb_unit = lastdrive;
			blk_devices[lastdrive].dpb_subunit = Index;
			blk_devices[lastdrive].dpb_device = dhp;
			blk_devices[lastdrive].dpb_flags = M_CHANGED;
			++lastdrive;
		}
	}
#ifdef DEBUG
	printf("init_device: complete.\n");
#endif
}


struct dhdr FAR *link_dhdr(lp, dhp)
struct dhdr FAR *dhp, FAR *lp;
{
	lp -> dh_next = dhp;
#ifdef DEBUG
	printf("link_dhdr: initializing device at 0x%04x:%04x\n",
		FP_SEG(dhp), FP_OFF(dhp));
#endif
	init_device(dhp);
#ifdef DEBUG
	printf("link_dhdr: init_device complete\n");
#endif
	return dhp;
}


static COUNT boot_kernel()
{
	COUNT rc;
	exec_blk exb;

	/* Test for user break				*/
	if(con_break())
		return TRUE;
	printf("\nBooting DOS-C ");

#ifndef IPLDBG
	/* If not - initialize the exec block		*/
	/* and go for it!				*/
	exb.exec.env_seg = 0;
	exb.exec.cmd_line = "";
	exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb far *)0;
	rc = DosExec(P_WAIT, (exec_blk far *)&exb, (BYTE far *)szDefaultKernel);

	/* if we're here, unable to load the kernel, so	*/
	/* give the user the reason and exit		*/
	printf("IPL cannot load kernel\n\n");
	switch(rc)
	{
	case DE_FILENOTFND:
		printf("File %s not found\n", szDefaultKernel);
		break;

	case DE_INVLDDATA:
		printf("Inavlid data\n");
		break;

	default:
		printf("Unknown reason (rc = %d)\n", rc);
		break;
	}
#endif
	return FALSE;
}


static VOID ipl()
{
	register struct table *p;
	register BYTE *lp;
	struct table *lookup();
	BYTE *scan(), *skipwh();
	static COUNT argc;
	static BYTE *argv[16];
	static BYTE args[16][LINESIZE];

	scopy(dflt_pr_string, pr_string);
	for(;;)
	{
		put_prompt(pr_string);
		kb_buf.kb_size = LINESIZE - 1;
		kb_buf.kb_count = 0;
		sti((keyboard far *)&kb_buf);
		kb_buf.kb_buf[kb_buf.kb_count] = '\0';
		for(argc = 0; argc < 16; argc++)
		{
			argv[argc] = (BYTE *)0;
			args[argc][0] = '\0';
		}
		lp = scan(kb_buf.kb_buf, args[0]);
		argv[0] = args[0];
		/* this kludge is for an MS-DOS wart emulation */
		tail = skipwh(lp);
		for(argc = 1; ; argc++)
		{
			lp = scan(lp, args[argc]);
			if(*args[argc] == '\0')
				break;
			else
				argv[argc] = args[argc];
		}
		if(*argv[0] != '\0')
		{
			p = lookup(commands, argv[0]);
			(*(p -> func))(argc, argv);
		}
	}
}


COUNT prompt(argc, argv)
COUNT argc;
BYTE *argv[];
{
	if(argc == 1)
		scopy(dflt_pr_string, pr_string);
	else
	{
		pr_string[0] = '\n';
		/* should be */
		/* scopy(argv[1], &pr_string[1]); */
		/* but to emulate an MS-DOS wart, is */
		scopy(tail, &pr_string[1]);
	}
	return TRUE;
}


/* put_prompt - print prompt obeying $x commands */
COUNT put_prompt(fmt)
register BYTE *fmt;
{
	register BYTE c;
	BYTE *s;

	while ((c = *fmt++) != '\0')
	{
		if (c != '$')
		{
			put_console(c);
			continue;
		}
		switch (c = *fmt++)
		{
		case 'p':
			put_console('A' + default_drive);
			put_console(':');
			for(s = blk_devices[default_drive].dpb_path; *s != '\0'; s++)
				put_console(*s);
			continue;

		case 'n':
			put_console('A' + default_drive);
			continue;

		case 'g':
			put_console('>');
			continue;

		case 'l':
			put_console('<');
			continue;

		case 'b':
			put_console('|');
			continue;

		case 'e':
			put_console('=');
			continue;

		default:
			put_console(c);
			continue;
		}
	}
	return TRUE;
}


struct table *lookup(p, token)
struct table *p;
BYTE *token;
{
	while(*(p -> entry) != '\0')
	{
		if(strcmp(p -> entry, token) == 0)
			break;
		else
			++p;
	}
	return p;
}


COUNT unknown()
{
	printf("\nBad command or file name");
	return FALSE;
}


COUNT ver()
{
	printf(psignon, MAJOR_RELEASE, MINOR_RELEASE);
	return TRUE;
}


COUNT help()
{
	printf("\nSorry, help is not available");
	return TRUE;
}


COUNT type(argc, argv)
COUNT argc;
BYTE *argv[];
{
	COUNT fd;
	BYTE c;

	if(argc != 2)
	{
		printf("\nInvalid number of parameters\n");
		return FALSE;
	}
	if((fd = dos_open((BYTE far *)argv[1], 0)) < 0)
	{
		printf("\nFile not found");
		return FALSE;
	}
	else
		printf("\n");
	while(dos_read(fd, (BYTE far *)&c, 1) == 1)
		printf("%c", c);
	dos_close(fd);
	return TRUE;
}


COUNT dir(argc, argv)
COUNT argc;
BYTE *argv[];
{
	REG struct f_node *fnp;
	BYTE buf[13];
	COUNT count = 0;


	if(argc == 1)
	{
		if((fnp = dir_open((BYTE FAR *)".")) == (struct f_node *)0)
			goto quit;
	}
	else
	{
		if((fnp = dir_open((BYTE FAR *)argv[1])) == (struct f_node *)0)
			goto quit;
	}
	while(dir_read(fnp) == sizeof(struct dirent))
	{
		if(fnp -> f_dir.dir_name[0] != '\0' && fnp -> f_dir.dir_name[0] != DELETED)
		{
			WORD hour = TM_HOUR(fnp -> f_dir.dir_time);

			bcopy(fnp -> f_dir.dir_name, &buf[0], 8);
			buf[8] = ' ';
			bcopy(fnp -> f_dir.dir_ext, &buf[9], 3);
			buf[12] = '\0';
			printf("\n   %s %-10ld  %-2d-%-02d-%-02d  %-2d:%-02d%c",
				buf, fnp -> f_dir.dir_size,
				DT_MONTH(fnp -> f_dir.dir_date),
				DT_DAY(fnp -> f_dir.dir_date),
				(DT_YEAR(fnp -> f_dir.dir_date) + 1980) % 100,
				hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour,
				TM_MIN(fnp -> f_dir.dir_time),
				hour >= 12 ? 'p' : 'a');
			++count;
		}
	}
	printf("\n%-10d file(s)\n", count);
quit:	dir_close(fnp);
	return TRUE;
}



[ RETURN TO DIRECTORY ]