Usermode/CLIShell - Fixed not catching execve returning
[tpg/acess2.git] / Usermode / Applications / CLIShell_src / main.c
index 2e51419..89bfe0d 100644 (file)
@@ -1,12 +1,17 @@
 /*\r
  * AcessOS Shell Version 3\r
  */\r
+#define USE_READLINE   1\r
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
 #include <stdio.h>\r
 #include <string.h>\r
 #include "header.h"\r
 \r
+#if USE_READLINE\r
+# include "readline.h"\r
+#endif\r
+\r
 #define _stdin 0\r
 #define _stdout        1\r
 #define _stderr        2\r
@@ -17,18 +22,17 @@ void        Parse_Args(char *str, char **dest);
 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_Help(int argc, char **argv);\r
 void   Command_Cd(int argc, char **argv);\r
 void   Command_Dir(int argc, char **argv);\r
 \r
 // ==== CONSTANT GLOBALS ====\r
-char   *cCOLOUR_NAMES[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};\r
 struct {\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
+       {"help", Command_Help}, {"clear", Command_Clear},\r
        {"cd", Command_Cd}, {"dir", Command_Dir}\r
 };\r
 static char    *cDEFAULT_PATH[] = {"/Acess/Bin"};\r
@@ -45,14 +49,18 @@ char        **gasCommandHistory;
  int   giCommandSpace = 0;\r
 \r
 // ==== CODE ====\r
-int main(int argc, char *argv[], char *envp[])\r
+int main(int argc, char *argv[], char **envp)\r
 {\r
        char    *sCommandStr;\r
        char    *saArgs[32] = {0};\r
         int    length = 0;\r
         int    i;\r
         int    iArgCount = 0;\r
+       #if !USE_READLINE\r
         int    bCached = 1;\r
+       #else\r
+       tReadline       *readline_state = Readline_Init(1);\r
+       #endif\r
        \r
        gasEnvironment = envp;\r
        \r
@@ -69,22 +77,28 @@ int main(int argc, char *argv[], char *envp[])
                }\r
        }       \r
        \r
-       write(_stdout, 22, "Acess Shell Version 3\n");\r
-       write(_stdout,  2, "\n");\r
+       printf("Acess Shell Version 3\n\n");\r
        for(;;)\r
        {\r
                // Free last command & arguments\r
                if(saArgs[0])   free(saArgs);\r
+               #if !USE_READLINE\r
                if(!bCached)    free(sCommandStr);\r
                bCached = 0;\r
-               write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory);\r
-               write(_stdout, 3, "$ ");\r
+               #endif\r
+               \r
+               printf("%s$ ", gsCurrentDirectory);\r
                \r
                // Read Command line\r
+               #if USE_READLINE\r
+               sCommandStr = Readline( readline_state );\r
+               printf("\n");\r
+               length = strlen(sCommandStr);\r
+               #else\r
                sCommandStr = ReadCommandLine( &length );\r
                \r
                if(!sCommandStr) {\r
-                       write(_stdout, 25, "PANIC: Out of heap space\n");\r
+                       printf("PANIC: Out of heap space\n");\r
                        return -1;\r
                }\r
                \r
@@ -99,6 +113,7 @@ int main(int argc, char *argv[], char *envp[])
                        gasCommandHistory[ giLastCommand ] = sCommandStr;\r
                        bCached = 1;\r
                }\r
+               #endif\r
                \r
                // Parse Command Line into arguments\r
                Parse_Args(sCommandStr, saArgs);\r
@@ -123,9 +138,14 @@ int main(int argc, char *argv[], char *envp[])
                \r
                // Shall we?\r
                CallCommand( &saArgs[1] );\r
+               \r
+               #if USE_READLINE\r
+               free( sCommandStr );\r
+               #endif\r
        }\r
 }\r
 \r
+#if !USE_READLINE\r
 /**\r
  * \fn char *ReadCommandLine(int *Length)\r
  * \brief Read from the command line\r
@@ -135,6 +155,9 @@ char *ReadCommandLine(int *Length)
        char    *ret;\r
         int    len, pos, space = 1023;\r
        char    ch;\r
+       #if 0\r
+        int    scrollbackPos = giLastCommand;\r
+       #endif\r
         \r
        // Preset Variables\r
        ret = malloc( space+1 );\r
@@ -143,65 +166,124 @@ char *ReadCommandLine(int *Length)
                \r
        // Read In Command Line\r
        do {\r
-               read(_stdin, 1, &ch);   // Read Character from stdin (read is a blocking call)\r
+               ch = getchar(); // Read Character from stdin (read is a blocking call)\r
+               if(ch == '\n')  break;\r
+               \r
+               switch(ch)\r
+               {\r
                // Control characters\r
-               if(ch == '\x1B') {\r
-                       read(_stdin, 1, &ch);   // Read control character\r
+               case '\x1B':\r
+                       ch = getchar(); // Read control character\r
                        switch(ch)\r
                        {\r
-                       case 'D':       if(pos) pos--;  break;\r
-                       case 'C':       if(pos<len)     pos++;  break;\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
+                               ch = getchar(); // Read control character\r
                                switch(ch)\r
                                {\r
-                               case 'D':       if(pos) pos--;  break;\r
-                               case 'C':       if(pos<len)     pos++;  break;\r
+                               #if 0\r
+                               case 'A':       // Up\r
+                                       {\r
+                                                int    oldLen = len;\r
+                                               if( scrollbackPos > 0 ) break;\r
+                                               \r
+                                               free(ret);\r
+                                               ret = strdup( gasCommandHistory[--scrollbackPos] );\r
+                                               \r
+                                               len = strlen(ret);\r
+                                               while(pos--)    printf("\x1B[D");\r
+                                               write(_stdout, len, ret);       pos = len;\r
+                                               while(pos++ < oldLen)   write(_stdout, 1, " ");\r
+                                       }\r
+                                       break;\r
+                               case 'B':       // Down\r
+                                       {\r
+                                                int    oldLen = len;\r
+                                               if( scrollbackPos < giLastCommand-1 )   break;\r
+                                               \r
+                                               free(ret);\r
+                                               ret = strdup( gasCommandHistory[++scrollbackPos] );\r
+                                               \r
+                                               len = strlen(ret);\r
+                                               while(pos--)    write(_stdout, 3, "\x1B[D");\r
+                                               write(_stdout, len, ret);       pos = len;\r
+                                               while(pos++ < oldLen)   write(_stdout, 1, " ");\r
+                                       }\r
+                                       break;\r
+                               #endif\r
+                               case 'D':       // Left\r
+                                       if(pos == 0)    break;\r
+                                       pos --;\r
+                                       printf("\x1B[D");\r
+                                       break;\r
+                               case 'C':       // Right\r
+                                       if(pos == len)  break;\r
+                                       pos++;\r
+                                       printf("\x1B[C");\r
+                                       break;\r
                                }\r
                        }\r
-                       continue;\r
-               }\r
+                       break;\r
+               \r
                // Backspace\r
-               if(ch == '\b') {\r
-                       if(len <= 0)            continue;       // Protect against underflows\r
+               case '\b':\r
+                       if(len <= 0)            break;  // Protect against underflows\r
+                       putchar(ch);\r
                        if(pos == len) {        // Simple case of end of string\r
-                               len --; pos--;\r
-                       } else {\r
+                               len --;\r
+                               pos--;\r
+                       }\r
+                       else {\r
+                               printf("%.*s ", len-pos, &ret[pos]);    // Move Text\r
+                               printf("\x1B[%iD", len-pos+1);\r
+                               // Alter Buffer\r
                                memmove(&ret[pos-1], &ret[pos], len-pos);\r
                                pos --;\r
                                len --;\r
                        }\r
-                       write(_stdout, 1, &ch);\r
-                       continue;\r
-               }\r
+                       break;\r
+               \r
                // Tab\r
-               if(ch == '\t') {\r
+               case '\t':\r
                        //TODO: Implement Tab-Completion\r
                        //Currently just ignore tabs\r
-                       continue;\r
-               }\r
+                       break;\r
                \r
-               // Expand Buffer\r
-               if(len > space) {\r
-                       space += 256;\r
-                       ret = realloc(ret, space+1);\r
-                       if(!ret)        return NULL;\r
+               default:                \r
+                       // Expand Buffer\r
+                       if(len+1 > space) {\r
+                               space += 256;\r
+                               ret = realloc(ret, space+1);\r
+                               if(!ret)        return NULL;\r
+                       }\r
+                       \r
+                       // Editing inside the buffer\r
+                       if(pos != len) {\r
+                               putchar(ch);    // Print new character\r
+                               printf("%.*s", len-pos, &ret[pos]);     // Move Text\r
+                               printf("\x1B[%iD", len-pos);\r
+                               memmove( &ret[pos+1], &ret[pos], len-pos );\r
+                       }\r
+                       else {\r
+                               putchar(ch);\r
+                       }\r
+                       ret[pos++] = ch;\r
+                       len ++;\r
+                       break;\r
                }\r
-               \r
-               write(_stdout, 1, &ch);\r
-               ret[pos++] = ch;\r
-               len ++;\r
        } while(ch != '\n');\r
        \r
-       // Remove newline\r
-       pos --;\r
-       ret[pos] = '\0';\r
+       // Cap String\r
+       ret[len] = '\0';\r
+       printf("\n");\r
        \r
        // Return length\r
        if(Length)      *Length = len;\r
        \r
        return ret;\r
 }\r
+#endif\r
 \r
 /**\r
  * \fn void Parse_Args(char *str, char **dest)\r
@@ -214,7 +296,7 @@ void Parse_Args(char *str, char **dest)
        \r
        if(buf == NULL) {\r
                dest[0] = NULL;\r
-               Print("Parse_Args: Out of heap space!\n");\r
+               printf("Parse_Args: Out of heap space!\n");\r
                return ;\r
        }\r
        \r
@@ -268,7 +350,7 @@ void CallCommand(char **Args)
                // 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
+                       printf("Unknown Command: `%s'\n", Args[0]);     // Error Message\r
                        return ;\r
                }\r
                \r
@@ -278,8 +360,7 @@ void CallCommand(char **Args)
                \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
+                       printf("`%s' is a directory.\n", sTmpBuffer);\r
                        return ;\r
                }\r
        }\r
@@ -302,7 +383,7 @@ void CallCommand(char **Args)
                \r
                // Exhausted path directories\r
                if( i == giNumPathDirs ) {\r
-                       Print("Unknown Command: `");Print(exefile);Print("'\n");\r
+                       printf("Unknown Command: `%s'\n", exefile);\r
                        return ;\r
                }\r
        }\r
@@ -310,10 +391,13 @@ void CallCommand(char **Args)
        // Create new process\r
        pid = clone(CLONE_VM, 0);\r
        // Start Task\r
-       if(pid == 0)\r
+       if(pid == 0) {\r
                execve(sTmpBuffer, Args, gasEnvironment);\r
+               printf("Execve returned, ... oops\n");\r
+               exit(-1);\r
+       }\r
        if(pid <= 0) {\r
-               Print("Unablt to create process: `");Print(sTmpBuffer);Print("'\n");    // Error Message\r
+               printf("Unable to create process: `%s'\n", sTmpBuffer); // Error Message\r
        }\r
        else {\r
                 int    status;\r
@@ -331,76 +415,31 @@ void Command_Logout(int argc, char **argv)
 }\r
 \r
 /**\r
- * \fn void Command_Clear(int argc, char **argv)\r
- * \brief Clear the screen\r
+ * \fn void Command_Colour(int argc, char **argv)\r
+ * \brief Displays the help screen\r
  */\r
-void Command_Clear(int argc, char **argv)\r
+void Command_Help(int argc, char **argv)\r
 {\r
-       write(_stdout, 4, "\x1B[2J");   //Clear Screen\r
+       printf( "Acess 2 Command Line Interface\n"\r
+               " By John Hodge (thePowersGang / [TPG])\n"\r
+               "\n"\r
+               "Builtin Commands:\n"\r
+               " logout: Return to the login prompt\n"\r
+               " exit:   Same\n"\r
+               " help:   Display this message\n"\r
+               " clear:  Clear the screen\n"\r
+               " cd:     Change the current directory\n"\r
+               " dir:    Print the contents of the current directory\n");\r
+       return;\r
 }\r
 \r
 /**\r
- * \fn void Command_Colour(int argc, char **argv)\r
- * \brief Set the colour of the shell prompt\r
- * \note Conflicts with coloured `dir` display\r
+ * \fn void Command_Clear(int argc, char **argv)\r
+ * \brief Clear the screen\r
  */\r
-void Command_Colour(int argc, char **argv)\r
+void Command_Clear(int argc, char **argv)\r
 {\r
-       int fg, bg;\r
-       char    clrStr[6] = "\x1B[37m";\r
-       \r
-       // Verify Arg Count\r
-       if(argc < 2)\r
-       {\r
-               goto usage;\r
-       }\r
-       \r
-       // Check Colour\r
-       for(fg=0;fg<8;fg++)\r
-               if(strcmp(cCOLOUR_NAMES[fg], argv[1]) == 0)\r
-                       break;\r
-\r
-       // Foreground a valid colour\r
-       if(fg == 8) {\r
-               Print("Unknown Colour '");Print(argv[1]);Print("'\n");\r
-               goto usage;\r
-       }\r
-       // Set Foreground\r
-       clrStr[3] = '0' + fg;\r
-       write(_stdout, 6, clrStr);\r
-       \r
-       // Need to Set Background?\r
-       if(argc > 2)\r
-       {\r
-               for(bg=0;bg<8;bg++)\r
-                       if(strcmp(cCOLOUR_NAMES[bg], argv[2]) == 0)\r
-                               break;\r
-       \r
-               // Valid colour\r
-               if(bg == 8)\r
-               {\r
-                       Print("Unknown Colour '");Print(argv[2]);Print("'\n");\r
-                       goto usage;\r
-               }\r
-       \r
-               clrStr[2] = '4';\r
-               clrStr[3] = '0' + bg;\r
-               write(_stdout, 6, clrStr);\r
-       }\r
-       // Return\r
-       return;\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
-               Print(cCOLOUR_NAMES[fg]);\r
-               write(_stdout, 3, ", ");\r
-       }\r
-       write(_stdout, 4, "\b\b\n");\r
-       return;\r
+       write(_stdout, "\x1B[2J", 4);   //Clear Screen\r
 }\r
 \r
 /**\r
@@ -415,7 +454,7 @@ void Command_Cd(int argc, char **argv)
        \r
        if(argc < 2)\r
        {\r
-               Print(gsCurrentDirectory);Print("\n");\r
+               printf("%s\n", gsCurrentDirectory);\r
                return;\r
        }\r
        \r
@@ -423,14 +462,14 @@ void Command_Cd(int argc, char **argv)
        \r
        fp = open(tmpPath, 0);\r
        if(fp == -1) {\r
-               write(_stdout, 26, "Directory does not exist\n");\r
+               printf("Directory does not exist\n");\r
                return;\r
        }\r
        finfo(fp, &stats, 0);\r
        close(fp);\r
        \r
        if( !(stats.flags & FILEFLAG_DIRECTORY) ) {\r
-               write(_stdout, 17, "Not a Directory\n");\r
+               printf("Not a Directory\n");\r
                return;\r
        }\r
        \r
@@ -476,16 +515,14 @@ void Command_Dir(int argc, char **argv)
        if( finfo(dp, &info, 0) == -1 )\r
        {\r
                close(dp);\r
-               write(_stdout, 34, "stat Failed, Bad File Descriptor\n");\r
+               printf("stat Failed, Bad File Descriptor\n");\r
                return;\r
        }\r
        // Check if it's a directory\r
        if(!(info.flags & FILEFLAG_DIRECTORY))\r
        {\r
                close(dp);\r
-               write(_stdout, 27, "Unable to open directory `");\r
-               write(_stdout, strlen(tmpPath)+1, tmpPath);\r
-               write(_stdout, 20, "', Not a directory\n");\r
+               printf("Unable to open directory `%s', Not a directory\n", tmpPath);\r
                return;\r
        }\r
        \r
@@ -503,7 +540,7 @@ void Command_Dir(int argc, char **argv)
                if(fp < 0)\r
                {\r
                        if(fp == -3)\r
-                               write(_stdout, 42, "Invalid Permissions to traverse directory\n");\r
+                               printf("Invalid Permissions to traverse directory\n");\r
                        break;\r
                }\r
                // Open File\r
@@ -513,49 +550,49 @@ void Command_Dir(int argc, char **argv)
                finfo(fp, &info, 0);\r
                \r
                if(info.flags & FILEFLAG_DIRECTORY)\r
-                       write(_stdout, 1, "d");\r
+                       printf("d");\r
                else\r
-                       write(_stdout, 1, "-");\r
+                       printf("-");\r
                \r
                // Print Mode\r
                // - Owner\r
-               acl.group = 0;  acl.id = info.uid;\r
+               acl.object = 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
+               acl.object = info.gid | 0x80000000;\r
                _SysGetACL(fp, &acl);\r
                if(acl.perms & 1)       modeStr[3] = 'r';       else    modeStr[3] = '-';\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
+               acl.object = 0xFFFFFFFF;\r
                _SysGetACL(fp, &acl);\r
                if(acl.perms & 1)       modeStr[6] = 'r';       else    modeStr[6] = '-';\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
+               printf(modeStr);\r
                close(fp);\r
                \r
                // Colour Code\r
                if(info.flags & FILEFLAG_DIRECTORY)     // Directory: Green\r
-                       write(_stdout, 6, "\x1B[32m");\r
+                       printf("\x1B[32m");\r
                // Default: White\r
                \r
                // Print Name\r
-               write(_stdout, strlen(fileName), fileName);\r
+               printf("%s", fileName);\r
                \r
                // Print slash if applicable\r
                if(info.flags & FILEFLAG_DIRECTORY)\r
-                       write(_stdout, 1, "/");\r
+                       printf("/");\r
                \r
                // Revert Colour\r
-               write(_stdout, 6, "\x1B[37m");\r
+               printf("\x1B[37m");\r
                \r
                // Newline!\r
-               write(_stdout, 1, "\n");\r
+               printf("\n");\r
        }\r
        // Close Directory\r
        close(dp);\r

UCC git Repository :: git.ucc.asn.au