2 AcessOS Shell Version 2
\r
3 - Based on IOOS CLI Shell
\r
5 #include <acess/sys.h>
\r
13 // ==== PROTOTYPES ====
\r
14 char *ReadCommandLine(int *Length);
\r
15 void Parse_Args(char *str, char **dest);
\r
16 void Command_Colour(int argc, char **argv);
\r
17 void Command_Clear(int argc, char **argv);
\r
18 //void Command_Ls(int argc, char **argv);
\r
19 void Command_Cd(int argc, char **argv);
\r
20 //void Command_Cat(int argc, char **argv);
\r
22 // ==== CONSTANT GLOBALS ====
\r
23 char *cCOLOUR_NAMES[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
\r
26 void (*fcn)(int argc, char **argv);
\r
28 {"colour", Command_Colour}, {"clear", Command_Clear}, {"cd", Command_Cd}
\r
30 #define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0]))
\r
32 // ==== LOCAL VARIABLES ====
\r
33 char gsCommandBuffer[1024];
\r
34 char *gsCurrentDirectory = "/";
\r
35 char gsTmpBuffer[1024];
\r
36 char **gasCommandHistory;
\r
37 int giLastCommand = 0;
\r
38 int giCommandSpace = 0;
\r
41 int main(int argc, char *argv[], char *envp[])
\r
51 //Command_Clear(0, NULL);
\r
53 write(_stdout, 1, "\n");
\r
54 write(_stdout, 36, "Acess Shell Version 3\n");
\r
55 write(_stdout, 30, " Based on CLI Shell for IOOS\n");
\r
56 write(_stdout, 2, "\n");
\r
59 // Free last command & arguments
\r
60 if(saArgs[0]) free(saArgs);
\r
61 if(!bCached) free(sCommandStr);
\r
63 write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory);
\r
64 write(_stdout, 3, "$ ");
\r
66 // Read Command line
\r
67 sCommandStr = ReadCommandLine( &length );
\r
69 // Check if the command should be cached
\r
70 if(gasCommandHistory == NULL || strcmp(sCommandStr, gasCommandHistory[giLastCommand]) != 0)
\r
72 if(giLastCommand >= giCommandSpace) {
\r
73 giCommandSpace += 12;
\r
74 gasCommandHistory = realloc(gasCommandHistory, giCommandSpace*sizeof(char*));
\r
77 gasCommandHistory[ giLastCommand ] = sCommandStr;
\r
81 // Parse Command Line into arguments
\r
82 Parse_Args(sCommandStr, saArgs);
\r
86 while(saArgs[iArgCount]) iArgCount++;
\r
88 // Silently Ignore all empty commands
\r
89 if(saArgs[1][0] == '\0') continue;
\r
91 // Check Built-In Commands
\r
92 // [HACK] Mem Usage - Use Length in place of `i'
\r
93 for(length=0;length<BUILTIN_COUNT;length++)
\r
95 if(strcmp(saArgs[1], cBUILTINS[length].name) == 0)
\r
97 cBUILTINS[length].fcn(iArgCount-1, &saArgs[1]);
\r
102 if(length == BUILTIN_COUNT)
\r
104 GeneratePath(saArgs[1], gsCurrentDirectory, gsTmpBuffer);
\r
105 // Use length in place of fp
\r
106 length = open(gsTmpBuffer, 0);
\r
107 // Check file existence
\r
109 Print("Unknown Command: `");Print(saArgs[1]);Print("'\n"); // Error Message
\r
112 // Check if the file is a directory
\r
113 finfo( length, &info );
115 if(info.flags & FILEFLAG_DIRECTORY) {
\r
116 Print("`");Print(saArgs[1]); // Error Message
\r
117 Print("' is a directory.\n");
\r
120 pid = clone(CLONE_VM, 0);
\r
121 if(pid == 0) execve(gsTmpBuffer, &saArgs[1], NULL);
\r
123 Print("Unablt to create process: `");Print(gsTmpBuffer);Print("'\n"); // Error Message
124 //SysDebug("pid = %i\n", pid);
\r
127 //waitpid(pid, K_WAITPID_DIE);
\r
134 * \fn char *ReadCommandLine(int *Length)
\r
135 * \brief Read from the command line
\r
137 char *ReadCommandLine(int *Length)
\r
140 int len, pos, space = 1023;
\r
143 // Preset Variables
\r
144 ret = malloc( space+1 );
\r
148 // Read In Command Line
\r
150 read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call)
\r
151 // Ignore control characters
\r
152 if(ch < 0) continue;
\r
155 if(len <= 0) continue; // Protect against underflows
\r
156 if(pos == len) { // Simple case of end of string
\r
159 memmove(&ret[pos-1], &ret[pos], len-pos);
\r
163 write(_stdout, 1, &ch);
\r
169 ret = realloc(ret, space+1);
\r
170 if(!ret) return NULL;
\r
173 write(_stdout, 1, &ch);
\r
176 } while(ch != '\n');
\r
183 if(Length) *Length = len;
\r
189 * \fn void Parse_Args(char *str, char **dest)
\r
190 * \brief Parse a string into an argument array
\r
192 void Parse_Args(char *str, char **dest)
\r
195 char *buf = malloc( strlen(str) + 1 );
\r
200 // Trim leading whitespace
\r
201 while(*buf == ' ' && *buf) buf++;
\r
205 dest[i] = buf; // Save start of string
\r
207 while(*buf && *buf != ' ')
\r
211 while(*buf && !(*buf == '"' && buf[-1] != '\\'))
\r
215 if(*buf == '\0') break;
\r
217 while(*++buf == ' ' && *buf);
\r
218 if(*buf == '\0') break;
\r
228 * \fn void Command_Colour(int argc, char **argv)
\r
231 void Command_Colour(int argc, char **argv)
\r
234 char clrStr[6] = "\x1B[37m";
\r
236 // Verify Arg Count
\r
239 Print("Please specify a colour\n");
\r
244 for(fg=0;fg<8;fg++)
\r
245 if(strcmp(cCOLOUR_NAMES[fg], argv[1]) == 0)
\r
248 // Foreground a valid colour
\r
250 Print("Unknown Colour '");Print(argv[1]);Print("'\n");
\r
254 clrStr[3] = '0' + fg;
\r
255 write(_stdout, 6, clrStr);
\r
257 // Need to Set Background?
\r
260 for(bg=0;bg<8;bg++)
\r
261 if(strcmp(cCOLOUR_NAMES[bg], argv[2]) == 0)
\r
267 Print("Unknown Colour '");Print(argv[2]);Print("'\n");
\r
272 clrStr[3] = '0' + bg;
\r
273 write(_stdout, 6, clrStr);
\r
278 // Function Usage (Requested via a Goto (I know it's ugly))
\r
280 Print("Valid Colours are ");
\r
281 for(fg=0;fg<8;fg++)
\r
283 Print(cCOLOUR_NAMES[fg]);
\r
284 write(_stdout, 3, ", ");
\r
286 write(_stdout, 4, "\b\b\n");
\r
290 void Command_Clear(int argc, char **argv)
\r
292 write(_stdout, 4, "\x1B[2J"); //Clear Screen
\r
295 void Command_Cd(int argc, char **argv)
\r
297 char tmpPath[1024];
\r
303 Print(gsCurrentDirectory);Print("\n");
\r
307 GeneratePath(argv[1], gsCurrentDirectory, tmpPath);
\r
309 fp = open(tmpPath, 0);
\r
311 write(_stdout, 26, "Directory does not exist\n");
\r
317 if(!(stats.flags & FILEFLAG_DIRECTORY)) {
\r
318 write(_stdout, 17, "Not a Directory\n");
\r
322 strcpy(gsCurrentDirectory, tmpPath);
\r