X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2FCLIShell_src%2Fmain.c;h=d6c40d65a4db47e3ffb24e7c8a680bf73839d4ac;hb=a8067bafb36f98612767060db856cd6bf36ef940;hp=28d476f3ec08fc15bc86ea0105218fddd2188fed;hpb=17e16b3110b4c5124b0707435e0427993d696545;p=tpg%2Facess2.git diff --git a/Usermode/Applications/CLIShell_src/main.c b/Usermode/Applications/CLIShell_src/main.c index 28d476f3..d6c40d65 100644 --- a/Usermode/Applications/CLIShell_src/main.c +++ b/Usermode/Applications/CLIShell_src/main.c @@ -1,9 +1,10 @@ /* - AcessOS Shell Version 2 -- Based on IOOS CLI Shell -*/ + * AcessOS Shell Version 3 + */ #include #include +#include +#include #include "header.h" #define _stdin 0 @@ -13,26 +14,31 @@ // ==== PROTOTYPES ==== char *ReadCommandLine(int *Length); void Parse_Args(char *str, char **dest); -void Command_Colour(int argc, char **argv); +void CallCommand(char **Args); +void Command_Logout(int argc, char **argv); void Command_Clear(int argc, char **argv); -//void Command_Ls(int argc, char **argv); +void Command_Help(int argc, char **argv); void Command_Cd(int argc, char **argv); -//void Command_Cat(int argc, char **argv); +void Command_Dir(int argc, char **argv); // ==== CONSTANT GLOBALS ==== -char *cCOLOUR_NAMES[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"}; struct { char *name; void (*fcn)(int argc, char **argv); } cBUILTINS[] = { - {"colour", Command_Colour}, {"clear", Command_Clear}, {"cd", Command_Cd} + {"exit", Command_Logout}, {"logout", Command_Logout}, + {"help", Command_Help}, {"clear", Command_Clear}, + {"cd", Command_Cd}, {"dir", Command_Dir} }; +static char *cDEFAULT_PATH[] = {"/Acess/Bin"}; #define BUILTIN_COUNT (sizeof(cBUILTINS)/sizeof(cBUILTINS[0])) // ==== LOCAL VARIABLES ==== + int giNumPathDirs = 1; +char **gasPathDirs = cDEFAULT_PATH; +char **gasEnvironment; char gsCommandBuffer[1024]; -char *gsCurrentDirectory = "/"; -char gsTmpBuffer[1024]; +char *gsCurrentDirectory = NULL; char **gasCommandHistory; int giLastCommand = 0; int giCommandSpace = 0; @@ -41,17 +47,28 @@ char **gasCommandHistory; int main(int argc, char *argv[], char *envp[]) { char *sCommandStr; - char *saArgs[32]; + char *saArgs[32] = {0}; int length = 0; - int pid = -1; + int i; int iArgCount = 0; int bCached = 1; - t_sysFInfo info; - //Command_Clear(0, NULL); + gasEnvironment = envp; + + Command_Clear(0, NULL); + + { + char *tmp = getenv("CWD"); + if(tmp) { + gsCurrentDirectory = malloc(strlen(tmp)+1); + strcpy(gsCurrentDirectory, tmp); + } else { + gsCurrentDirectory = malloc(2); + strcpy(gsCurrentDirectory, "/"); + } + } - write(_stdout, 36, "AcessOS/AcessBasic Shell Version 2\n"); - write(_stdout, 30, " Based on CLI Shell for IOOS\n"); + write(_stdout, 22, "Acess Shell Version 3\n"); write(_stdout, 2, "\n"); for(;;) { @@ -59,12 +76,18 @@ int main(int argc, char *argv[], char *envp[]) if(saArgs[0]) free(saArgs); if(!bCached) free(sCommandStr); bCached = 0; + write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory); - write(_stdout, 3, "$ "); + write(_stdout, 2, "$ "); // Read Command line sCommandStr = ReadCommandLine( &length ); + if(!sCommandStr) { + write(_stdout, 25, "PANIC: Out of heap space\n"); + return -1; + } + // Check if the command should be cached if(gasCommandHistory == NULL || strcmp(sCommandStr, gasCommandHistory[giLastCommand]) != 0) { @@ -88,44 +111,18 @@ int main(int argc, char *argv[], char *envp[]) if(saArgs[1][0] == '\0') continue; // Check Built-In Commands - // [HACK] Mem Usage - Use Length in place of `i' - for(length=0;length 0 ) break; + + free(ret); + ret = strdup( gasCommandHistory[--scrollbackPos] ); + + len = strlen(ret); + while(pos--) write(_stdout, 3, "\x1B[D"); + while(pos++ < len) write(_stdout, 3, "\x1B[C"); + break; + case 'B': // Down + if( scrollbackPos < giLastCommand-1 ) break; + free(ret); + ret = strdup( gasCommandHistory[++scrollbackPos] ); + + len = strlen(ret); + while(pos--) write(_stdout, 3, "\x1B[D"); + while(pos++ < len) write(_stdout, 3, "\x1B[C"); + break; + #endif + case 'D': // Left + if(pos == 0) break; + pos --; + write(_stdout, 3, "\x1B[D"); + break; + case 'C': // Right + if(pos == len-1) break; + pos++; + write(_stdout, 3, "\x1B[C"); + break; + } + } + continue; + } // Backspace if(ch == '\b') { if(len <= 0) continue; // Protect against underflows @@ -162,6 +204,13 @@ char *ReadCommandLine(int *Length) write(_stdout, 1, &ch); continue; } + // Tab + if(ch == '\t') { + //TODO: Implement Tab-Completion + //Currently just ignore tabs + continue; + } + // Expand Buffer if(len > space) { space += 256; @@ -193,6 +242,12 @@ void Parse_Args(char *str, char **dest) int i = 1; char *buf = malloc( strlen(str) + 1 ); + if(buf == NULL) { + dest[0] = NULL; + Print("Parse_Args: Out of heap space!\n"); + return ; + } + strcpy(buf, str); dest[0] = buf; @@ -224,73 +279,120 @@ void Parse_Args(char *str, char **dest) } /** - * \fn void Command_Colour(int argc, char **argv) - * \brief + * \fn void CallCommand(char **Args) */ -void Command_Colour(int argc, char **argv) +void CallCommand(char **Args) { - int fg, bg; - char clrStr[6] = "\x1B[37m"; + t_sysFInfo info; + int pid = -1; + int fd = 0; + char sTmpBuffer[1024]; + char *exefile = Args[0]; - // Verify Arg Count - if(argc < 2) + if(exefile[0] == '/' + || (exefile[0] == '.' && exefile[1] == '/') + || (exefile[0] == '.' && exefile[1] == '.' && exefile[2] == '/') + ) { - Print("Please specify a colour\n"); - goto usage; - } - - // Check Colour - for(fg=0;fg<8;fg++) - if(strcmp(cCOLOUR_NAMES[fg], argv[1]) == 0) - break; - - // Foreground a valid colour - if(fg == 8) { - Print("Unknown Colour '");Print(argv[1]);Print("'\n"); - goto usage; + GeneratePath(exefile, gsCurrentDirectory, sTmpBuffer); + // Check file existence + fd = open(sTmpBuffer, OPENFLAG_EXEC); + if(fd == -1) { + Print("Unknown Command: `");Print(Args[0]);Print("'\n"); // Error Message + return ; + } + + // Get File info and close file + finfo( fd, &info, 0 ); + close( fd ); + + // Check if the file is a directory + if(info.flags & FILEFLAG_DIRECTORY) { + Print("`");Print(sTmpBuffer); // Error Message + Print("' is a directory.\n"); + return ; + } } - // Set Foreground - clrStr[3] = '0' + fg; - write(_stdout, 6, clrStr); - - // Need to Set Background? - if(argc > 2) + else { - for(bg=0;bg<8;bg++) - if(strcmp(cCOLOUR_NAMES[bg], argv[2]) == 0) - break; - - // Valid colour - if(bg == 8) + int i; + + // Check all components of $PATH + for( i = 0; i < giNumPathDirs; i++ ) { - Print("Unknown Colour '");Print(argv[2]);Print("'\n"); - goto usage; + GeneratePath(exefile, gasPathDirs[i], sTmpBuffer); + fd = open(sTmpBuffer, OPENFLAG_EXEC); + if(fd == -1) continue; + finfo( fd, &info, 0 ); + close( fd ); + if(info.flags & FILEFLAG_DIRECTORY) continue; + // Woohoo! We found a valid command + break; + } + + // Exhausted path directories + if( i == giNumPathDirs ) { + Print("Unknown Command: `");Print(exefile);Print("'\n"); + return ; } + } - clrStr[2] = '4'; - clrStr[3] = '0' + bg; - write(_stdout, 6, clrStr); + // Create new process + pid = clone(CLONE_VM, 0); + // Start Task + if(pid == 0) + execve(sTmpBuffer, Args, gasEnvironment); + if(pid <= 0) { + Print("Unablt to create process: `");Print(sTmpBuffer);Print("'\n"); // Error Message } - // Return - return; - - // Function Usage (Requested via a Goto (I know it's ugly)) -usage: - Print("Valid Colours are "); - for(fg=0;fg<8;fg++) - { - Print(cCOLOUR_NAMES[fg]); - write(_stdout, 3, ", "); + else { + int status; + waittid(pid, &status); } - write(_stdout, 4, "\b\b\n"); +} + +/** + * \fn void Command_Logout(int argc, char **argv) + * \brief Exit the shell, logging the user out + */ +void Command_Logout(int argc, char **argv) +{ + exit(0); +} + +/** + * \fn void Command_Colour(int argc, char **argv) + * \brief Displays the help screen + */ +void Command_Help(int argc, char **argv) +{ + Print("Acess 2 Command Line Interface\n"); + Print(" By John Hodge (thePowersGang / [TPG])\n"); + Print("\n"); + Print("Builtin Commands:\n"); + Print(" logout: Return to the login prompt\n"); + Print(" exit: Same\n"); + Print(" help: Display this message\n"); + Print(" clear: Clear the screen\n"); + Print(" cd: Change the current directory\n"); + Print(" dir: Print the contents of the current directory\n"); + //Print("\n"); return; } +/** + * \fn void Command_Clear(int argc, char **argv) + * \brief Clear the screen + */ void Command_Clear(int argc, char **argv) { write(_stdout, 4, "\x1B[2J"); //Clear Screen } +/** + * \fn void Command_Cd(int argc, char **argv) + * \brief Change directory + */ void Command_Cd(int argc, char **argv) { char tmpPath[1024]; @@ -310,14 +412,137 @@ void Command_Cd(int argc, char **argv) write(_stdout, 26, "Directory does not exist\n"); return; } - finfo(fp, &stats); + finfo(fp, &stats, 0); close(fp); - if(!(stats.flags & FILEFLAG_DIRECTORY)) { + if( !(stats.flags & FILEFLAG_DIRECTORY) ) { write(_stdout, 17, "Not a Directory\n"); return; } + free(gsCurrentDirectory); + gsCurrentDirectory = malloc(strlen(tmpPath)+1); strcpy(gsCurrentDirectory, tmpPath); + + // Register change with kernel + chdir( gsCurrentDirectory ); } +/** + * \fn void Command_Dir(int argc, char **argv) + * \brief Print the contents of a directory + */ +void Command_Dir(int argc, char **argv) +{ + int dp, fp, dirLen; + char modeStr[11] = "RWXrwxRWX "; + char tmpPath[1024]; + char *fileName; + t_sysFInfo info; + t_sysACL acl; + + // Generate Directory Path + if(argc > 1) + dirLen = GeneratePath(argv[1], gsCurrentDirectory, tmpPath); + else + { + strcpy(tmpPath, gsCurrentDirectory); + } + dirLen = strlen(tmpPath); + + // Open Directory + dp = open(tmpPath, OPENFLAG_READ); + // Check if file opened + if(dp == -1) + { + printf("Unable to open directory `%s', File cannot be found\n", tmpPath); + return; + } + // Get File Stats + if( finfo(dp, &info, 0) == -1 ) + { + close(dp); + write(_stdout, 34, "stat Failed, Bad File Descriptor\n"); + return; + } + // Check if it's a directory + if(!(info.flags & FILEFLAG_DIRECTORY)) + { + close(dp); + write(_stdout, 27, "Unable to open directory `"); + write(_stdout, strlen(tmpPath)+1, tmpPath); + write(_stdout, 20, "', Not a directory\n"); + return; + } + + // Append Shash for file paths + if(tmpPath[dirLen-1] != '/') + { + tmpPath[dirLen++] = '/'; + tmpPath[dirLen] = '\0'; + } + + fileName = (char*)(tmpPath+dirLen); + // Read Directory Content + while( (fp = readdir(dp, fileName)) ) + { + if(fp < 0) + { + if(fp == -3) + write(_stdout, 42, "Invalid Permissions to traverse directory\n"); + break; + } + // Open File + fp = open(tmpPath, 0); + if(fp == -1) continue; + // Get File Stats + finfo(fp, &info, 0); + + if(info.flags & FILEFLAG_DIRECTORY) + write(_stdout, 1, "d"); + else + write(_stdout, 1, "-"); + + // Print Mode + // - Owner + acl.group = 0; acl.id = info.uid; + _SysGetACL(fp, &acl); + if(acl.perms & 1) modeStr[0] = 'r'; else modeStr[0] = '-'; + if(acl.perms & 2) modeStr[1] = 'w'; else modeStr[1] = '-'; + if(acl.perms & 8) modeStr[2] = 'x'; else modeStr[2] = '-'; + // - Group + acl.group = 1; acl.id = info.gid; + _SysGetACL(fp, &acl); + if(acl.perms & 1) modeStr[3] = 'r'; else modeStr[3] = '-'; + if(acl.perms & 2) modeStr[4] = 'w'; else modeStr[4] = '-'; + if(acl.perms & 8) modeStr[5] = 'x'; else modeStr[5] = '-'; + // - World + acl.group = 1; acl.id = -1; + _SysGetACL(fp, &acl); + if(acl.perms & 1) modeStr[6] = 'r'; else modeStr[6] = '-'; + if(acl.perms & 2) modeStr[7] = 'w'; else modeStr[7] = '-'; + if(acl.perms & 8) modeStr[8] = 'x'; else modeStr[8] = '-'; + write(_stdout, 10, modeStr); + close(fp); + + // Colour Code + if(info.flags & FILEFLAG_DIRECTORY) // Directory: Green + write(_stdout, 6, "\x1B[32m"); + // Default: White + + // Print Name + write(_stdout, strlen(fileName), fileName); + + // Print slash if applicable + if(info.flags & FILEFLAG_DIRECTORY) + write(_stdout, 1, "/"); + + // Revert Colour + write(_stdout, 6, "\x1B[37m"); + + // Newline! + write(_stdout, 1, "\n"); + } + // Close Directory + close(dp); +}