Metropoli BBS
VIEWER: config.c MODE: TEXT (ASCII)
/****************************************************************/
/*								*/
/*			    config.c				*/
/*			      DOS-C				*/
/*								*/
/*		  config.sys Processing Functions		*/
/*								*/
/*			Copyright (c) 1996			*/
/*			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.					*/
/****************************************************************/


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

/* $Logfile:   D:/dos-c/src/kernel/config.c_v  $ */
#ifdef VERSION_STRINGS
static BYTE *RcsId = "$Header:   D:/dos-c/src/kernel/config.c_v   1.1   29 May 1996 21:03:44   patv  $";
#endif

/*
 * $Log:   D:/dos-c/src/kernel/config.c_v  $
 * 
 *    Rev 1.1   29 May 1996 21:03:44   patv
 * bug fixes for v0.91a
 * 
 *    Rev 1.0   19 Feb 1996  3:22:16   patv
 * Added NLS, int2f and config.sys processing
 */

#if 0
#define dos_open(x,y)	_open((const char *)(x),(y))
#define dos_read(x,y,z)	_read((int)(x),(void *)(y),(unsigned)(z))
#define dos_close	_close
#endif

static BYTE FAR *lpOldLast;
static BYTE FAR *lpBase;
static BYTE szToken[LINESIZE];
static BYTE szLine[LINESIZE];
static COUNT nCfgLine;
static COUNT nPass;

VOID Buffers(BYTE *pLine);
VOID Files(BYTE *pLine);
VOID InitPgm(BYTE *pLine);
VOID CfgFailure(BYTE *pLine);
BYTE *GetNumArg(BYTE *pLine, COUNT *pnArg);
BYTE *GetStringArg(BYTE *pLine, BYTE *pszString);

struct table *LookUp(struct table *p, BYTE *token);

struct table
{
	BYTE	*entry;
	BYTE	pass;
	VOID	(*func)(BYTE *pLine);
};

static struct table  commands[] =
{
	{"buffers",	1,	Buffers},
	{"files",	1,	Files},
	{"command",	1,	InitPgm},
	/* rem is never executed by locking out pass			*/
	{"rem",		0,	CfgFailure},
	/* default action						*/
	{"", 		-1,	CfgFailure}
};

BYTE FAR *KernelAlloc(WORD nBytes);

/* Do first time initialization.  Store last so that we can reset it	*/
/* later.								*/
void
PreConfig(void)
{
	/* Set pass number						*/
	nPass = 0;

	/* Initialize the base memory pointers				*/
	lpOldLast = lpBase = (BYTE FAR *)&last;

	/* Begin by initializing our system buffers			*/
	buffers = (struct buffer FAR *)
		KernelAlloc(Config.cfgBuffers * sizeof(struct buffer));
#ifdef DEBUG
	printf("Preliminary buffer allocated at 0x%04x:0x%04x\n",
		FP_SEG(buffers), FP_OFF(buffers));
#endif

	/* Initialize the file table					*/
	f_nodes = (struct f_node FAR *)
		KernelAlloc(Config.cfgFiles * sizeof(struct f_node));
	/* sfthead = (sfttbl FAR *)&basesft; */
	/* FCBp = (sfttbl FAR *)&FcbSft; */
	FCBp = (sfttbl FAR *)
		KernelAlloc(sizeof(sftheader)
		 + Config.cfgFiles * sizeof(sft));
	sfthead = (sfttbl FAR *)
		KernelAlloc(sizeof(sftheader)
		 + Config.cfgFiles * sizeof(sft));
#ifdef DEBUG
	printf("Preliminary f_node allocated at 0x%04x:0x%04x\n",
		FP_SEG(f_nodes), FP_OFF(f_nodes));
	printf("Preliminary FCB table allocated at 0x%04x:0x%04x\n",
		FP_SEG(FCBp), FP_OFF(FCBp));
	printf("Preliminary sft table allocated at 0x%04x:0x%04x\n",
		FP_SEG(sfthead), FP_OFF(sfthead));
#endif

	/* Done.  Now initialize the MCB structure			*/
	/* This next line is 8086 and 80x86 real mode specific		*/
#ifdef DEBUG
	printf("Preliminary  allocation completed: top at 0x%04x:0x%04x\n",
		FP_SEG(lpBase), FP_OFF(lpBase));
#endif
	first_mcb = FP_SEG(lpBase) + ((FP_OFF(lpBase) + 0x0f) >> 4);

	/* We expect ram_top as Kbytes, so convert to paragraphs */
	mcb_init((mcb FAR *)(MK_FP(first_mcb, 0)),
	 (ram_top << 6) - first_mcb - 1);
	nPass = 1;
}


/* Do second pass initialization.					*/
/* Also, run config.sys to load drivers.				*/
void
PostConfig(void)
{
	/* Set pass number						*/
	nPass = 2;

	/* Initialize the base memory pointers from last time.		*/
	lpBase = lpOldLast;

	/* Begin by initializing our system buffers			*/
	buffers = (struct buffer FAR *)
		KernelAlloc(Config.cfgBuffers * sizeof(struct buffer));
#ifdef DEBUG
	printf("Buffer allocated at 0x%04x:0x%04x\n",
		FP_SEG(buffers), FP_OFF(buffers));
#endif

	/* Initialize the file table					*/
	f_nodes = (struct f_node FAR *)
		KernelAlloc(Config.cfgFiles * sizeof(struct f_node));
	/* sfthead = (sfttbl FAR *)&basesft; */
	/* FCBp = (sfttbl FAR *)&FcbSft; */
	FCBp = (sfttbl FAR *)
		KernelAlloc(sizeof(sftheader)
		 + Config.cfgFiles * sizeof(sft));
	sfthead = (sfttbl FAR *)
		KernelAlloc(sizeof(sftheader)
		 + Config.cfgFiles * sizeof(sft));
#ifdef DEBUG
	printf("f_node allocated at 0x%04x:0x%04x\n",
		FP_SEG(f_nodes), FP_OFF(f_nodes));
	printf("FCB table allocated at 0x%04x:0x%04x\n",
		FP_SEG(FCBp), FP_OFF(FCBp));
	printf("sft table allocated at 0x%04x:0x%04x\n",
		FP_SEG(sfthead), FP_OFF(sfthead));
#endif

	/* Done.  Now initialize the MCB structure			*/
	/* This next line is 8086 and 80x86 real mode specific		*/
#ifdef DEBUG
	printf("Allocation completed: top at 0x%04x:0x%04x\n",
		FP_SEG(lpBase), FP_OFF(lpBase));
#endif
	first_mcb = FP_SEG(lpBase) + ((FP_OFF(lpBase) + 0x0f) >> 4);

	/* We expect ram_top as Kbytes, so convert to paragraphs */
	mcb_init((mcb FAR *)(MK_FP(first_mcb, 0)),
	 (ram_top << 6) - first_mcb - 1);
}


VOID DoConfig(VOID)
{
	COUNT nFileDesc;
	COUNT nRetCode;

	/* Check to see if we have a config.sys file.  If not, just	*/
	/* exit since we don't force the user to have one.		*/
	if((nFileDesc = dos_open((BYTE FAR *)"config.sys", 0)) < 0)
	{
#ifdef DEBUG
		printf("CONFIG.SYS not found\n");
#endif
		return;
	}

	/* Have one -- initialize.					*/
	nCfgLine = 0;
	nPass = 1;

	/* Read each line into the buffer and then parse the line,	*/
	/* do the table lookup and execute the handler for that		*/
	/* function.							*/
	FOREVER
	{
		BYTE cRead;
		COUNT nCharRead = 0;
		BOOL bEof, bEol;
		BYTE *pLine, *pTmp;
		struct table *pEntry;

		/* Initialize to a null line				*/
		szLine[0] = '\0';
		bEol = FALSE;

		/* Read a line from config				*/
		while(!bEol)
		{
			/* Read a charachter				*/
			nRetCode =
			 dos_read(nFileDesc, (BYTE FAR *)&cRead, 1);

			/* and check for EOF				*/
			if(bEof = (nRetCode != 1))
			{
				bEol = TRUE;
				break;
			}

			switch(cRead)
			{
			case '\r':
				++nCfgLine;
				bEol = TRUE;
				break;

			case '\0':
			case '\n':
				break;

			default:
				szLine[nCharRead++] = cRead;
				szLine[nCharRead] = '\0';
				if(nCharRead >= (LINESIZE - 1))
					bEol = TRUE;
				break;
			}
		}

		/* Skip leading white space and get verb.		*/
		pLine = scan(szLine, szToken);

		/* Translate the verb to lower case ...			*/
		for(pTmp = szToken; *pTmp != '\0'; pTmp++)
			*pTmp = tolower(*pTmp);

		/* If the line was blank, skip it.  Otherwise, look up	*/
		/* the verb and execute the appropriate function.	*/
		if(*szToken != '\0')
		{
			pEntry = LookUp(commands, szToken);
			if(pEntry -> pass < 0 || pEntry -> pass == nPass)
				(*(pEntry -> func))(pLine);
		}

		/* Check bEof.  If it's true, exit.  This allows	*/
		/* for a line ending with an EOF.			*/
		if(bEof)
			break;
	}
	dos_close(nFileDesc);
}


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

BYTE *GetNumArg(BYTE *pLine, COUNT *pnArg)
{
	/* Skip leading white space					*/
	pLine = skipwh(pLine);

	/* We must find a '=' because form is VERB = NUMBER		*/
	if('=' != *pLine)
	{
		CfgFailure(pLine);
		return (BYTE *)0;
	}

	/* Found '=', now look for NUMBER				*/
	pLine = skipwh(++pLine);
	if(!isnum(pLine))
	{
		CfgFailure(pLine);
		return (BYTE *)0;
	}
	return GetNumber(pLine, pnArg);
}


BYTE *GetStringArg(BYTE *pLine, BYTE *pszString)
{
	/* Skip leading white space					*/
	pLine = skipwh(pLine);

	/* We must find a '=' because form is VERB = STRING [STRINGS]	*/
	if('=' != *pLine)
	{
		CfgFailure(pLine);
		return (BYTE *)0;
	}

	/* Found '=', now look for STRING				*/
	pLine = skipwh(++pLine);

	/* just return whatever string is there, including null		*/
	return scan(pLine, pszString);
}


static VOID Buffers(BYTE *pLine)
{
	COUNT nBuffers;

	/* Get the argument						*/
	if(GetNumArg(pLine, &nBuffers) == (BYTE *)0)
		return;

	/* Got the value, assign either default or new value		*/
	Config.cfgBuffers = max(Config.cfgBuffers, nBuffers);
}


static VOID Files(BYTE *pLine)
{
	COUNT nFiles;

	/* Get the argument						*/
	if(GetNumArg(pLine, &nFiles) == (BYTE *)0)
		return;

	/* Got the value, assign either default or new value		*/
	Config.cfgFiles = max(Config.cfgFiles, nFiles);
}


static VOID InitPgm(BYTE *pLine)
{
	/* Get the string argument that represents the new init pgm	*/
	GetStringArg(pLine, Config.cfgInit);

	/* Now take whatever tail is left and add it on as a single	*/
	/* string.							*/
	strcpy(Config.cfgInitTail, pLine);

	/* and add a DOS new line just to be safe			*/
	strcat(Config.cfgInitTail, "\r\n");
}


static VOID CfgFailure(BYTE *pLine)
{
	BYTE *pTmp = szLine;

	printf("CONFIG.SYS error in line %d\n", nCfgLine);
	printf(">>>%s\n   ", pTmp);
	while(pTmp++ != pLine)
		printf(" ");
	printf("^\n");
}

static BYTE FAR *
KernelAlloc(WORD nBytes)
{
	BYTE FAR *lpAllocated = lpBase;

	lpBase += nBytes;
	return lpAllocated;
}



[ RETURN TO DIRECTORY ]