Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[tpg/acess2.git] / KernelLand / Kernel / emergency_console.c
diff --git a/KernelLand/Kernel/emergency_console.c b/KernelLand/Kernel/emergency_console.c
new file mode 100644 (file)
index 0000000..dd6d708
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Acess 2 Kernel
+ * - By John Hodge (thePowersGang)
+ * 
+ * emergency_console.c
+ * - Kernel-land emergency console/shell
+ */
+#include <acess.h>
+#include <stdarg.h>
+
+#define STDIN  0
+#define STDOUT 1
+#define STDERR 2
+
+// === PROTOTYPES ===
+void EmergencyConsole(void);
+// -- Commands
+void Command_ls(const char* path);
+void Command_hd(const char* path);
+void Command_mount(const char *fs, const char *dev, const char *point);
+// --
+static char **split_args(char *line);
+static char *read_line(int fd);
+static int dprintf(int fd, const char *fmt, ...);// __attribute__((printf(2,3)));
+
+// === CODE ===
+void EmergencyConsole(void)
+{
+       for(;;)
+       {
+               dprintf(STDOUT, "(kernel)$ ");
+               char *line = read_line(STDIN);
+               
+               // Explode line into args
+               char **args = split_args(line);
+               // Get command from first arg
+               ASSERT(args);
+               ASSERT(args[0]);
+               if( strcmp(args[0], "help") == 0 ) {
+                       dprintf(STDOUT,
+                               "Commands:\n"
+                               "ls <path> - List the contents of a directory\n"
+                               "hd <path> - Dump a file in a 16 bytes/line hex format\n"
+                               "mount <fs> <device> <point> - Mount a filesystem\n"
+                               );
+               }
+               else if( strcmp(args[0], "ls") == 0 ) {
+                       Command_ls(args[1]); 
+               }
+               else if( strcmp(args[0], "hd") == 0 ) {
+                       Command_hd(args[1]);
+               }
+               else if( strcmp(args[0], "mount") == 0 ) {
+                       Command_mount(args[1], args[2], args[3]);
+               }
+               else
+               {
+                       dprintf(STDERR, "Unknown command '%s'\n", args[0]);
+               }
+               // Free args
+               free(args);
+               free(line);
+       }
+}
+
+void Command_ls(const char* path)
+{
+       dprintf(STDERR, "ls: TODO - Implement\n");
+}
+void Command_hd(const char* path)
+{
+       dprintf(STDERR, "hd: TODO - Implement\n");
+}
+void Command_mount(const char *fs, const char *dev, const char *point)
+{
+       dprintf(STDERR, "mount: TODO - Implement\n");
+}
+
+// Allocates return array (NUL terminated), but mangles input string
+static int split_args_imp(char *line, char **buf)
+{
+        int    argc = 0;
+        int    pos = 0;
+       enum {
+               MODE_SPACE,
+               MODE_NORM,
+               MODE_SQUOTE,
+               MODE_DQUOTE,
+       } mode = MODE_SPACE;
+       for( char *chp = line; *chp; chp ++ )
+       {
+               if( *chp == ' ' ) {
+                       if( mode != MODE_SPACE ) {
+                               if(buf) buf[argc][pos] = '\0';
+                               argc ++;
+                       }
+                       mode = MODE_SPACE;
+                       continue ;
+               }
+               
+               switch( mode )
+               {
+               case MODE_SPACE:
+                       if( buf )
+                               buf[argc] = chp;
+                       pos = 0;
+               case MODE_NORM:
+                       switch( *chp )
+                       {
+                       case '"':
+                               mode = MODE_DQUOTE;
+                               break;
+                       case '\'':
+                               mode = MODE_SQUOTE;
+                               break;
+                       case '\\':
+                               chp ++;
+                               switch( *chp )
+                               {
+                               case '\0':
+                                       dprintf(STDERR, "err: Trailing '\\'\n");
+                                       break;
+                               case '\\':
+                               case '\'':
+                               case '"':
+                                       if(buf) buf[argc][pos++] = *chp;
+                                       break;
+                               default:
+                                       dprintf(STDERR, "err: Unkown escape '%c'\n", *chp);
+                                       break;
+                               }
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               case MODE_SQUOTE:
+                       switch( *chp )
+                       {
+                       case '\'':
+                               mode = MODE_NORM;
+                               break;
+                       case '\0':
+                               dprintf(STDERR, "err: Unterminated \' string\n");
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               case MODE_DQUOTE:
+                       switch( *chp )
+                       {
+                       case '\"':
+                               mode = MODE_NORM;
+                               break;
+                       case '\\':
+                               chp ++;
+                               switch(*chp)
+                               {
+                               case '\0':
+                                       dprintf(STDERR, "err: Trailing '\\' in \" string\n");
+                                       break;
+                               case '\\':
+                               case '"':
+                                       if(buf) buf[argc][pos++] = *chp;
+                                       break;
+                               default:
+                                       dprintf(STDERR, "err: Unkown escape '%c'\n", *chp);
+                                       break;
+                               }
+                               break;
+                       case '\0':
+                               dprintf(STDERR, "err: Unterminated \" string\n");
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               }
+       }
+
+       if(buf) buf[argc][pos++] = '\0';
+       argc ++;
+       return argc;
+}
+static char **split_args(char *line)
+{
+       // 1. Count
+       int count = split_args_imp(line, NULL);
+       char **ret = malloc( (count + 1) * sizeof(char*) );
+       
+       split_args_imp(line, ret);
+       ret[count] = NULL;
+       return ret;
+}
+
+static char *read_line(int fd)
+{
+       // Read line (or up to ~128 bytes)
+       // - This assumes a default PTY state (i.e. line buffered, echo on)
+       char *ret = malloc(128);
+       size_t len = VFS_Read(STDIN, 128, ret);
+       ret[len] = 0;
+       return ret;
+}
+
+static int dprintf(int fd, const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       size_t len = vsnprintf(NULL, 0, fmt, args);
+       va_end(args);
+       
+       char buf[len+1];
+       va_start(args, fmt);
+       vsnprintf(buf, len+1, fmt, args);
+       va_end(args);
+       
+       VFS_Write(fd, len, buf);
+       
+       return len;
+}
+

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