--- /dev/null
+/* CLI.C V1.0 (A MMURTL Command Line Interpreter) */\r
+/* Copyright (c) 1993, 1994 R.A. Burgess */\r
+/* ALL RIGHTS RESERVED */\r
+/* Use MakeIt.Bat to build in DOS, or use CM32 and DASM:\r
+ CM32 CLI.C\r
+ CM32 DASM.ATF\r
+*/\r
+\r
+\r
+#define U32 unsigned long\r
+#define S32 long\r
+#define U16 unsigned int\r
+#define S16 int\r
+#define U8 unsigned char\r
+#define S8 char\r
+#define TRUE 1\r
+#define FALSE 0\r
+\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+\r
+/* Includes for OS public calls and structures */\r
+\r
+#include "\OSSOURCE\MKernel.h"\r
+#include "\OSSOURCE\MMemory.h"\r
+#include "\OSSOURCE\MData.h"\r
+#include "\OSSOURCE\MTimer.h"\r
+#include "\OSSOURCE\MVid.h"\r
+#include "\OSSOURCE\MKbd.h"\r
+#include "\OSSOURCE\MJob.h"\r
+#include "\OSSOURCE\MFiles.h"\r
+#include "\OSSOURCE\MStatus.h"\r
+\r
+/******************** BEGIN DATA ********************/\r
+\r
+/* Define the Foreground and Background colors */\r
+\r
+#define EDVID BLACK|BGWHITE\r
+#define NORMVID WHITE|BGBLACK\r
+#define STATVID BLACK|BGCYAN\r
+\r
+long iCol, iLine;\r
+\r
+/* aStatLine is exactly 80 characters in length */\r
+\r
+char aStatLine[] =\r
+"mm/dd/yy 00:00:00 CLI V1.0 Job Path: ";\r
+\r
+char aPath[70];\r
+long cbPath;\r
+char fUpdatePath;\r
+\r
+char sdisk, syspath[50]; /* holds system disk and system path */\r
+char hlppath[60]; /* Path to help file */\r
+char clipath[60]; /* Path to CLI */\r
+char cmdpath[60]; /* Path to command file */\r
+\r
+char aCmd[80]; /* Command line */\r
+long cbCmd = 0;\r
+\r
+unsigned char Buffer[512];\r
+unsigned char bigBuf[4096];\r
+char text[70];\r
+\r
+char ExitChar;\r
+\r
+unsigned long GPExch; /* Messaging for Main */\r
+unsigned long GPMsg[2];\r
+unsigned long GPHndl;\r
+\r
+unsigned long StatExch; /* Messaging for status task */\r
+long StatStack[256]; /* 1024 byte stack for stat task */\r
+\r
+long time, date;\r
+\r
+long JobNum;\r
+\r
+/* array of internal commands for parsing */\r
+\r
+#define NCMDS 16\r
+\r
+char paCmds[NCMDS+1][10] = {\r
+ "", /* 0 external */\r
+ "xxxxx", /* 1 - not used */\r
+ "Cls", /* 2 */\r
+ "Copy", /* 3 */\r
+ "Del", /* 4 */\r
+ "Dir", /* 5 */\r
+ "Debug", /* 6 */\r
+ "Dump", /* 7 */\r
+ "Exit", /* 8 */\r
+ "Help", /* 9 */\r
+ "MD", /* 10 */\r
+ "Monitor", /* 11 */\r
+ "Path", /* 12 */\r
+ "RD", /* 13 */\r
+ "Ren", /* 14 */\r
+ "Run", /* 15 */\r
+ "Type", /* 16 */\r
+ };\r
+\r
+#define EXTCMD 0 /* External Command */\r
+#define RESVDCMD 1\r
+#define CLSCMD 2\r
+#define COPYCMD 3\r
+#define DELCMD 4\r
+#define DIRCMD 5\r
+#define DBGCMD 6\r
+#define DUMPCMD 7\r
+#define EXITCMD 8\r
+#define HELPCMD 9\r
+#define MAKEDIR 10\r
+#define MONCMD 11\r
+#define PATHCMD 12\r
+#define REMDIR 13\r
+#define RENCMD 14\r
+#define RUNCMD 15\r
+#define TYPECMD 16\r
+\r
+\r
+long CmdNum = 0;\r
+\r
+char *apParam[13]; /* Param 0 is cmd name */\r
+long acbParam[13];\r
+#define nParamsMax 13\r
+\r
+#define ErcBadParams 80\r
+\r
+/* Directory Entry Records, 16 records 32 bytes each */\r
+\r
+struct dirstruct {\r
+ U8 Name[8];\r
+ U8 Ext[3];\r
+ U8 Attr;\r
+ U8 Rsvd[10];\r
+ U16 Time;\r
+ U16 Date;\r
+ U16 StartClstr;\r
+ U32 FileSize;\r
+ } dirent[16];\r
+\r
+/************************* BEGIN CODE ********************/\r
+\r
+/*********************************************************\r
+ This is the status task for the CLI. It updates\r
+ the status line which has the time and path.\r
+ It runs as a separate task and is started each\r
+ time the CLI is executed.\r
+*********************************************************/\r
+\r
+void StatTask(void)\r
+{\r
+ for(;;)\r
+ {\r
+ if (fUpdatePath)\r
+ {\r
+ if (cbPath > 30)\r
+ cbPath = 30;\r
+ FillData(&aStatLine[47], 30, ' ');\r
+ CopyData(aPath, &aStatLine[47], cbPath);\r
+ fUpdatePath = 0;\r
+ }\r
+\r
+\r
+ GetCMOSDate(&date);\r
+ aStatLine[0] = '0' + ((date >> 20) & 0x0f); /* month */\r
+ aStatLine[1] = '0' + ((date >> 16) & 0x0f);\r
+ aStatLine[3] = '0' + ((date >> 12) & 0x0f); /* Day */\r
+ aStatLine[4] = '0' + ((date >> 8) & 0x0f);\r
+ aStatLine[6] = '0' + ((date >> 28) & 0x0f); /* year */\r
+ aStatLine[7] = '0' + ((date >> 24) & 0x0f);\r
+\r
+ GetCMOSTime(&time);\r
+ aStatLine[10] = '0' + ((time >> 20) & 0x0f);\r
+ aStatLine[11] = '0' + ((time >> 16) & 0x0f);\r
+ aStatLine[13] = '0' + ((time >> 12) & 0x0f);\r
+ aStatLine[14] = '0' + ((time >> 8) & 0x0f);\r
+ aStatLine[16] = '0' + ((time >> 4) & 0x0f);\r
+ aStatLine[17] = '0' + (time & 0x0f);\r
+\r
+ PutVidChars(0,0, aStatLine, 80, STATVID);\r
+\r
+ Sleep(100); /* sleep 1 second */\r
+ } /* forEVER */\r
+}\r
+\r
+/*********************************************************\r
+ This displays error code text string if listed and\r
+ NON zero.\r
+*********************************************************/\r
+\r
+void CheckErc (unsigned long erc)\r
+{\r
+char *pSt;\r
+char st[40];\r
+\r
+FillData(st, 40, 0);\r
+switch (erc)\r
+{\r
+ case 0: return;\r
+ case 1: pSt = "End of file"; break;\r
+ case 4: pSt = "User cancelled"; break;\r
+ case 80: pSt = "Invalid parameters"; break;\r
+ case 101: pSt = "Out of memory (need more for this)"; break;\r
+ case 200: pSt = "Invalid filename (not correct format)"; break;\r
+ case 201: pSt = "No such drive"; break;\r
+ case 202: pSt = "The name is not a file (it's a directory)"; break;\r
+ case 203: pSt = "File doesn't exist"; break;\r
+ case 204: pSt = "Directory doesn't exist"; break;\r
+ case 205: pSt = "File is ReadOnly"; break;\r
+ case 208: pSt = "File in use"; break;\r
+ case 222: pSt = "Can't rename across drives"; break;\r
+ case 223: pSt = "Can't rename across directories"; break;\r
+ case 226: pSt = "File Already Exists (duplicate name)"; break;\r
+ case 228: pSt = "Root directory is full"; break;\r
+ case 230: pSt = "Disk is full (bummer)"; break;\r
+ case 231: pSt = "Directory is full"; break;\r
+\r
+ default:\r
+ sprintf(st, "Error %05d on last command", erc);\r
+ pSt = st;\r
+ break;\r
+}\r
+ printf("%s\r\n", pSt);\r
+}\r
+\r
+/*********************************************************\r
+ This simply does a software interrupt 03 (Debugger).\r
+*********************************************************/\r
+\r
+void GoDebug(void)\r
+{\r
+;\r
+#asm\r
+ INT 03\r
+#endasm\r
+return;\r
+}\r
+\r
+/*********************************************************\r
+ This is called to initialize the screen.\r
+ If we are returning from and external command\r
+ we do not reset the cursor position. fNew is\r
+ used to determine is we do or not.\r
+*********************************************************/\r
+\r
+void InitScreen(int fNew)\r
+{\r
+ SetNormVid(NORMVID);\r
+ GetXY(&iCol, &iLine);\r
+ if (fNew)\r
+ {\r
+ iCol = 0;\r
+ iLine = 2;\r
+ ClrScr();\r
+ }\r
+ SetXY(iCol, iLine);\r
+ PutVidChars(0,0, aStatLine, 80, STATVID);\r
+ return;\r
+}\r
+\r
+/*********************************************\r
+ This does a hex dump to the screen of a \r
+ memory area passed in by "pb"\r
+**********************************************/\r
+\r
+U32 Dump(unsigned char *pb, long cb, unsigned long addr)\r
+{\r
+U32 erc, i, j, KeyCode;\r
+unsigned char buff[17];\r
+\r
+ erc = 0;\r
+ GetXY(&iCol, &iLine);\r
+\r
+ while (cb)\r
+ {\r
+ printf("%08x ", addr);\r
+ if (cb > 15) j=16;\r
+ else j = cb;\r
+ for (i=0; i<j; i++)\r
+ {\r
+ printf("%02x ",*pb);\r
+ buff[i] = *pb++;\r
+ if (buff[i] < 0x20)\r
+ buff[i] = 0x2E;\r
+ if (buff[i] > 0x7F)\r
+ buff[i] = 0x2E;\r
+ }\r
+ buff[i+1] = 0;\r
+ printf("%s\r\n", &buff[0]);\r
+ ++iLine;\r
+ if (iLine >= 22)\r
+ {\r
+ SetXY(0,23);\r
+ printf("ESC to cancel, any other key to continue...");\r
+ ReadKbd(&KeyCode, 1); /* ReadKbd, wait */\r
+ if ((KeyCode & 0xff) == 0x1b)\r
+ {\r
+ return 4;\r
+ }\r
+ InitScreen(TRUE);\r
+ SetXY(0,1);\r
+ iLine =1;\r
+ }\r
+ if (cb > 15) cb-=16;\r
+ else cb=0;\r
+ addr+=j;\r
+ }\r
+ return erc;\r
+}\r
+\r
+/*********************************************************\r
+ This sets up to call the dump routine for each page.\r
+ This expects to find the filename in param[1].\r
+*********************************************************/\r
+\r
+long DoDump(void)\r
+{\r
+unsigned long j, k, l, erc, dret, fh;\r
+\r
+erc = 0;\r
+if ((apParam[1]) && (acbParam[1]))\r
+{\r
+ if (iLine >= 23) \r
+ {\r
+ ScrollVid(0,1,80,23,1);\r
+ SetXY(0,23);\r
+ }\r
+ erc = OpenFile(apParam[1], acbParam[1], ModeRead, 1, &fh);\r
+ if (!erc) \r
+ {\r
+ j=0; /* file lfa */\r
+ GetFileSize(fh, &k);\r
+ while ((j<k) && (!erc))\r
+ {\r
+ FillData(Buffer, 512, 0);\r
+ erc = ReadBytes (fh, Buffer, 512, &dret);\r
+ if (k-j > 512)\r
+ l = 512;\r
+ else l=k-j;\r
+ if (erc < 2)\r
+ erc = Dump(Buffer, dret, j);\r
+ j+=512;\r
+ }\r
+ CloseFile (fh);\r
+ }\r
+}\r
+else\r
+ printf("Filename not given\r\n");\r
+\r
+return erc;\r
+}\r
+\r
+/*********************************************************\r
+ This types a text file to the screen.\r
+*********************************************************/\r
+\r
+long DoType(char *pName, long cbName)\r
+{\r
+long i, j, lfa, erc, dret, fh, KeyCode;\r
+\r
+erc = 0;\r
+if ((pName) && (cbName)) \r
+{\r
+\r
+ if (iLine >= 23)\r
+ {\r
+ ScrollVid(0,1,80,23,1);\r
+ SetXY(0,23);\r
+ }\r
+ erc = OpenFile(pName, cbName, 0, 1, &fh);\r
+ if (!erc) \r
+ {\r
+ FillData(Buffer, 512, 0);\r
+ dret = 1;\r
+ while ((erc<2) && (dret)) \r
+ {\r
+ GetFileLFA(fh, &lfa);\r
+ erc = ReadBytes (fh, Buffer, 78, &dret);\r
+ i = 1;\r
+ while ((Buffer[i-1] != 0x0A) && (i < dret)) \r
+ {\r
+ i++;\r
+ }\r
+ for (j=0; j<=i; j++) \r
+ {\r
+ if ((Buffer[j] == 0x09) || (Buffer[j] == 0x0d) ||\r
+ (Buffer[j] == 0x0a))\r
+ Buffer[j] = 0x20;\r
+ }\r
+ if (dret)\r
+ {\r
+ PutVidChars(0, iLine, Buffer, i, NORMVID);\r
+ iLine++;\r
+ }\r
+ SetXY(0,iLine);\r
+ SetFileLFA(fh, lfa+i);\r
+ if (iLine >= 22)\r
+ {\r
+ SetXY(0,23);\r
+ printf("ESC to cancel, any other key to continue...");\r
+ ReadKbd(&KeyCode, 1); /* ReadKbd, wait */\r
+ if ((KeyCode & 0xff) == 0x1b)\r
+ return(4);\r
+ InitScreen(TRUE);\r
+ SetXY(0,1);\r
+ iLine =1;\r
+ }\r
+ }\r
+ printf("\r\nError: %d\r\n", erc);\r
+ CloseFile (fh);\r
+ }\r
+}\r
+else\r
+ printf("Filename not given\r\n");\r
+\r
+return erc;\r
+}\r
+\r
+/*******************************************************\r
+ This reads DOS FAT date & time and converts it into\r
+ strings with the format MM/DD/YY HH/MM/SS.\r
+ This is used by the directory listing.\r
+********************************************************/\r
+void CnvrtFATTime(U16 time,\r
+ U16 date,\r
+ char *pTimeRet,\r
+ char *pDateRet)\r
+{\r
+U32 yr,mo,da,hr,mi,se;\r
+char st[15];\r
+\r
+ yr = ((date & 0xFE00) >> 9) + 1980 - 1900;\r
+ if (yr > 99) yr -=100;\r
+ mo = (date & 0x01E0) >> 5;\r
+ da = date & 0x001F;\r
+ hr = (time & 0xF800) >> 11;\r
+ mi = (time & 0x07E0) >> 5;\r
+ se = (time & 0x001F) * 2;\r
+ sprintf(st, "%02d:%02d:%02d",hr,mi,se);\r
+ CopyData(st, pTimeRet, 8);\r
+ sprintf(st, "%02d-%02d-%02d",mo,da,yr);\r
+ CopyData(st, pDateRet, 8);\r
+\r
+}\r
+\r
+/*******************************************************\r
+ Copy a single file with overwrite checking.\r
+ Use block mode for speed. This uses a conservative\r
+ 4K buffer. THis could be made a good deal faster by\r
+ allocating a large chunk of memory and using it\r
+ instead of the 4K static buffer.\r
+********************************************************/\r
+\r
+U32 CopyFile(char *pFrom, U32 cbFrom, char *pTo, U32 cbTo)\r
+{\r
+U32 fhTo, fhFrom, bytesWant, bytesGot, bytesLeft, erc,\r
+ bytesOut, size, dLFA, KeyCode;\r
+\r
+ erc = OpenFile(pFrom, cbFrom, ModeRead, 0, &fhFrom);\r
+ if (!erc)\r
+ {\r
+ /* Check to see if it exists already */\r
+\r
+ erc = CreateFile(pTo, cbTo, 0);\r
+ if ((!erc) || (erc==ErcDupName))\r
+ {\r
+ if (erc == ErcDupName)\r
+ {\r
+ printf("File already exists. Overwrite? (Y/N)\r\n");\r
+ ReadKbd(&KeyCode, 1); /* ReadKbd, wait */\r
+ if (((KeyCode & 0xff) == 'Y') || ((KeyCode & 0xff) == 'y'))\r
+ {\r
+ erc = 0;\r
+ }\r
+ }\r
+\r
+ if (!erc)\r
+ {\r
+ erc = OpenFile(pTo, cbTo, ModeModify, 0, &fhTo);\r
+ if (!erc)\r
+ {\r
+ /* both files are open in block mode */\r
+\r
+ erc = GetFileSize(fhFrom, &size);\r
+ if (!erc)\r
+ erc = SetFileSize(fhTo, size);\r
+\r
+ dLFA = 0;\r
+ bytesLeft = size;\r
+ while ((!erc) && (bytesLeft))\r
+ { if (bytesLeft >= 4096)\r
+ bytesWant = 4096;\r
+ else\r
+ bytesWant = bytesLeft;\r
+ if (bytesWant & 511) /* handle last sector */\r
+ bytesWant += 512;\r
+ bytesWant = (bytesWant/512) * 512;\r
+ erc = ReadBlock(fhFrom, bigBuf, bytesWant,\r
+ dLFA, &bytesGot);\r
+ if (bytesGot)\r
+ {\r
+ erc = WriteBlock(fhTo, bigBuf, bytesGot,\r
+ dLFA, &bytesOut);\r
+ if (bytesLeft < bytesOut)\r
+ bytesLeft = 0;\r
+ else\r
+ bytesLeft-=bytesOut;\r
+ }\r
+ dLFA += bytesGot;\r
+ }\r
+ CloseFile(fhTo);\r
+ }\r
+ }\r
+ }\r
+ CloseFile(fhFrom);\r
+ }\r
+ return(erc);\r
+}\r
+\r
+/*********************************************************\r
+ Does a directory listing for param[1] or current path.\r
+*********************************************************/\r
+\r
+U32 DoDir(void)\r
+{\r
+U8 fDone;\r
+U32 SectNum, erc, KeyCode, i;\r
+char st[78];\r
+\r
+if (iLine >= 23)\r
+{\r
+ ScrollVid(0,1,80,23,1);\r
+ SetXY(0,23);\r
+}\r
+fDone = 0;\r
+SectNum = 0;\r
+while (!fDone)\r
+{\r
+ erc = GetDirSector(apParam[1], acbParam[1], &dirent[0], 512, SectNum);\r
+ if (!erc) \r
+ {\r
+ for (i=0; i<16; i++) \r
+ {\r
+ if (!dirent[i].Name[0])\r
+ {\r
+ erc = 1;\r
+ fDone = 1;\r
+ }\r
+ if ((dirent[i].Name[0]) && (dirent[i].Name[0] != 0xE5))\r
+ {\r
+ sprintf(st, "%8s %3s %8d xx/xx/xx xx/xx/xx %2x %04x\r\n",\r
+ dirent[i].Name,\r
+ dirent[i].Ext,\r
+ dirent[i].FileSize,\r
+ dirent[i].Attr,\r
+ dirent[i].StartClstr);\r
+ CnvrtFATTime(dirent[i].Time, dirent[i].Date, &st[33], &st[24]);\r
+ printf("%s", st);\r
+ iLine++;\r
+ if (iLine >= 22)\r
+ {\r
+ SetXY(0,23);\r
+ printf("ESC to cancel, any other key to continue...");\r
+ ReadKbd(&KeyCode, 1); /* ReadKbd, wait */\r
+ if ((KeyCode & 0xff) == 0x1b)\r
+ {\r
+ erc = 4;\r
+ fDone = TRUE;\r
+ }\r
+ InitScreen(TRUE);\r
+ SetXY(0,1);\r
+ iLine =1;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ fDone = TRUE;\r
+ SectNum++;\r
+}\r
+\r
+return(erc);\r
+}\r
+\r
+/*********************************************************\r
+ This fills in the pointers to, and sizes of, each parameter\r
+ found on the command line in the arrays apParams and\r
+ acbParams.\r
+*********************************************************/\r
+\r
+void ParseCmdLine(void)\r
+{\r
+long iCmd, iPrm, i; /* iCmd is index to aCmd */\r
+ iCmd = 0;\r
+ for (iPrm=0; iPrm<nParamsMax; iPrm++) \r
+ {\r
+ acbParam[iPrm] = 0; /* default the param to empty */\r
+ apParam[iPrm] = 0; /* Null the ptr */\r
+ if (iCmd < cbCmd)\r
+ {\r
+ if (!isspace(aCmd[iCmd])) \r
+ {\r
+ apParam[iPrm] = &aCmd[iCmd++]; /* ptr to param */\r
+ i = 1;\r
+ while ((iCmd < cbCmd) && (!isspace(aCmd[iCmd])))\r
+ {\r
+ i++;\r
+ iCmd++;\r
+ }\r
+ acbParam[iPrm] = i; /* size of param */\r
+ }\r
+ while ((iCmd < cbCmd) && (isspace(aCmd[iCmd])))\r
+ iCmd++;\r
+ }\r
+ }\r
+}\r
+\r
+/*************************************************\r
+ This opens and parses Commands.CLI in the system\r
+ directory and looks for the command name in\r
+ apParam[0]. If it finds it, it places the full\r
+ filespec for the run file in "runfile" for the\r
+ caller, then fixes up the aCmd command line\r
+ just as if it had come from the user.\r
+ The format for a line entry in Commands.CLI is:\r
+ name fullspec param param param...\r
+**************************************************/\r
+\r
+long GetCLICommand(char *runfile)\r
+{\r
+long i, j, k;\r
+FILE *f;\r
+char rawline[90]; /* used to build a pseudo command line */\r
+char cmdline[90]; /* used to build a pseudo command line */\r
+char fdone;\r
+\r
+ cmdline[0] = 0;\r
+\r
+ f = fopen(cmdpath, "r");\r
+ if (f)\r
+ {\r
+ fdone = 0;\r
+ while (!fdone)\r
+ {\r
+ if (fgets(rawline, 89, f))\r
+ {\r
+ if (rawline[0] == ';') /* a comment line */\r
+ continue;\r
+ j = CompareNCS(apParam[0], rawline, acbParam[0]);\r
+ if (j == -1)\r
+ { /* we found a match for the command */\r
+ /* Move the command name into the command line */\r
+ i = 0; /* Index into rawline */\r
+ j = 0; /* Index into cmdline we are building */\r
+ k = 0; /* Index into runfile name we return to caller */\r
+ while (!(isspace(rawline[i])))\r
+ cmdline[j++] = rawline[i++];\r
+ /* follwed by a space */\r
+ cmdline[j++] = ' ';\r
+\r
+ /* skip whitespace in rawline */\r
+ while (isspace(rawline[i]))\r
+ i++;\r
+\r
+ /* now move runfile name */\r
+ while (!(isspace(rawline[i])))\r
+ runfile[k++] = rawline[i++];\r
+ runfile[k] = 0; /* null terminte */\r
+\r
+ /* skip whitespace in rawline */\r
+ while (isspace(rawline[i]))\r
+ i++;\r
+ /* now move arguments if any, and LF */\r
+ while (rawline[i])\r
+ cmdline[j++] = rawline[i++];\r
+ cmdline[j] = 0;\r
+\r
+ /* Move cmd line we built to real cmd line */\r
+ strcpy(aCmd, cmdline);\r
+ cbCmd = strlen(aCmd);\r
+ return(1); /* tell em we got it! */\r
+ }\r
+ }\r
+ else\r
+ fdone = 1;\r
+ }\r
+ }\r
+ else\r
+ printf("Commands.CLI not found.\r\n");\r
+\r
+ return(0);\r
+}\r
+\r
+\r
+/**************************************************\r
+ When a command is specified to the CLI and it\r
+ is not an internal command, we first look for\r
+ a .RUN file in the current path. If we don't\r
+ find one, we go to the system directory, if\r
+ it's not there, we then go to COMMANDS.CLI\r
+ and search it line by line to see if a run\r
+ file is specified there. If so, we set the\r
+ command line with everything after the runfile\r
+ specified and try to execute it.\r
+***************************************************/\r
+\r
+void FindRunFile(void)\r
+{\r
+char runfile[80];\r
+long i, erc, fh;\r
+\r
+ /* Try to find in current path */\r
+\r
+ CopyData(apParam[0], runfile, acbParam[0]);\r
+ runfile[acbParam[0]] = 0;\r
+ strcat(runfile, ".RUN");\r
+\r
+ erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
+ if (!erc)\r
+ { /* found a run file in sys directory */\r
+ CloseFile(fh);\r
+ SetCmdLine(aCmd, cbCmd);\r
+ erc = Chain(runfile, strlen(runfile), 0);\r
+ }\r
+ else /* Try to find in System directory */\r
+ {\r
+ strcpy(runfile, syspath);\r
+ i = strlen(runfile);\r
+ CopyData(apParam[0], &runfile[i], acbParam[0]);\r
+ runfile[acbParam[0]+i] = 0; /* null terminate */\r
+ strcat(runfile, ".RUN");\r
+ erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
+ if (!erc)\r
+ { /* found a run file */\r
+ CloseFile(fh);\r
+ SetCmdLine(aCmd, cbCmd);\r
+ erc = Chain(runfile, strlen(runfile), 0);\r
+ }\r
+ /* now we call GetCLICommand as a last resort */\r
+ else if (GetCLICommand(runfile))\r
+ {\r
+ erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
+ if (!erc)\r
+ { /* found a run file */\r
+ CloseFile(fh);\r
+ SetCmdLine(aCmd, cbCmd);\r
+ erc = Chain(runfile, strlen(runfile), 0);\r
+ }\r
+ }\r
+ }\r
+ printf("Command not found\r\n");\r
+}\r
+\r
+/**********************************************\r
+ Main function entry point.\r
+ Note: No params to CLI.\r
+***********************************************/\r
+\r
+void main(void)\r
+{\r
+unsigned long erc, i, j, fh;\r
+\r
+ erc = AllocExch(&StatExch);\r
+ erc = AllocExch(&GPExch);\r
+\r
+ SpawnTask(&StatTask, 24, 0, &StatStack[255], 0);\r
+\r
+ GetJobNum(&JobNum);\r
+ sprintf(&aStatLine[37], "%02d", JobNum);\r
+\r
+ SetJobName("CLI V1.0", 8);\r
+\r
+ /* Get system disk and set up path names for\r
+ cli, command file, and help file.\r
+ */\r
+\r
+ GetSystemDisk(&sdisk);\r
+ sdisk &= 0x7F;\r
+ sdisk += 0x41; /* 0=A, 1=B, 2=C etc. */\r
+ syspath[0] = sdisk;\r
+ syspath[1] = ':';\r
+ syspath[2] = 0;\r
+ strcat(syspath, "\\MMSYS\\");\r
+\r
+ strcpy(clipath, syspath);\r
+ strcat(clipath,"CLI.RUN");\r
+\r
+ strcpy(cmdpath, syspath);\r
+ strcat(cmdpath,"COMMANDS.CLI");\r
+\r
+ strcpy(hlppath, syspath);\r
+ strcat(hlppath,"HELP.CLI");\r
+\r
+ /* If a path was already set we assume that we are re-loading\r
+ after an external command has been run. We do not\r
+ want to reset the screen completely so the user can\r
+ see anything the external command left on the screen.\r
+ */\r
+\r
+ cbPath = 0;\r
+ GetPath(JobNum, aPath, &cbPath);\r
+ if (cbPath)\r
+ {\r
+ GetXY(&iCol, &iLine);\r
+ if (iLine == 0) /* under status line */\r
+ iLine = 1;\r
+ InitScreen(FALSE);\r
+ SetXY(0, iLine);\r
+ }\r
+ else\r
+ {\r
+ strcpy (aPath, syspath);\r
+ cbPath = strlen(syspath);\r
+ SetPath(syspath, strlen(syspath));\r
+ InitScreen(TRUE);\r
+ }\r
+\r
+ fUpdatePath = 1;\r
+\r
+ while (1)\r
+ {\r
+ FillData(aCmd, 79, ' ');\r
+ aCmd[79] = 0;\r
+ cbCmd = 0;\r
+ SetXY(0, iLine);\r
+ TTYOut (">", 1, NORMVID);\r
+ EditLine(aCmd, cbCmd, 79, &cbCmd, &ExitChar, EDVID);\r
+ TTYOut ("\r\n", 2, NORMVID);\r
+ GetXY(&iCol, &iLine);\r
+\r
+ acbParam[0] = 0;\r
+ apParam[0] = 0;\r
+ CmdNum = 0;\r
+\r
+ if (ExitChar == 0x0d)\r
+ ParseCmdLine(); /* set up all params */\r
+\r
+ if ((acbParam[0]) && (apParam[0]))\r
+ { /* It's a command! */\r
+\r
+ i = 1;\r
+ while (i <= NCMDS)\r
+ {\r
+ j = strlen(paCmds[i]);\r
+ if ((acbParam[0] == j) &&\r
+ (CompareNCS(apParam[0], paCmds[i], j) == -1))\r
+ {\r
+ CmdNum = i;\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ erc = 0;\r
+ switch (CmdNum)\r
+ {\r
+ case EXTCMD: /* external command */\r
+ SetExitJob(clipath, strlen(clipath));\r
+ FindRunFile();\r
+ break;\r
+ case CLSCMD:\r
+ InitScreen(TRUE);\r
+ break;\r
+ case COPYCMD:\r
+ if ((acbParam[1]) && (acbParam[2]))\r
+ erc = CopyFile(apParam[1], acbParam[1],\r
+ apParam[2], acbParam[2]);\r
+ else erc = ErcBadParams;\r
+ break;\r
+ case DELCMD:\r
+ erc = OpenFile(apParam[1], acbParam[1], 1, 0, &fh);\r
+ if (!erc)\r
+ erc = DeleteFile(fh);\r
+ if (!erc)\r
+ printf("Done.\r\n");\r
+ break;\r
+ case DIRCMD:\r
+ erc = DoDir();\r
+ break;\r
+ case DBGCMD:\r
+ GoDebug();\r
+ break;\r
+ case DUMPCMD:\r
+ erc = DoDump();\r
+ break;\r
+ case EXITCMD:\r
+ SetExitJob("", 0);\r
+ ExitJob(0);\r
+ break;\r
+ case HELPCMD:\r
+ erc = DoType(hlppath, strlen(hlppath));\r
+ break;\r
+ case MAKEDIR:\r
+ erc = CreateDir(apParam[1], acbParam[1]);\r
+ break;\r
+ case MONCMD:\r
+ erc = Request("KEYBOARD", 4, GPExch, &GPHndl, 0,\r
+ 0, 0, 0, 0, 1, 0, 0);\r
+ erc = WaitMsg(GPExch, GPMsg);\r
+ SetVidOwner(1);\r
+ break;\r
+ case PATHCMD:\r
+ erc = SetPath(apParam[1], acbParam[1]);\r
+ if (!erc)\r
+ erc = GetPath(JobNum, aPath, &cbPath);\r
+ fUpdatePath = 1;\r
+ break;\r
+ case REMDIR:\r
+ erc = DeleteDir(apParam[1], acbParam[1]);\r
+ break;\r
+ case RENCMD:\r
+ if ((acbParam[1]) && (acbParam[2]))\r
+ erc = RenameFile(apParam[1], acbParam[1],\r
+ apParam[2], acbParam[2]);\r
+ else erc = ErcBadParams;\r
+ break;\r
+ case RUNCMD:\r
+ if (acbParam[1])\r
+ {\r
+ i = 2;\r
+ while (aCmd[i] != ' ')\r
+ i++;\r
+ SetCmdLine(&aCmd[i], cbCmd-i);\r
+ SetExitJob(clipath, strlen(clipath));\r
+ erc = Chain(apParam[1], acbParam[1], 0);\r
+ }\r
+ break;\r
+ case TYPECMD:\r
+ erc = DoType(apParam[1], acbParam[1]);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ CheckErc(erc);\r
+ }\r
+\r
+ GetXY(&iCol, &iLine);\r
+ if (iLine >= 23)\r
+ {\r
+ ScrollVid(0,1,80,23,1);\r
+ SetXY(0,23);\r
+ }\r
+ }\r
+}\r