#include <acess/sys.h>\r
#include <stdlib.h>\r
#include <stdio.h>\r
+#include <string.h>\r
#include "header.h"\r
\r
#define _stdin 0\r
// ==== PROTOTYPES ====\r
char *ReadCommandLine(int *Length);\r
void Parse_Args(char *str, char **dest);\r
-void Command_Colour(int argc, char **argv);\r
+void CallCommand(char **Args);\r
+void Command_Logout(int argc, char **argv);\r
void Command_Clear(int argc, char **argv);\r
+void Command_Colour(int argc, char **argv);\r
void Command_Cd(int argc, char **argv);\r
void Command_Dir(int argc, char **argv);\r
\r
char *name;\r
void (*fcn)(int argc, char **argv);\r
} cBUILTINS[] = {\r
+ {"exit", Command_Logout}, {"logout", Command_Logout},\r
{"colour", Command_Colour}, {"clear", Command_Clear},\r
{"cd", Command_Cd}, {"dir", Command_Dir}\r
};\r
+static char *cDEFAULT_PATH[] = {"/Acess/Bin"};\r
#define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0]))\r
\r
// ==== LOCAL VARIABLES ====\r
+ int giNumPathDirs = 1;\r
+char **gasPathDirs = cDEFAULT_PATH;\r
+char **gasEnvironment;\r
char gsCommandBuffer[1024];\r
char *gsCurrentDirectory = NULL;\r
-char gsTmpBuffer[1024];\r
char **gasCommandHistory;\r
int giLastCommand = 0;\r
int giCommandSpace = 0;\r
int main(int argc, char *argv[], char *envp[])\r
{\r
char *sCommandStr;\r
- char *saArgs[32];\r
+ char *saArgs[32] = {0};\r
int length = 0;\r
- int pid = -1;\r
+ int i;\r
int iArgCount = 0;\r
int bCached = 1;\r
- t_sysFInfo info;\r
\r
- //Command_Clear(0, NULL);\r
+ gasEnvironment = envp;\r
+ \r
+ Command_Clear(0, NULL);\r
\r
{\r
char *tmp = getenv("CWD");\r
}\r
} \r
\r
- write(_stdout, 1, "\n");\r
write(_stdout, 22, "Acess Shell Version 3\n");\r
write(_stdout, 2, "\n");\r
for(;;)\r
if(saArgs[0]) free(saArgs);\r
if(!bCached) free(sCommandStr);\r
bCached = 0;\r
- write(_stdout, 1, "\n");\r
write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory);\r
write(_stdout, 3, "$ ");\r
\r
// Read Command line\r
sCommandStr = ReadCommandLine( &length );\r
\r
+ if(!sCommandStr) {\r
+ write(_stdout, 25, "PANIC: Out of heap space\n");\r
+ return -1;\r
+ }\r
+ \r
// Check if the command should be cached\r
if(gasCommandHistory == NULL || strcmp(sCommandStr, gasCommandHistory[giLastCommand]) != 0)\r
{\r
if(saArgs[1][0] == '\0') continue;\r
\r
// Check Built-In Commands\r
- // [HACK] Mem Usage - Use Length in place of `i'\r
- for(length=0;length<BUILTIN_COUNT;length++)\r
+ for( i = 0; i < BUILTIN_COUNT; i++ )\r
{\r
- if(strcmp(saArgs[1], cBUILTINS[length].name) == 0)\r
+ if( strcmp(saArgs[1], cBUILTINS[i].name) == 0 )\r
{\r
- cBUILTINS[length].fcn(iArgCount-1, &saArgs[1]);\r
+ cBUILTINS[i].fcn(iArgCount-1, &saArgs[1]);\r
break;\r
}\r
}\r
+ if(i != BUILTIN_COUNT) continue;\r
\r
- if(length != BUILTIN_COUNT) continue;\r
-
- // - Calling a file\r
- GeneratePath(saArgs[1], gsCurrentDirectory, gsTmpBuffer);\r
- // Use length in place of fp\r
- length = open(gsTmpBuffer, 0);\r
- // Check file existence\r
- if(length == -1) {\r
- Print("Unknown Command: `");Print(saArgs[1]);Print("'\n"); // Error Message\r
- continue;\r
- }\r
- // Check if the file is a directory\r
- finfo( length, &info, 0 );
- close( length );\r
- if(info.flags & FILEFLAG_DIRECTORY) {\r
- Print("`");Print(saArgs[1]); // Error Message\r
- Print("' is a directory.\n");\r
- continue;\r
- }\r
- // Load new executable\r
- pid = clone(CLONE_VM, 0);\r
- if(pid == 0) execve(gsTmpBuffer, &saArgs[1], envp);\r
- if(pid <= 0) {\r
- Print("Unablt to create process: `");Print(gsTmpBuffer);Print("'\n"); // Error Message
- //SysDebug("pid = %i\n", pid);\r
- }\r
- else {\r
- int status;\r
- waittid(pid, &status);\r
- }\r
+ // Shall we?\r
+ CallCommand( &saArgs[1] );\r
}\r
}\r
\r
\r
// Preset Variables\r
ret = malloc( space+1 );\r
- len = 0;\r
- pos = 0;\r
+ if(!ret) return NULL;\r
+ len = 0; pos = 0;\r
\r
// Read In Command Line\r
do {\r
read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call)\r
- // Ignore control characters\r
- if(ch < 0) continue;\r
+ // Control characters\r
+ if(ch == '\x1B') {\r
+ read(_stdin, 1, &ch); // Read control character\r
+ switch(ch)\r
+ {\r
+ case 'D': if(pos) pos--; break;\r
+ case 'C': if(pos<len) pos++; break;\r
+ case '[':\r
+ read(_stdin, 1, &ch); // Read control character\r
+ switch(ch)\r
+ {\r
+ case 'D': if(pos) pos--; break;\r
+ case 'C': if(pos<len) pos++; break;\r
+ }\r
+ }\r
+ continue;\r
+ }\r
// Backspace\r
if(ch == '\b') {\r
if(len <= 0) continue; // Protect against underflows\r
write(_stdout, 1, &ch);\r
continue;\r
}\r
+ // Tab\r
+ if(ch == '\t') {\r
+ //TODO: Implement Tab-Completion\r
+ //Currently just ignore tabs\r
+ continue;\r
+ }\r
+ \r
// Expand Buffer\r
if(len > space) {\r
space += 256;\r
int i = 1;\r
char *buf = malloc( strlen(str) + 1 );\r
\r
+ if(buf == NULL) {\r
+ dest[0] = NULL;\r
+ Print("Parse_Args: Out of heap space!\n");\r
+ return ;\r
+ }\r
+ \r
strcpy(buf, str);\r
dest[0] = buf;\r
\r
}\r
}\r
\r
+/**\r
+ * \fn void CallCommand(char **Args)\r
+ */\r
+void CallCommand(char **Args)\r
+{\r
+ t_sysFInfo info;\r
+ int pid = -1;\r
+ int fd = 0;\r
+ char sTmpBuffer[1024];\r
+ char *exefile = Args[0];\r
+ \r
+ if(exefile[0] == '/'\r
+ || (exefile[0] == '.' && exefile[1] == '/')\r
+ || (exefile[0] == '.' && exefile[1] == '.' && exefile[2] == '/')\r
+ )\r
+ {\r
+ GeneratePath(exefile, gsCurrentDirectory, sTmpBuffer);\r
+ // Check file existence\r
+ fd = open(sTmpBuffer, OPENFLAG_EXEC);\r
+ if(fd == -1) {\r
+ Print("Unknown Command: `");Print(Args[0]);Print("'\n"); // Error Message\r
+ return ;\r
+ }\r
+ \r
+ // Get File info and close file\r
+ finfo( fd, &info, 0 );\r
+ close( fd );\r
+ \r
+ // Check if the file is a directory\r
+ if(info.flags & FILEFLAG_DIRECTORY) {\r
+ Print("`");Print(sTmpBuffer); // Error Message\r
+ Print("' is a directory.\n");\r
+ return ;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ int i;\r
+ \r
+ // Check all components of $PATH\r
+ for( i = 0; i < giNumPathDirs; i++ )\r
+ {\r
+ GeneratePath(exefile, gasPathDirs[i], sTmpBuffer);\r
+ fd = open(sTmpBuffer, OPENFLAG_EXEC);\r
+ if(fd == -1) continue;\r
+ finfo( fd, &info, 0 );\r
+ close( fd );\r
+ if(info.flags & FILEFLAG_DIRECTORY) continue;\r
+ // Woohoo! We found a valid command\r
+ break;\r
+ }\r
+ \r
+ // Exhausted path directories\r
+ if( i == giNumPathDirs ) {\r
+ Print("Unknown Command: `");Print(exefile);Print("'\n");\r
+ return ;\r
+ }\r
+ }\r
+ \r
+ // Create new process\r
+ pid = clone(CLONE_VM, 0);\r
+ // Start Task\r
+ if(pid == 0)\r
+ execve(sTmpBuffer, Args, gasEnvironment);\r
+ if(pid <= 0) {\r
+ Print("Unablt to create process: `");Print(sTmpBuffer);Print("'\n"); // Error Message\r
+ }\r
+ else {\r
+ int status;\r
+ waittid(pid, &status);\r
+ }\r
+}\r
+\r
+/**\r
+ * \fn void Command_Logout(int argc, char **argv)\r
+ * \brief Exit the shell, logging the user out\r
+ */\r
+void Command_Logout(int argc, char **argv)\r
+{\r
+ exit(0);\r
+}\r
+\r
+/**\r
+ * \fn void Command_Clear(int argc, char **argv)\r
+ * \brief Clear the screen\r
+ */\r
+void Command_Clear(int argc, char **argv)\r
+{\r
+ write(_stdout, 4, "\x1B[2J"); //Clear Screen\r
+}\r
+\r
/**\r
* \fn void Command_Colour(int argc, char **argv)\r
- * \brief \r
+ * \brief Set the colour of the shell prompt\r
+ * \note Conflicts with coloured `dir` display\r
*/\r
void Command_Colour(int argc, char **argv)\r
{\r
// Verify Arg Count\r
if(argc < 2)\r
{\r
- Print("Please specify a colour\n");\r
goto usage;\r
}\r
\r
\r
// Function Usage (Requested via a Goto (I know it's ugly))\r
usage:\r
+ Print("Usage: colour <foreground> [<background>]\n");\r
Print("Valid Colours are ");\r
for(fg=0;fg<8;fg++)\r
{\r
return;\r
}\r
\r
-void Command_Clear(int argc, char **argv)\r
-{\r
- write(_stdout, 4, "\x1B[2J"); //Clear Screen\r
-}\r
-\r
/**\r
* \fn void Command_Cd(int argc, char **argv)\r
* \brief Change directory\r
free(gsCurrentDirectory);\r
gsCurrentDirectory = malloc(strlen(tmpPath)+1);\r
strcpy(gsCurrentDirectory, tmpPath);\r
+ \r
+ // Register change with kernel\r
+ chdir( gsCurrentDirectory );\r
}\r
\r
/**\r
+ * \fn void Command_Dir(int argc, char **argv)\r
+ * \brief Print the contents of a directory\r
*/\r
void Command_Dir(int argc, char **argv)\r
{\r
// Check if file opened\r
if(dp == -1)\r
{\r
- //printf("Unable to open directory `%s', File cannot be found\n", tmpPath);\r
- write(_stdout, 27, "Unable to open directory `");\r
- write(_stdout, strlen(tmpPath)+1, tmpPath);\r
- write(_stdout, 25, "', File cannot be found\n");\r
+ printf("Unable to open directory `%s', File cannot be found\n", tmpPath);\r
return;\r
}\r
// Get File Stats\r
write(_stdout, 1, "-");\r
\r
// Print Mode\r
+ // - Owner\r
acl.group = 0; acl.id = info.uid;\r
_SysGetACL(fp, &acl);\r
if(acl.perms & 1) modeStr[0] = 'r'; else modeStr[0] = '-';\r
if(acl.perms & 2) modeStr[1] = 'w'; else modeStr[1] = '-';\r
if(acl.perms & 8) modeStr[2] = 'x'; else modeStr[2] = '-';\r
+ // - Group\r
acl.group = 1; acl.id = info.gid;\r
_SysGetACL(fp, &acl);\r
if(acl.perms & 1) modeStr[3] = 'r'; else modeStr[3] = '-';\r
- if(acl.perms & 1) modeStr[4] = 'w'; else modeStr[4] = '-';\r
- if(acl.perms & 1) modeStr[5] = 'x'; else modeStr[5] = '-';\r
+ if(acl.perms & 2) modeStr[4] = 'w'; else modeStr[4] = '-';\r
+ if(acl.perms & 8) modeStr[5] = 'x'; else modeStr[5] = '-';\r
+ // - World\r
acl.group = 1; acl.id = -1;\r
_SysGetACL(fp, &acl);\r
if(acl.perms & 1) modeStr[6] = 'r'; else modeStr[6] = '-';\r
- if(acl.perms & 1) modeStr[7] = 'w'; else modeStr[7] = '-';\r
- if(acl.perms & 1) modeStr[8] = 'x'; else modeStr[8] = '-';\r
+ if(acl.perms & 2) modeStr[7] = 'w'; else modeStr[7] = '-';\r
+ if(acl.perms & 8) modeStr[8] = 'x'; else modeStr[8] = '-';\r
write(_stdout, 10, modeStr);\r
close(fp);\r
\r