]> pd.if.org Git - mmurtl/commitdiff
autocommit for file dated 1995-02-09 16:00:18
authorRichard Burgess <>
Thu, 9 Feb 1995 16:00:18 +0000 (16:00 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 17 Oct 2016 14:03:48 +0000 (14:03 +0000)
msamples/cli/cli.c [new file with mode: 0644]

diff --git a/msamples/cli/cli.c b/msamples/cli/cli.c
new file mode 100644 (file)
index 0000000..823107c
--- /dev/null
@@ -0,0 +1,946 @@
+/* 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