📄 cli.c
字号:
/* CLI.C (A MMURTL Command Line Interpreter) */
/* Copyright (c) 1993, 1994 R.A. Burgess */
/* All Rights Reserved */
#define U32 unsigned long
#define S32 long
#define U16 unsigned int
#define S16 int
#define U8 unsigned char
#define S8 char
#define TRUE 1
#define FALSE 0
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* Includes for OS public calls and structures */
#include "MKernel.h"
#include "MMemory.h"
#include "MData.h"
#include "MTimer.h"
#include "MVid.h"
#include "MKbd.h"
#include "MJob.h"
#include "MFiles.h"
/************************* BEGIN Data ********************/
/************************* BEGIN Data ********************/
/************************* BEGIN Data ********************/
/* Define the Foreground and Background colors */
#define EDVID BLACK|BGWHITE
#define NORMVID WHITE|BGBLACK
#define STATVID BLACK|BGCYAN
long iCol, iLine;
char aStatLine[] =
"mm/dd/yy 00:00:00 CLI V0.8x Job Path: ";
char aPath[70];
long cbPath;
char fUpdatePath;
long olCmd[50]; /* offset in tmp file to last 50 commands */
char aCmd[80];
long cbCmd = 0;
unsigned char Buffer[512];
char text[70];
char ExitChar;
unsigned long GPExch; /* Messaging for main */
unsigned long GPMsg[2];
unsigned long GPHndl;
unsigned long StatExch; /* Messaging for status task */
long StatStack[256]; /* 1024 byte stack for stat task */
long time, date;
long JobNum;
char paCmds[15][10] = {
"", /* 0 external */
"xxxxx", /* 1 - not used */
"Cls", /* 2 */
"Copy", /* 3 */
"Del", /* 4 */
"Dir", /* 5 */
"Debug", /* 6 */
"Dump", /* 7 */
"Exit", /* 8 */
"Help", /* 9 */
"Monitor", /* 10 */
"Path", /* 11 */
"Ren", /* 12 */
"Run", /* 13 */
"Type", /* 14 */
};
#define NCMDS 14
#define EXTCMD 0 /* External Command */
#define RESVDCMD 1
#define CLSCMD 2
#define COPYCMD 3
#define DELCMD 4
#define DIRCMD 5
#define DBGCMD 6
#define DUMPCMD 7
#define EXITCMD 8
#define HELPCMD 9
#define MONCMD 10
#define PATHCMD 11
#define RENCMD 12
#define RUNCMD 13
#define TYPECMD 14
long CmdNum = 0;
char *apParam[13]; /* Param 0 is cmd name */
long acbParam[13];
#define nParamsMax 13
#define ErcBadParams 80
/* Directory Entry Records, 16 records 32 bytes each */
struct dirstruct {
U8 Name[8];
U8 Ext[3];
U8 Attr;
U8 Rsvd[10];
U16 Time;
U16 Date;
U16 StartClstr;
U32 FileSize;
} dirent[16];
/************************* BEGIN CODE ********************/
/************************* BEGIN CODE ********************/
/************************* BEGIN CODE ********************/
/*********************************************************
This is the status task for the CLI. It updates
the status line which has the time and path.
*********************************************************/
void StatTask(void)
{
for(;;) {
if (fUpdatePath) {
if (cbPath > 30)
cbPath = 30;
FillData(&aStatLine[47], 30, ' ');
CopyData(aPath, &aStatLine[47], cbPath);
fUpdatePath = 0;
}
GetCMOSDate(&date);
aStatLine[0] = '0' + ((date >> 20) & 0x0f); /* month */
aStatLine[1] = '0' + ((date >> 16) & 0x0f);
aStatLine[3] = '0' + ((date >> 12) & 0x0f); /* Day */
aStatLine[4] = '0' + ((date >> 8) & 0x0f);
aStatLine[6] = '0' + ((date >> 28) & 0x0f); /* year */
aStatLine[7] = '0' + ((date >> 24) & 0x0f);
GetCMOSTime(&time);
aStatLine[10] = '0' + ((time >> 20) & 0x0f);
aStatLine[11] = '0' + ((time >> 16) & 0x0f);
aStatLine[13] = '0' + ((time >> 12) & 0x0f);
aStatLine[14] = '0' + ((time >> 8) & 0x0f);
aStatLine[16] = '0' + ((time >> 4) & 0x0f);
aStatLine[17] = '0' + (time & 0x0f);
PutVidChars(0,0, aStatLine, 80, STATVID);
Sleep(100); /* sleep 1 second */
} /* for EVER */
}
/*********************************************************
This displays error code text string if listed and
NON zero.
*********************************************************/
void CheckErc (unsigned long erc)
{
char *pSt;
char st[40]
long i;
FillData(st, 40, 0);
switch (erc) {
case 0: return;
case 1: pSt = "End of file"; break;
case 4: pSt = "User cancelled"; break;
case 200: pSt = "Invalid filename (not correct format)"; break;
case 201: pSt = "No such drive"; break;
case 202: pSt = "The name is not a file (it's a directory)"; break;
case 203: pSt = "File doesn't exist"; break;
case 204: pSt = "Directory doesn't exist"; break;
case 205: pSt = "File is ReadOnly"; break;
case 208: pSt = "File in use"; break;
case 222: pSt = "Can't rename across drives"; break;
case 223: pSt = "Can't rename across directories"; break;
case 228: pSt = "Root directory is full"; break;
case 230: pSt = "Disk is full (bummer)"; break;
case 231: pSt = "Directory is full"; break;
default:
sprintf(st, "Error %05d on last command", erc);
pSt = st;
break;
}
printf("%s\r\n", pSt);
}
/*********************************************************
This simply does a software interrupt 03 (Debugger).
*********************************************************/
void GoDebug(void)
{
;
#asm
INT 03
#endasm
return;
}
/*********************************************************
This is called to initialize the screen.
*********************************************************/
void InitScreen(void)
{
SetNormVid(NORMVID);
ClrScr();
PutVidChars(0,0, aStatLine, 80, STATVID);
SetXY(0,2);
return;
}
/*********************************************/
U32 Dump(unsigned char *pb, long cb, unsigned long addr)
{
U32 erc, i, j, KeyCode;
unsigned char buff[17];
erc = 0;
GetXY(&iCol, &iLine);
while (cb) {
printf("%08x ", addr);
if (cb > 15) j=16;
else j = cb;
for (i=0; i<j; i++) {
printf("%02x ",*pb);
buff[i] = *pb++;
if (buff[i] < 0x20)
buff[i] = 0x2E;
if (buff[i] > 0x7F)
buff[i] = 0x2E;
}
buff[i+1] = 0;
printf("%s\r\n", &buff[0]);
++iLine;
if (iLine >= 22) {
SetXY(0,23);
printf("ESC to cancel, any other key to continue...");
ReadKbd(&KeyCode, 1); /* ReadKbd, wait */
if ((KeyCode & 0xff) == 0x1b) {
return 4;
}
InitScreen();
SetXY(0,1);
iLine =1;
}
if (cb > 15) cb-=16;
else cb=0;
addr+=j;
}
return erc;
}
/*********************************************************
This sets up to call the dump routine for each page.
This expects to find the filename in param[1].
*********************************************************/
long DoDump(void)
{
unsigned long i, j, k, l, erc, c1, dret, fh;
erc = 0;
if ((apParam[1]) && (acbParam[1])) {
if (iLine >= 23) {
ScrollVid(0,1,80,23,1);
SetXY(0,23);
}
erc = OpenFile(apParam[1], acbParam[1], 0, 1, &fh);
if (!erc) {
j=0; /* file lfa */
GetFileSize(fh, &k);
while ((j<k) && (!erc)) {
FillData(Buffer, 512, 0);
erc = ReadBytes (fh, Buffer, 512, &dret);
if (k-j > 512)
l = 512;
else l=k-j;
if (erc < 2)
erc = Dump(Buffer, dret, j);
j+=512;
}
CloseFile (fh);
}
}
else
printf("Filename not given\r\n");
return erc;
}
/*********************************************************
This types a text file to the screen.
*********************************************************/
long DoType(char *pName, long cbName)
{
long i, j, lfa, erc, dret, fh, KeyCode;
erc = 0;
if ((pName) && (cbName)) {
if (iLine >= 23) {
ScrollVid(0,1,80,23,1);
SetXY(0,23);
}
erc = OpenFile(pName, cbName, 0, 1, &fh);
if (!erc) {
FillData(Buffer, 512, 0);
dret = 1;
while ((erc<2) && (dret)) {
GetFileLFA(fh, &lfa);
erc = ReadBytes (fh, Buffer, 78, &dret);
i = 1;
while ((Buffer[i-1] != 0x0A) && (i < dret)) {
i++;
}
for (j=0; j<=i; j++) {
if ((Buffer[j] == 0x09) || (Buffer[j] == 0x0d) ||
(Buffer[j] == 0x0a))
Buffer[j] = 0x20;
}
if (dret) {
PutVidChars(0, iLine, Buffer, i, NORMVID);
iLine++;
}
SetXY(0,iLine);
SetFileLFA(fh, lfa+i);
if (iLine >= 22) {
SetXY(0,23);
printf("ESC to cancel, any other key to continue...");
ReadKbd(&KeyCode, 1); /* ReadKbd, wait */
if ((KeyCode & 0xff) == 0x1b)
return(4);
InitScreen();
SetXY(0,1);
iLine =1;
}
}
printf("\r\nError: %d\r\n", erc);
CloseFile (fh);
}
}
else
printf("Filename not given\r\n");
return erc;
}
/*******************************************************
This converts DOS FAT date & time and converts it into
strings with the format MM/DD/YY HH/MM/SS.
********************************************************/
void CnvrtFATTime(U16 time,
U16 date,
char *pTimeRet,
char *pDateRet)
{
U32 yr,mo,da,hr,mi,se;
char st[15];
yr = ((date & 0xFE00) >> 9) + 1980 - 1900;
if (yr > 99) yr -=100;
mo = (date & 0x01E0) >> 5;
da = date & 0x001F;
hr = (time & 0xF800) >> 11;
mi = (time & 0x07E0) >> 5;
se = (time & 0x001F) * 2;
sprintf(st, "%02d:%02d:%02d",hr,mi,se);
CopyData(st, pTimeRet, 8);
sprintf(st, "%02d-%02d-%02d",mo,da,yr);
CopyData(st, pDateRet, 8);
}
/*********************************************************
Does a directory listing for param 1 or current path.
*********************************************************/
U32 DoDir(void)
{
U8 fDone;
U32 SectNum, erc, KeyCode, i;
char st[78];
if (iLine >= 23) {
ScrollVid(0,1,80,23,1);
SetXY(0,23);
}
fDone = 0;
SectNum = 0;
while (!fDone) {
erc = GetDirSector(apParam[1], acbParam[1], &dirent[0], 512, SectNum);
if (!erc) {
for (i=0; i<16; i++) {
if (!dirent[i].Name[0])
erc = 1;
if ((dirent[i].Name[0]) && (dirent[i].Name[0] != 0xE5)) {
sprintf(st, "%8s %3s %8d xx/xx/xx xx/xx/xx %2x %04x\r\n",
dirent[i].Name,
dirent[i].Ext,
dirent[i].FileSize,
dirent[i].Attr,
dirent[i].StartClstr);
CnvrtFATTime(dirent[i].Time, dirent[i].Date, &st[33], &st[24]);
printf("%s", st);
iLine++;
if (iLine >= 22) {
SetXY(0,23);
printf("ESC to cancel, any other key to continue...");
ReadKbd(&KeyCode, 1); /* ReadKbd, wait */
if ((KeyCode & 0xff) == 0x1b) {
erc = 4;
fDone = TRUE;
}
InitScreen();
SetXY(0,1);
iLine =1;
}
}
}
}
else
fDone = TRUE;
SectNum++;
}
return(erc);
}
/*********************************************************
This Fills in the ptrs to and sizes of each parameter
found on the command line in the arrays apParams and
acbParams.
*********************************************************/
void ParseCmdLine(void)
{
long iCmd, iPrm, i; /* iCmd is index to aCmd */
iCmd = 0;
for (iPrm=0; iPrm<nParamsMax; iPrm++) {
acbParam[iPrm] = 0; /* default the param to empty */
apParam[iPrm] = 0; /* Null the ptr */
if (iCmd < cbCmd) {
if (!isspace(aCmd[iCmd])) {
apParam[iPrm] = &aCmd[iCmd++]; /* ptr to param */
i = 1;
while ((iCmd < cbCmd) && (!isspace(aCmd[iCmd]))) {
i++;
iCmd++;
}
acbParam[iPrm] = i; /* size of param */
}
while ((iCmd < cbCmd) && (isspace(aCmd[iCmd])))
iCmd++;
}
}
}
void main(void)
{
unsigned long erc, i, j, fh;
erc = AllocExch(&StatExch);
erc = AllocExch(&GPExch);
InitScreen();
SpawnTask(&StatTask, 24, 0, &StatStack[255], 0);
SetExitJob("C:\\MMURTL\\CLI.RUN", 17);
SetPath("C:\\MMURTL\\", 10);
GetJobNum(&JobNum);
sprintf(&aStatLine[37], "%02d", JobNum);
GetPath(JobNum, aPath, &cbPath);
fUpdatePath = 1;
iLine = 1;
while (1) {
FillData(aCmd, 79, ' ');
aCmd[79] = 0;
cbCmd = 0;
SetXY(0, iLine);
TTYOut (">", 1, NORMVID);
EditLine(aCmd, cbCmd, 79, &cbCmd, &ExitChar, EDVID);
TTYOut ("\r\n", 2, NORMVID);
GetXY(&iCol, &iLine);
acbParam[0] = 0;
apParam[0] = 0;
CmdNum = 0;
if ((ExitChar == 0x01) || (ExitChar == 0x81)) {
}
if (ExitChar == 0x0d)
ParseCmdLine(); /* set up all params */
if ((acbParam[0]) && (apParam[0])) { /* It's a command! */
i = 1;
while (i <= NCMDS) {
j = strlen(paCmds[i]);
if ((acbParam[0] == j) &&
(CompareNCS(apParam[0], paCmds[i], j) == -1))
{
CmdNum = i;
break;
}
i++;
}
erc = 0;
switch (CmdNum) {
case EXTCMD: /* external command */
printf("Command not found\r\n");
break;
case CLSCMD:
InitScreen();
break;
case COPYCMD:
break;
case DELCMD:
erc = OpenFile(apParam[1], acbParam[1], 1, 0, &fh);
if (!erc)
erc = DeleteFile(fh);
if (!erc)
printf("Done.\r\n");
break;
case DIRCMD:
erc = DoDir();
break;
case DBGCMD:
GoDebug();
break;
case DUMPCMD:
erc = DoDump();
break;
case EXITCMD:
SetExitJob("", 0);
ExitJob(0);
break;
case HELPCMD:
erc = DoType("C:\\MMURTL\\CLI.Hlp", 17);
break;
case MONCMD:
erc = Request("KEYBOARD", 4, GPExch, &GPHndl, 0,
0, 0, 0, 0, 1, 0, 0);
erc = WaitMsg(GPExch, GPMsg);
SetVidOwner(1);
break;
case PATHCMD:
erc = SetPath(apParam[1], acbParam[1]);
if (!erc)
erc = GetPath(JobNum, aPath, &cbPath);
fUpdatePath = 1;
break;
case RENCMD:
if ((acbParam[1]) && (acbParam[2]))
erc = RenameFile(apParam[1], acbParam[1],
apParam[2], acbParam[2]);
else erc = ErcBadParams;
break;
case RUNCMD:
if (acbParam[1]) {
SetCmdLine(aCmd, cbCmd);
SetExitJob("C:\\MMURTL\\CLI.RUN", 17);
erc = Chain(apParam[1], acbParam[1], 0);
}
break;
case TYPECMD:
erc = DoType(apParam[1], acbParam[1]);
break;
default:
break;
}
CheckErc(erc);
}
GetXY(&iCol, &iLine);
if (iLine >= 23) {
ScrollVid(0,1,80,23,1);
SetXY(0,23);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -