]> pd.if.org Git - mmurtl/blob - msamples/cli/cli.c
autocommit for file dated 1995-02-09 16:00:18
[mmurtl] / msamples / cli / cli.c
1 /* CLI.C V1.0  (A MMURTL Command Line Interpreter) */\r
2 /*  Copyright (c) 1993, 1994 R.A. Burgess     */\r
3 /*         ALL RIGHTS RESERVED                */\r
4 /* Use MakeIt.Bat to build in DOS, or use CM32 and DASM:\r
5    CM32 CLI.C\r
6    CM32 DASM.ATF\r
7 */\r
8 \r
9 \r
10 #define U32 unsigned long\r
11 #define S32 long\r
12 #define U16 unsigned int\r
13 #define S16 int\r
14 #define U8 unsigned char\r
15 #define S8 char\r
16 #define TRUE 1\r
17 #define FALSE 0\r
18 \r
19 \r
20 #include <stdio.h>\r
21 #include <string.h>\r
22 #include <ctype.h>\r
23 \r
24 /* Includes for OS public calls and structures */\r
25 \r
26 #include "\OSSOURCE\MKernel.h"\r
27 #include "\OSSOURCE\MMemory.h"\r
28 #include "\OSSOURCE\MData.h"\r
29 #include "\OSSOURCE\MTimer.h"\r
30 #include "\OSSOURCE\MVid.h"\r
31 #include "\OSSOURCE\MKbd.h"\r
32 #include "\OSSOURCE\MJob.h"\r
33 #include "\OSSOURCE\MFiles.h"\r
34 #include "\OSSOURCE\MStatus.h"\r
35 \r
36 /******************** BEGIN DATA ********************/\r
37 \r
38 /* Define the Foreground and Background colors */\r
39 \r
40 #define EDVID   BLACK|BGWHITE\r
41 #define NORMVID WHITE|BGBLACK\r
42 #define STATVID BLACK|BGCYAN\r
43 \r
44 long iCol, iLine;\r
45 \r
46 /* aStatLine is exactly 80 characters in length */\r
47 \r
48 char aStatLine[] =\r
49 "mm/dd/yy  00:00:00  CLI  V1.0    Job     Path:                                  ";\r
50 \r
51 char aPath[70];\r
52 long cbPath;\r
53 char fUpdatePath;\r
54 \r
55 char sdisk, syspath[50];        /* holds system disk and system path */\r
56 char hlppath[60];                       /* Path to help file */\r
57 char clipath[60];                       /* Path to CLI */\r
58 char cmdpath[60];                       /* Path to command file */\r
59 \r
60 char aCmd[80];                          /* Command line */\r
61 long cbCmd = 0;\r
62 \r
63 unsigned char Buffer[512];\r
64 unsigned char bigBuf[4096];\r
65 char text[70];\r
66 \r
67 char ExitChar;\r
68 \r
69 unsigned long GPExch;           /* Messaging for Main */\r
70 unsigned long GPMsg[2];\r
71 unsigned long GPHndl;\r
72 \r
73 unsigned long StatExch; /* Messaging for status task */\r
74 long StatStack[256];    /* 1024 byte stack for stat task */\r
75 \r
76 long time, date;\r
77 \r
78 long JobNum;\r
79 \r
80 /* array of internal commands for parsing */\r
81 \r
82 #define NCMDS 16\r
83 \r
84 char paCmds[NCMDS+1][10] = {\r
85         "",                                     /* 0 external */\r
86         "xxxxx",                        /* 1 - not used */\r
87         "Cls",                          /* 2  */\r
88         "Copy",                         /* 3  */\r
89         "Del",                          /* 4  */\r
90         "Dir",                          /* 5  */\r
91         "Debug",                        /* 6  */\r
92         "Dump",                         /* 7  */\r
93         "Exit",                         /* 8  */\r
94         "Help",                         /* 9  */\r
95         "MD",                           /* 10 */\r
96         "Monitor",                      /* 11 */\r
97         "Path",                         /* 12 */\r
98         "RD",                           /* 13 */\r
99         "Ren",                          /* 14 */\r
100         "Run",                          /* 15 */\r
101         "Type",                         /* 16 */\r
102         };\r
103 \r
104 #define EXTCMD 0                /* External Command */\r
105 #define RESVDCMD 1\r
106 #define CLSCMD  2\r
107 #define COPYCMD 3\r
108 #define DELCMD  4\r
109 #define DIRCMD  5\r
110 #define DBGCMD  6\r
111 #define DUMPCMD 7\r
112 #define EXITCMD 8\r
113 #define HELPCMD 9\r
114 #define MAKEDIR 10\r
115 #define MONCMD  11\r
116 #define PATHCMD 12\r
117 #define REMDIR  13\r
118 #define RENCMD  14\r
119 #define RUNCMD  15\r
120 #define TYPECMD 16\r
121 \r
122 \r
123 long CmdNum = 0;\r
124 \r
125 char *apParam[13];              /* Param 0 is cmd name */\r
126 long acbParam[13];\r
127 #define nParamsMax 13\r
128 \r
129 #define ErcBadParams 80\r
130 \r
131 /* Directory Entry Records, 16 records 32 bytes each */\r
132 \r
133 struct dirstruct {\r
134         U8  Name[8];\r
135         U8  Ext[3];\r
136         U8  Attr;\r
137         U8  Rsvd[10];\r
138         U16 Time;\r
139         U16 Date;\r
140         U16 StartClstr;\r
141         U32 FileSize;\r
142         } dirent[16];\r
143 \r
144 /************************* BEGIN CODE ********************/\r
145 \r
146 /*********************************************************\r
147     This is the status task for the CLI.  It updates\r
148     the status line which has the time and path.\r
149     It runs as a separate task and is started each\r
150     time the CLI is executed.\r
151 *********************************************************/\r
152 \r
153 void StatTask(void)\r
154 {\r
155         for(;;)\r
156         {\r
157                 if (fUpdatePath)\r
158                 {\r
159                         if (cbPath > 30)\r
160                                 cbPath = 30;\r
161                         FillData(&aStatLine[47], 30, ' ');\r
162                         CopyData(aPath, &aStatLine[47], cbPath);\r
163                         fUpdatePath = 0;\r
164                 }\r
165 \r
166 \r
167                 GetCMOSDate(&date);\r
168                 aStatLine[0] = '0' + ((date >> 20) & 0x0f); /* month */\r
169                 aStatLine[1] = '0' + ((date >> 16) & 0x0f);\r
170                 aStatLine[3] = '0' + ((date >> 12) & 0x0f); /* Day */\r
171                 aStatLine[4] = '0' + ((date >> 8)  & 0x0f);\r
172                 aStatLine[6] = '0' + ((date >> 28) & 0x0f); /* year */\r
173                 aStatLine[7] = '0' + ((date >> 24) & 0x0f);\r
174 \r
175                 GetCMOSTime(&time);\r
176                 aStatLine[10] = '0' + ((time >> 20) & 0x0f);\r
177                 aStatLine[11] = '0' + ((time >> 16) & 0x0f);\r
178                 aStatLine[13] = '0' + ((time >> 12) & 0x0f);\r
179                 aStatLine[14] = '0' + ((time >> 8) & 0x0f);\r
180                 aStatLine[16] = '0' + ((time >> 4) & 0x0f);\r
181                 aStatLine[17] = '0' + (time & 0x0f);\r
182 \r
183                 PutVidChars(0,0, aStatLine, 80, STATVID);\r
184 \r
185                 Sleep(100);     /* sleep 1 second */\r
186         } /* forEVER */\r
187 }\r
188 \r
189 /*********************************************************\r
190   This displays error code text string if listed and\r
191   NON zero.\r
192 *********************************************************/\r
193 \r
194 void CheckErc (unsigned long erc)\r
195 {\r
196 char *pSt;\r
197 char st[40];\r
198 \r
199 FillData(st, 40, 0);\r
200 switch (erc)\r
201 {\r
202         case 0: return;\r
203         case 1:   pSt = "End of file";          break;\r
204         case 4:   pSt = "User cancelled";               break;\r
205         case 80:  pSt = "Invalid parameters";    break;\r
206         case 101: pSt = "Out of memory (need more for this)";    break;\r
207         case 200: pSt = "Invalid filename (not correct format)";         break;\r
208         case 201: pSt = "No such drive";        break;\r
209         case 202: pSt = "The name is not a file (it's a directory)"; break;\r
210         case 203: pSt = "File doesn't exist";   break;\r
211         case 204: pSt = "Directory doesn't exist";      break;\r
212         case 205: pSt = "File is ReadOnly"; break;\r
213         case 208: pSt = "File in use"; break;\r
214         case 222: pSt = "Can't rename across drives"; break;\r
215         case 223: pSt = "Can't rename across directories"; break;\r
216         case 226: pSt = "File Already Exists (duplicate name)"; break;\r
217         case 228: pSt = "Root directory is full"; break;\r
218         case 230: pSt = "Disk is full (bummer)"; break;\r
219         case 231: pSt = "Directory is full"; break;\r
220 \r
221         default:\r
222                 sprintf(st, "Error %05d on last command", erc);\r
223                 pSt = st;\r
224                 break;\r
225 }\r
226         printf("%s\r\n", pSt);\r
227 }\r
228 \r
229 /*********************************************************\r
230   This simply does a software interrupt 03 (Debugger).\r
231 *********************************************************/\r
232 \r
233 void GoDebug(void)\r
234 {\r
235 ;\r
236 #asm\r
237         INT 03\r
238 #endasm\r
239 return;\r
240 }\r
241 \r
242 /*********************************************************\r
243     This is called to initialize the screen.\r
244     If we are returning from and external command\r
245     we do not reset the cursor position. fNew is\r
246     used to determine is we do or not.\r
247 *********************************************************/\r
248 \r
249 void InitScreen(int fNew)\r
250 {\r
251         SetNormVid(NORMVID);\r
252         GetXY(&iCol, &iLine);\r
253         if (fNew)\r
254         {\r
255                 iCol = 0;\r
256                 iLine = 2;\r
257                 ClrScr();\r
258         }\r
259         SetXY(iCol, iLine);\r
260     PutVidChars(0,0, aStatLine, 80, STATVID);\r
261         return;\r
262 }\r
263 \r
264 /*********************************************\r
265  This does a hex dump to the screen of a \r
266  memory area passed in by "pb"\r
267 **********************************************/\r
268 \r
269 U32 Dump(unsigned char *pb, long cb, unsigned long addr)\r
270 {\r
271 U32 erc, i, j, KeyCode;\r
272 unsigned char buff[17];\r
273 \r
274         erc = 0;\r
275         GetXY(&iCol, &iLine);\r
276 \r
277         while (cb)\r
278         {\r
279                 printf("%08x ", addr);\r
280                 if (cb > 15) j=16;\r
281                 else j = cb;\r
282                 for (i=0; i<j; i++)\r
283                 {\r
284                         printf("%02x ",*pb);\r
285                         buff[i] = *pb++;\r
286                         if (buff[i] < 0x20)\r
287                                 buff[i] = 0x2E;\r
288                         if (buff[i] > 0x7F)\r
289                                 buff[i] = 0x2E;\r
290                 }\r
291                 buff[i+1] = 0;\r
292                 printf("%s\r\n", &buff[0]);\r
293                 ++iLine;\r
294                 if (iLine >= 22)\r
295                 {\r
296                         SetXY(0,23);\r
297                         printf("ESC to cancel, any other key to continue...");\r
298                         ReadKbd(&KeyCode, 1);  /* ReadKbd, wait */\r
299                         if ((KeyCode & 0xff) == 0x1b)\r
300                         {\r
301                                 return 4;\r
302                         }\r
303                         InitScreen(TRUE);\r
304                         SetXY(0,1);\r
305                         iLine =1;\r
306                 }\r
307                 if (cb > 15) cb-=16;\r
308                 else cb=0;\r
309         addr+=j;\r
310         }\r
311         return erc;\r
312 }\r
313 \r
314 /*********************************************************\r
315   This sets up to call the dump routine for each page.\r
316   This expects to find the filename in param[1].\r
317 *********************************************************/\r
318 \r
319 long DoDump(void)\r
320 {\r
321 unsigned long j, k, l, erc, dret, fh;\r
322 \r
323 erc = 0;\r
324 if ((apParam[1]) && (acbParam[1]))\r
325 {\r
326         if (iLine >= 23) \r
327         {\r
328                 ScrollVid(0,1,80,23,1);\r
329                 SetXY(0,23);\r
330         }\r
331         erc = OpenFile(apParam[1], acbParam[1], ModeRead, 1, &fh);\r
332         if (!erc) \r
333         {\r
334                 j=0;                            /* file lfa */\r
335                 GetFileSize(fh, &k);\r
336                 while ((j<k) && (!erc))\r
337                 {\r
338                         FillData(Buffer, 512, 0);\r
339                         erc = ReadBytes (fh, Buffer, 512, &dret);\r
340                         if (k-j > 512)\r
341                                 l = 512;\r
342                         else l=k-j;\r
343                         if (erc < 2)\r
344                                 erc = Dump(Buffer, dret, j);\r
345                         j+=512;\r
346                 }\r
347                 CloseFile (fh);\r
348         }\r
349 }\r
350 else\r
351         printf("Filename not given\r\n");\r
352 \r
353 return erc;\r
354 }\r
355 \r
356 /*********************************************************\r
357   This types a text file to the screen.\r
358 *********************************************************/\r
359 \r
360 long DoType(char *pName, long cbName)\r
361 {\r
362 long i, j, lfa, erc, dret, fh, KeyCode;\r
363 \r
364 erc = 0;\r
365 if ((pName) && (cbName)) \r
366 {\r
367 \r
368         if (iLine >= 23)\r
369         {\r
370                 ScrollVid(0,1,80,23,1);\r
371                 SetXY(0,23);\r
372         }\r
373         erc = OpenFile(pName, cbName, 0, 1, &fh);\r
374         if (!erc) \r
375         {\r
376                 FillData(Buffer, 512, 0);\r
377                 dret = 1;\r
378                 while ((erc<2) && (dret)) \r
379                 {\r
380                         GetFileLFA(fh, &lfa);\r
381                         erc = ReadBytes (fh, Buffer, 78, &dret);\r
382                         i = 1;\r
383                         while ((Buffer[i-1] != 0x0A) && (i < dret)) \r
384                         {\r
385                                 i++;\r
386                         }\r
387                         for (j=0; j<=i; j++) \r
388                         {\r
389                                 if ((Buffer[j] == 0x09) || (Buffer[j] == 0x0d) ||\r
390                     (Buffer[j] == 0x0a))\r
391                    Buffer[j] = 0x20;\r
392                         }\r
393                         if (dret)\r
394                         {\r
395                                 PutVidChars(0, iLine, Buffer, i, NORMVID);\r
396                                 iLine++;\r
397                         }\r
398                         SetXY(0,iLine);\r
399                         SetFileLFA(fh, lfa+i);\r
400                         if (iLine >= 22)\r
401                         {\r
402                                 SetXY(0,23);\r
403                                 printf("ESC to cancel, any other key to continue...");\r
404                                 ReadKbd(&KeyCode, 1);  /* ReadKbd, wait */\r
405                                 if ((KeyCode & 0xff) == 0x1b)\r
406                               return(4);\r
407                                 InitScreen(TRUE);\r
408                                 SetXY(0,1);\r
409                                 iLine =1;\r
410                         }\r
411                 }\r
412                 printf("\r\nError: %d\r\n", erc);\r
413                 CloseFile (fh);\r
414         }\r
415 }\r
416 else\r
417         printf("Filename not given\r\n");\r
418 \r
419 return erc;\r
420 }\r
421 \r
422 /*******************************************************\r
423   This reads DOS FAT date & time and converts it into\r
424   strings with the format  MM/DD/YY  HH/MM/SS.\r
425   This is used by the directory listing.\r
426 ********************************************************/\r
427 void CnvrtFATTime(U16 time,\r
428                                   U16 date,\r
429                                   char *pTimeRet,\r
430                                   char *pDateRet)\r
431 {\r
432 U32 yr,mo,da,hr,mi,se;\r
433 char st[15];\r
434 \r
435         yr = ((date & 0xFE00) >> 9) + 1980 - 1900;\r
436         if (yr > 99) yr -=100;\r
437         mo = (date & 0x01E0) >> 5;\r
438         da = date & 0x001F;\r
439         hr = (time & 0xF800) >> 11;\r
440         mi = (time & 0x07E0) >> 5;\r
441         se = (time & 0x001F) * 2;\r
442         sprintf(st, "%02d:%02d:%02d",hr,mi,se);\r
443         CopyData(st, pTimeRet, 8);\r
444         sprintf(st, "%02d-%02d-%02d",mo,da,yr);\r
445         CopyData(st, pDateRet, 8);\r
446 \r
447 }\r
448 \r
449 /*******************************************************\r
450   Copy a single file with overwrite checking.\r
451   Use block mode for speed. This uses a conservative\r
452   4K buffer. THis could be made a good deal faster by\r
453   allocating a large chunk of memory and using it\r
454   instead of the 4K static buffer.\r
455 ********************************************************/\r
456 \r
457 U32 CopyFile(char *pFrom, U32 cbFrom, char *pTo, U32 cbTo)\r
458 {\r
459 U32 fhTo, fhFrom, bytesWant, bytesGot, bytesLeft, erc,\r
460     bytesOut, size, dLFA, KeyCode;\r
461 \r
462         erc = OpenFile(pFrom, cbFrom, ModeRead, 0, &fhFrom);\r
463         if (!erc)\r
464         {\r
465                 /* Check to see if it exists already */\r
466 \r
467                 erc = CreateFile(pTo, cbTo, 0);\r
468                 if ((!erc) || (erc==ErcDupName))\r
469                 {\r
470                         if (erc == ErcDupName)\r
471                         {\r
472                                 printf("File already exists. Overwrite? (Y/N)\r\n");\r
473                                 ReadKbd(&KeyCode, 1);  /* ReadKbd, wait */\r
474                                 if (((KeyCode & 0xff) == 'Y') || ((KeyCode & 0xff) == 'y'))\r
475                                 {\r
476                                         erc = 0;\r
477                                 }\r
478                         }\r
479 \r
480                         if (!erc)\r
481                         {\r
482                         erc = OpenFile(pTo, cbTo, ModeModify, 0, &fhTo);\r
483                                 if (!erc)\r
484                                 {\r
485                                         /* both files are open in block mode */\r
486 \r
487                                         erc = GetFileSize(fhFrom, &size);\r
488                                         if (!erc)\r
489                                                 erc = SetFileSize(fhTo, size);\r
490 \r
491                                         dLFA = 0;\r
492                                         bytesLeft = size;\r
493                                         while ((!erc) && (bytesLeft))\r
494                                         {   if (bytesLeft >= 4096)\r
495                                                         bytesWant = 4096;\r
496                                                 else\r
497                                                         bytesWant = bytesLeft;\r
498                                                 if (bytesWant & 511)    /* handle last sector */\r
499                                                         bytesWant += 512;\r
500                                                 bytesWant = (bytesWant/512) * 512;\r
501                                                 erc = ReadBlock(fhFrom, bigBuf, bytesWant,\r
502                                                                                 dLFA, &bytesGot);\r
503                                                 if (bytesGot)\r
504                                                 {\r
505                                                         erc = WriteBlock(fhTo, bigBuf, bytesGot,\r
506                                                                                          dLFA, &bytesOut);\r
507                                                         if (bytesLeft < bytesOut)\r
508                                                                 bytesLeft = 0;\r
509                                                         else\r
510                                                                 bytesLeft-=bytesOut;\r
511                                                 }\r
512                                                 dLFA += bytesGot;\r
513                                         }\r
514                                         CloseFile(fhTo);\r
515                                 }\r
516                         }\r
517                 }\r
518                 CloseFile(fhFrom);\r
519         }\r
520         return(erc);\r
521 }\r
522 \r
523 /*********************************************************\r
524   Does a directory listing for param[1] or current path.\r
525 *********************************************************/\r
526 \r
527 U32 DoDir(void)\r
528 {\r
529 U8 fDone;\r
530 U32 SectNum, erc, KeyCode, i;\r
531 char st[78];\r
532 \r
533 if (iLine >= 23)\r
534 {\r
535         ScrollVid(0,1,80,23,1);\r
536         SetXY(0,23);\r
537 }\r
538 fDone = 0;\r
539 SectNum = 0;\r
540 while (!fDone)\r
541 {\r
542         erc = GetDirSector(apParam[1], acbParam[1], &dirent[0], 512, SectNum);\r
543         if (!erc) \r
544         {\r
545                 for (i=0; i<16; i++) \r
546                 {\r
547                         if (!dirent[i].Name[0])\r
548                         {\r
549                                 erc = 1;\r
550                                 fDone = 1;\r
551                         }\r
552                         if ((dirent[i].Name[0]) && (dirent[i].Name[0] != 0xE5))\r
553                         {\r
554                                 sprintf(st, "%8s %3s  %8d  xx/xx/xx xx/xx/xx  %2x   %04x\r\n",\r
555                                                 dirent[i].Name,\r
556                                                 dirent[i].Ext,\r
557                                                 dirent[i].FileSize,\r
558                                                 dirent[i].Attr,\r
559                                                 dirent[i].StartClstr);\r
560                                 CnvrtFATTime(dirent[i].Time, dirent[i].Date, &st[33], &st[24]);\r
561                                 printf("%s", st);\r
562                                 iLine++;\r
563                                 if (iLine >= 22)\r
564                                 {\r
565                                         SetXY(0,23);\r
566                                         printf("ESC to cancel, any other key to continue...");\r
567                                         ReadKbd(&KeyCode, 1);  /* ReadKbd, wait */\r
568                                         if ((KeyCode & 0xff) == 0x1b)\r
569                                         {\r
570                                                 erc = 4;\r
571                                                 fDone = TRUE;\r
572                                         }\r
573                                         InitScreen(TRUE);\r
574                                         SetXY(0,1);\r
575                                         iLine =1;\r
576                                 }\r
577                         }\r
578                 }\r
579         }\r
580         else\r
581                 fDone = TRUE;\r
582         SectNum++;\r
583 }\r
584 \r
585 return(erc);\r
586 }\r
587 \r
588 /*********************************************************\r
589   This fills in the pointers to, and sizes of, each parameter\r
590   found on the command line in the arrays apParams and\r
591   acbParams.\r
592 *********************************************************/\r
593 \r
594 void ParseCmdLine(void)\r
595 {\r
596 long iCmd, iPrm, i;             /* iCmd is index to aCmd */\r
597         iCmd = 0;\r
598         for (iPrm=0; iPrm<nParamsMax; iPrm++) \r
599         {\r
600                 acbParam[iPrm] = 0;             /* default the param to empty */\r
601                 apParam[iPrm] = 0;              /* Null the ptr */\r
602                 if (iCmd < cbCmd)\r
603                 {\r
604                         if (!isspace(aCmd[iCmd])) \r
605                         {\r
606                                 apParam[iPrm] = &aCmd[iCmd++];  /* ptr to param */\r
607                                 i = 1;\r
608                                 while ((iCmd < cbCmd) && (!isspace(aCmd[iCmd])))\r
609                                 {\r
610                                         i++;\r
611                                         iCmd++;\r
612                                 }\r
613                                 acbParam[iPrm] = i;             /* size of param */\r
614                         }\r
615                         while ((iCmd < cbCmd) && (isspace(aCmd[iCmd])))\r
616                                 iCmd++;\r
617                 }\r
618         }\r
619 }\r
620 \r
621 /*************************************************\r
622   This opens and parses Commands.CLI in the system\r
623   directory and looks for the command name in\r
624   apParam[0]. If it finds it, it places the full\r
625   filespec for the run file in "runfile" for the\r
626   caller, then fixes up the aCmd command line\r
627   just as if it had come from the user.\r
628   The format for a line entry in Commands.CLI is:\r
629   name fullspec param param param...\r
630 **************************************************/\r
631 \r
632 long GetCLICommand(char *runfile)\r
633 {\r
634 long i, j, k;\r
635 FILE *f;\r
636 char rawline[90];       /* used to build a pseudo command line */\r
637 char cmdline[90];       /* used to build a pseudo command line */\r
638 char fdone;\r
639 \r
640         cmdline[0] = 0;\r
641 \r
642         f = fopen(cmdpath, "r");\r
643         if (f)\r
644         {\r
645                 fdone = 0;\r
646                 while (!fdone)\r
647                 {\r
648                         if (fgets(rawline, 89, f))\r
649                         {\r
650                                 if (rawline[0] == ';')  /* a comment line */\r
651                                         continue;\r
652                                 j = CompareNCS(apParam[0], rawline, acbParam[0]);\r
653                                 if (j == -1)\r
654                                 {       /* we found a match for the command */\r
655                                         /* Move the command name into the command line */\r
656                                         i = 0; /* Index into rawline */\r
657                                         j = 0; /* Index into cmdline we are building */\r
658                                         k = 0; /* Index into runfile name we return to caller */\r
659                                         while (!(isspace(rawline[i])))\r
660                                                 cmdline[j++] = rawline[i++];\r
661                                         /* follwed by a space */\r
662                                         cmdline[j++] = ' ';\r
663 \r
664                                         /* skip whitespace in rawline */\r
665                                         while (isspace(rawline[i]))\r
666                                                 i++;\r
667 \r
668                                         /* now move runfile name */\r
669                                         while (!(isspace(rawline[i])))\r
670                                                 runfile[k++] = rawline[i++];\r
671                                         runfile[k] = 0; /* null terminte */\r
672 \r
673                                         /* skip whitespace in rawline */\r
674                                         while (isspace(rawline[i]))\r
675                                                 i++;\r
676                                         /* now move arguments if any, and LF */\r
677                                         while (rawline[i])\r
678                                                 cmdline[j++] = rawline[i++];\r
679                                         cmdline[j] = 0;\r
680 \r
681                                         /* Move cmd line we built to real cmd line */\r
682                                         strcpy(aCmd, cmdline);\r
683                                         cbCmd = strlen(aCmd);\r
684                                         return(1);              /* tell em we got it! */\r
685                                 }\r
686                         }\r
687                         else\r
688                                 fdone = 1;\r
689                 }\r
690         }\r
691         else\r
692                 printf("Commands.CLI not found.\r\n");\r
693 \r
694         return(0);\r
695 }\r
696 \r
697 \r
698 /**************************************************\r
699   When a command is specified to the CLI and it\r
700   is not an internal command, we first look for\r
701   a .RUN file in the current path. If we don't\r
702   find one, we go to the system directory, if\r
703   it's not there, we then go to COMMANDS.CLI\r
704   and search it line by line to see if a run\r
705   file is specified there. If so, we set the\r
706   command line with everything after the runfile\r
707   specified and try to execute it.\r
708 ***************************************************/\r
709 \r
710 void FindRunFile(void)\r
711 {\r
712 char runfile[80];\r
713 long i, erc, fh;\r
714 \r
715         /* Try to find in current path */\r
716 \r
717         CopyData(apParam[0], runfile, acbParam[0]);\r
718         runfile[acbParam[0]] = 0;\r
719         strcat(runfile, ".RUN");\r
720 \r
721         erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
722         if (!erc)\r
723         {                       /* found a run file in sys directory */\r
724                 CloseFile(fh);\r
725                 SetCmdLine(aCmd, cbCmd);\r
726                 erc = Chain(runfile, strlen(runfile), 0);\r
727         }\r
728         else    /* Try to find in System directory */\r
729         {\r
730                 strcpy(runfile, syspath);\r
731                 i = strlen(runfile);\r
732                 CopyData(apParam[0], &runfile[i], acbParam[0]);\r
733                 runfile[acbParam[0]+i] = 0; /* null terminate */\r
734                 strcat(runfile, ".RUN");\r
735                 erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
736                 if (!erc)\r
737                 {                       /* found a run file */\r
738                         CloseFile(fh);\r
739                         SetCmdLine(aCmd, cbCmd);\r
740                         erc = Chain(runfile, strlen(runfile), 0);\r
741                 }\r
742                  /* now we call GetCLICommand as a last resort */\r
743                 else if (GetCLICommand(runfile))\r
744                 {\r
745                         erc = OpenFile(runfile, strlen(runfile), ModeRead, 1, &fh);\r
746                         if (!erc)\r
747                         {                       /* found a run file */\r
748                                 CloseFile(fh);\r
749                                 SetCmdLine(aCmd, cbCmd);\r
750                                 erc = Chain(runfile, strlen(runfile), 0);\r
751                         }\r
752                 }\r
753         }\r
754         printf("Command not found\r\n");\r
755 }\r
756 \r
757 /**********************************************\r
758    Main function entry point.\r
759    Note: No params to CLI.\r
760 ***********************************************/\r
761 \r
762 void main(void)\r
763 {\r
764 unsigned long erc, i, j, fh;\r
765 \r
766         erc = AllocExch(&StatExch);\r
767         erc = AllocExch(&GPExch);\r
768 \r
769         SpawnTask(&StatTask, 24, 0, &StatStack[255], 0);\r
770 \r
771         GetJobNum(&JobNum);\r
772         sprintf(&aStatLine[37], "%02d", JobNum);\r
773 \r
774         SetJobName("CLI V1.0", 8);\r
775 \r
776         /* Get system disk and set up path names for\r
777         cli, command file, and help file.\r
778         */\r
779 \r
780         GetSystemDisk(&sdisk);\r
781         sdisk &= 0x7F;\r
782         sdisk += 0x41;          /* 0=A, 1=B, 2=C etc. */\r
783         syspath[0] = sdisk;\r
784         syspath[1] = ':';\r
785         syspath[2] = 0;\r
786         strcat(syspath, "\\MMSYS\\");\r
787 \r
788         strcpy(clipath, syspath);\r
789         strcat(clipath,"CLI.RUN");\r
790 \r
791         strcpy(cmdpath, syspath);\r
792         strcat(cmdpath,"COMMANDS.CLI");\r
793 \r
794         strcpy(hlppath, syspath);\r
795         strcat(hlppath,"HELP.CLI");\r
796 \r
797         /* If a path was already set we assume that we are re-loading\r
798            after an external command has been run. We do not\r
799            want to reset the screen completely so the user can\r
800            see anything the external command left on the screen.\r
801         */\r
802 \r
803         cbPath = 0;\r
804         GetPath(JobNum, aPath, &cbPath);\r
805         if (cbPath)\r
806         {\r
807                 GetXY(&iCol, &iLine);\r
808                 if (iLine == 0) /* under status line */\r
809                         iLine = 1;\r
810                 InitScreen(FALSE);\r
811                 SetXY(0, iLine);\r
812         }\r
813         else\r
814         {\r
815                 strcpy (aPath, syspath);\r
816                 cbPath = strlen(syspath);\r
817                 SetPath(syspath, strlen(syspath));\r
818                 InitScreen(TRUE);\r
819         }\r
820 \r
821         fUpdatePath = 1;\r
822 \r
823         while (1)\r
824         {\r
825                 FillData(aCmd, 79, ' ');\r
826                 aCmd[79] = 0;\r
827                 cbCmd = 0;\r
828                 SetXY(0, iLine);\r
829                 TTYOut (">", 1, NORMVID);\r
830                 EditLine(aCmd, cbCmd, 79, &cbCmd, &ExitChar, EDVID);\r
831                 TTYOut ("\r\n", 2, NORMVID);\r
832                 GetXY(&iCol, &iLine);\r
833 \r
834                 acbParam[0] = 0;\r
835                 apParam[0] = 0;\r
836         CmdNum = 0;\r
837 \r
838                 if (ExitChar == 0x0d)\r
839                         ParseCmdLine();                 /* set up all params */\r
840 \r
841                 if ((acbParam[0]) && (apParam[0]))\r
842                 {       /* It's a command! */\r
843 \r
844                         i = 1;\r
845                         while (i <= NCMDS)\r
846                         {\r
847                                 j = strlen(paCmds[i]);\r
848                                 if ((acbParam[0] == j) &&\r
849                                         (CompareNCS(apParam[0], paCmds[i], j) == -1))\r
850                                 {\r
851                         CmdNum = i;\r
852                         break;\r
853                                 }\r
854                                 i++;\r
855                         }\r
856                         erc = 0;\r
857                         switch (CmdNum)\r
858                         {\r
859                                 case EXTCMD:                    /* external command */\r
860                                         SetExitJob(clipath, strlen(clipath));\r
861                                         FindRunFile();\r
862                                         break;\r
863                                 case CLSCMD:\r
864                                         InitScreen(TRUE);\r
865                                         break;\r
866                                 case COPYCMD:\r
867                     if ((acbParam[1]) && (acbParam[2]))\r
868                         erc = CopyFile(apParam[1], acbParam[1],\r
869                                          apParam[2], acbParam[2]);\r
870                                         else erc = ErcBadParams;\r
871                                         break;\r
872                                 case DELCMD:\r
873                                         erc = OpenFile(apParam[1], acbParam[1], 1, 0, &fh);\r
874                                         if (!erc)\r
875                                                 erc = DeleteFile(fh);\r
876                                         if (!erc)\r
877                                                 printf("Done.\r\n");\r
878                                         break;\r
879                                 case DIRCMD:\r
880                                         erc = DoDir();\r
881                                         break;\r
882                                 case DBGCMD:\r
883                                         GoDebug();\r
884                                         break;\r
885                                 case DUMPCMD:\r
886                                         erc = DoDump();\r
887                                         break;\r
888                                 case EXITCMD:\r
889                                         SetExitJob("", 0);\r
890                                         ExitJob(0);\r
891                                         break;\r
892                                 case HELPCMD:\r
893                                         erc = DoType(hlppath, strlen(hlppath));\r
894                                         break;\r
895                                 case MAKEDIR:\r
896                                         erc = CreateDir(apParam[1], acbParam[1]);\r
897                                         break;\r
898                                 case MONCMD:\r
899                                         erc = Request("KEYBOARD", 4, GPExch, &GPHndl, 0,\r
900                                                                         0, 0,   0, 0,   1, 0, 0);\r
901                                         erc = WaitMsg(GPExch, GPMsg);\r
902                                         SetVidOwner(1);\r
903                                         break;\r
904                                 case PATHCMD:\r
905                                         erc = SetPath(apParam[1], acbParam[1]);\r
906                                         if (!erc)\r
907                                                 erc = GetPath(JobNum, aPath, &cbPath);\r
908                                         fUpdatePath = 1;\r
909                                         break;\r
910                                 case REMDIR:\r
911                                         erc = DeleteDir(apParam[1], acbParam[1]);\r
912                                         break;\r
913                                 case RENCMD:\r
914                     if ((acbParam[1]) && (acbParam[2]))\r
915                         erc = RenameFile(apParam[1], acbParam[1],\r
916                                          apParam[2], acbParam[2]);\r
917                                         else erc = ErcBadParams;\r
918                                         break;\r
919                                 case RUNCMD:\r
920                                         if (acbParam[1])\r
921                                         {\r
922                                                 i = 2;\r
923                                                 while (aCmd[i] != ' ')\r
924                                                         i++;\r
925                                                 SetCmdLine(&aCmd[i], cbCmd-i);\r
926                                                 SetExitJob(clipath, strlen(clipath));\r
927                                                 erc = Chain(apParam[1], acbParam[1], 0);\r
928                                         }\r
929                                         break;\r
930                                 case TYPECMD:\r
931                                         erc = DoType(apParam[1], acbParam[1]);\r
932                                         break;\r
933                                 default:\r
934                                         break;\r
935                         }\r
936                         CheckErc(erc);\r
937                 }\r
938 \r
939                 GetXY(&iCol, &iLine);\r
940                 if (iLine >= 23)\r
941                 {\r
942                         ScrollVid(0,1,80,23,1);\r
943                         SetXY(0,23);\r
944                 }\r
945         }\r
946 }\r