2 * AcessOS Shell Version 3
\r
4 #define USE_READLINE 1
\r
5 #include <acess/sys.h>
\r
10 #include <readline.h>
\r
12 #include <acess/devices/pty.h>
\r
18 // ==== PROTOTYPES ====
\r
19 int Parse_Args(const char *str, char **dest);
\r
20 void CallCommand(char **Args);
\r
21 void Command_Logout(int argc, char **argv);
\r
22 void Command_Clear(int argc, char **argv);
\r
23 void Command_Help(int argc, char **argv);
\r
24 void Command_Cd(int argc, char **argv);
\r
25 void Command_Dir(int argc, char **argv);
\r
27 // ==== CONSTANT GLOBALS ====
\r
30 void (*fcn)(int argc, char **argv);
\r
32 {"exit", Command_Logout}, {"logout", Command_Logout},
\r
33 {"help", Command_Help}, {"clear", Command_Clear},
\r
34 {"cd", Command_Cd}, {"dir", Command_Dir}
\r
36 static char *cDEFAULT_PATH[] = {"/Acess/Bin","/Acess/SBin"};
\r
37 #define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0]))
\r
39 // ==== LOCAL VARIABLES ====
\r
40 int giNumPathDirs = 2;
\r
41 char **gasPathDirs = cDEFAULT_PATH;
\r
42 char **gasEnvironment;
\r
43 char gsCommandBuffer[1024];
\r
44 char *gsCurrentDirectory = NULL;
\r
45 char **gasCommandHistory;
\r
46 int giLastCommand = 0;
\r
47 int giCommandSpace = 0;
\r
50 int main(int argc, char *argv[], char **envp)
\r
53 char *saArgs[32] = {0};
\r
56 tReadline *readline_state = Readline_Init(1);
\r
58 gasEnvironment = envp;
\r
60 // Command_Clear(0, NULL);
\r
63 char *tmp = getenv("CWD");
\r
65 gsCurrentDirectory = malloc(strlen(tmp)+1);
\r
66 strcpy(gsCurrentDirectory, tmp);
\r
68 gsCurrentDirectory = malloc(2);
\r
69 strcpy(gsCurrentDirectory, "/");
\r
73 printf("Acess Shell Version 3\n\n");
\r
76 // Free last command & arguments
\r
77 if(saArgs[0]) free(saArgs[0]);
\r
79 printf("%s$ ", gsCurrentDirectory);
\r
82 // Read Command line
\r
83 sCommandStr = Readline( readline_state );
\r
85 if( !sCommandStr ) {
\r
90 // Parse Command Line into arguments
\r
91 iArgCount = Parse_Args(sCommandStr, saArgs);
\r
93 // Silently Ignore all empty commands
\r
94 if(saArgs[1][0] == '\0') continue;
\r
96 // Check Built-In Commands
\r
97 for( i = 0; i < BUILTIN_COUNT; i++ )
\r
99 if( strcmp(saArgs[1], cBUILTINS[i].name) == 0 )
\r
101 cBUILTINS[i].fcn(iArgCount-1, &saArgs[1]);
\r
105 if(i != BUILTIN_COUNT) continue;
\r
108 CallCommand( &saArgs[1] );
\r
110 free( sCommandStr );
\r
115 * \fn int Parse_Args(const char *str, char **dest)
\r
116 * \brief Parse a string into an argument array
\r
118 int Parse_Args(const char *str, char **dest)
\r
121 char *buf = malloc( strlen(str) + 1 );
\r
125 printf("Parse_Args: Out of heap space!\n");
\r
132 // Trim leading whitespace
\r
133 while(*buf == ' ' && *buf) buf++;
\r
137 dest[i] = buf; // Save start of string
\r
139 while(*buf && *buf != ' ')
\r
143 while(*buf && !(*buf == '"' && buf[-1] != '\\'))
\r
147 if(*buf == '\0') break;
\r
149 while(*++buf == ' ' && *buf);
\r
150 if(*buf == '\0') break;
\r
158 * \fn void CallCommand(char **Args)
\r
160 void CallCommand(char **Args)
\r
165 char sTmpBuffer[1024];
\r
166 char *exefile = Args[0];
\r
168 if(exefile[0] == '/'
\r
169 || (exefile[0] == '.' && exefile[1] == '/')
\r
170 || (exefile[0] == '.' && exefile[1] == '.' && exefile[2] == '/')
\r
173 GeneratePath(exefile, gsCurrentDirectory, sTmpBuffer);
\r
174 // Check file existence
\r
175 fd = _SysOpen(sTmpBuffer, OPENFLAG_EXEC);
\r
177 printf("Unknown Command: `%s'\n", Args[0]); // Error Message
\r
181 // Get File info and close file
\r
182 _SysFInfo( fd, &info, 0 );
\r
185 // Check if the file is a directory
\r
186 if(info.flags & FILEFLAG_DIRECTORY) {
\r
187 printf("`%s' is a directory.\n", sTmpBuffer);
\r
195 // Check all components of $PATH
\r
196 for( i = 0; i < giNumPathDirs; i++ )
\r
198 GeneratePath(exefile, gasPathDirs[i], sTmpBuffer);
\r
199 fd = _SysOpen(sTmpBuffer, OPENFLAG_EXEC);
\r
200 if(fd == -1) continue;
\r
201 _SysFInfo( fd, &info, 0 );
\r
203 if(info.flags & FILEFLAG_DIRECTORY) continue;
\r
204 // Woohoo! We found a valid command
\r
208 // Exhausted path directories
\r
209 if( i == giNumPathDirs ) {
\r
210 printf("Unknown Command: `%s'\n", exefile);
\r
215 // Create new process
\r
216 int fds[] = {0, 1, 2};
\r
218 pid = _SysSpawn(sTmpBuffer, (const char **)Args, (const char **)gasEnvironment, 3, fds, NULL);
\r
220 printf("Unable to create process: `%s'\n", sTmpBuffer); // Error Message
\r
224 _SysIOCtl(0, PTY_IOCTL_SETPGRP, &pid);
\r
225 _SysWaitTID(pid, &status);
\r
228 // Return terminal to a sane state
\r
231 _SysIOCtl(0, PTY_IOCTL_SETPGRP, &zero);
\r
234 // Print a status message if termination was non-clean
\r
237 printf("[%i] exited %i\n", pid, status);
\r
242 * \fn void Command_Logout(int argc, char **argv)
\r
243 * \brief Exit the shell, logging the user out
\r
245 void Command_Logout(int argc, char **argv)
\r
251 * \fn void Command_Colour(int argc, char **argv)
\r
252 * \brief Displays the help screen
\r
254 void Command_Help(int argc, char **argv)
\r
256 printf( "Acess 2 Command Line Interface\n"
\r
257 " By John Hodge (thePowersGang / [TPG])\n"
\r
259 "Builtin Commands:\n"
\r
260 " logout: Return to the login prompt\n"
\r
262 " help: Display this message\n"
\r
263 " clear: Clear the screen\n"
\r
264 " cd: Change the current directory\n"
\r
265 " dir: Print the contents of the current directory\n");
\r
270 * \fn void Command_Clear(int argc, char **argv)
\r
271 * \brief Clear the screen
\r
273 void Command_Clear(int argc, char **argv)
\r
275 _SysWrite(_stdout, "\x1B[2J", 4); //Clear Screen
\r
279 * \fn void Command_Cd(int argc, char **argv)
\r
280 * \brief Change directory
\r
282 void Command_Cd(int argc, char **argv)
\r
284 char tmpPath[1024];
\r
290 printf("%s\n", gsCurrentDirectory);
\r
294 GeneratePath(argv[1], gsCurrentDirectory, tmpPath);
\r
296 fp = _SysOpen(tmpPath, 0);
\r
298 printf("Directory does not exist\n");
\r
301 _SysFInfo(fp, &stats, 0);
\r
304 if( !(stats.flags & FILEFLAG_DIRECTORY) ) {
\r
305 printf("Not a Directory\n");
\r
309 free(gsCurrentDirectory);
\r
310 gsCurrentDirectory = malloc(strlen(tmpPath)+1);
\r
311 strcpy(gsCurrentDirectory, tmpPath);
\r
313 // Register change with kernel
\r
314 _SysChdir( gsCurrentDirectory );
\r
318 * \fn void Command_Dir(int argc, char **argv)
\r
319 * \brief Print the contents of a directory
\r
321 void Command_Dir(int argc, char **argv)
\r
324 char modeStr[11] = "RWXrwxRWX ";
\r
325 char fileName[256];
\r
330 // -- Generate and open directory --
\r
331 // Generate Directory Path
\r
332 char tmpPath[1024];
\r
334 GeneratePath(argv[1], gsCurrentDirectory, tmpPath);
\r
336 strcpy(tmpPath, gsCurrentDirectory);
\r
338 dp = _SysOpen(tmpPath, OPENFLAG_READ);
\r
340 printf("Unable to open directory `%s', File cannot be found\n", tmpPath);
\r
344 if( _SysFInfo(dp, &info, 0) == -1 )
\r
347 printf("stat Failed, Bad File Descriptor\n");
\r
350 // Check if it's a directory
\r
351 if(!(info.flags & FILEFLAG_DIRECTORY))
\r
354 printf("Unable to open directory `%s', Not a directory\n", tmpPath);
\r
358 // -- Read Directory Contents --
\r
359 while( (fp = _SysReadDir(dp, fileName)) )
\r
364 printf("Invalid Permissions to traverse directory\n");
\r
368 fp = _SysOpenChild(dp, fileName, 0);
\r
369 if(fp == -1) continue;
\r
371 _SysFInfo(fp, &info, 0);
\r
373 if(info.flags & FILEFLAG_DIRECTORY)
\r
380 acl.object = info.uid;
\r
381 _SysGetACL(fp, &acl);
\r
382 if(acl.perms & 1) modeStr[0] = 'r'; else modeStr[0] = '-';
\r
383 if(acl.perms & 2) modeStr[1] = 'w'; else modeStr[1] = '-';
\r
384 if(acl.perms & 8) modeStr[2] = 'x'; else modeStr[2] = '-';
\r
386 acl.object = info.gid | 0x80000000;
\r
387 _SysGetACL(fp, &acl);
\r
388 if(acl.perms & 1) modeStr[3] = 'r'; else modeStr[3] = '-';
\r
389 if(acl.perms & 2) modeStr[4] = 'w'; else modeStr[4] = '-';
\r
390 if(acl.perms & 8) modeStr[5] = 'x'; else modeStr[5] = '-';
\r
392 acl.object = 0xFFFFFFFF;
\r
393 _SysGetACL(fp, &acl);
\r
394 if(acl.perms & 1) modeStr[6] = 'r'; else modeStr[6] = '-';
\r
395 if(acl.perms & 2) modeStr[7] = 'w'; else modeStr[7] = '-';
\r
396 if(acl.perms & 8) modeStr[8] = 'x'; else modeStr[8] = '-';
\r
401 if(info.flags & FILEFLAG_DIRECTORY) // Directory: Green
\r
402 printf("\x1B[32m");
\r
406 printf("%s", fileName);
\r
408 // Print slash if applicable
\r
409 if(info.flags & FILEFLAG_DIRECTORY)
\r
413 printf("\x1B[37m");
\r