A UNIX emulation shell to access the underlying SDCard FileSystem through a terminal interface

Dependents:   Waldo_Embed_V2

Information

SDShell does not change the com baudrate. Access is made using the baud as initialized by the Serial object when passed into the SDShell object

Example

#include "mbed.h"
#include "SDFileSystem.h"
#include "SDShell.h"

Serial com(USBTX, USBRX);
SDFileSystem sd(p11, p12, p13, p14, "sd");
SDShell emulate;

int main()
{
    emulate.init();
    emulate.shell(com, sd, "/sd");
}
Revision:
2:b3107e463974
Parent:
1:514f321aa528
Child:
4:6ff0a3d92778
--- a/SDShell.cpp	Sat Apr 27 16:08:39 2013 +0000
+++ b/SDShell.cpp	Sat Apr 27 23:09:06 2013 +0000
@@ -13,10 +13,21 @@
 void SDShell::init(void)
 {
     // add known commands to a linked list
+    _cmds.attachMsg("ls"   , this, &SDShell::ls);
+    _cmds.attachMsg("cd"   , this, &SDShell::cd);
+    _cmds.attachMsg("pwd"  , this, &SDShell::pwd);
+    _cmds.attachMsg("head" , this, &SDShell::head);
+    _cmds.attachMsg("cat"  , this, &SDShell::cat);
+    _cmds.attachMsg("mkdir", this, &SDShell::create);
+    _cmds.attachMsg("touch", this, &SDShell::touch);
+    _cmds.attachMsg("rm"   , this, &SDShell::rm);
+    _cmds.attachMsg("exit" , this, &SDShell::exit);
+    _cmds.attachMsg("debug", this, &SDShell::debug);
+    
     return;
 }
 
-void SDShell::shell(Serial &com, SDFileSystem &storage, char *cwd)
+void SDShell::shell(Serial &com, SDFileSystem &storage, char const *cwd)
 {
     uint32_t done = 0;
 
@@ -25,64 +36,41 @@
     _storage = &storage;
 
     // put the current working directory to the root of the card - should be pulled in I think
-    strcpy(_cwd, "/sd");
+    strcpy(_cwd, cwd);
 
     while(0 == done) 
     {
         // gather input from the Serial object
         shellInput();
         // break up the command line arguemnt
-        _arg = split(_cmd, _cmd_line, 64, ' ');
+        _arg = split(_cmd, _cmdline, 64, ' ');
         // look at the arg and get paths and files separated if present
-        resolveDirectory(_new_path, _arg);
+        resolveDirectory(_newpath, _arg);
+        // print parsed members if we're debugging
         if(_debug)
         {
-            LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmd_line, _cmd, _arg, _new_path);
+            LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmdline, _cmd, _arg, _newpath);
         }
-
-        if (match(_cmd, "ls"))
-        {
-            ls(_new_path, _com);
-        } 
-        else if (match(_cmd, "cd")) 
-        {
-            cd(_new_path);
-        }
-        else if (match(_cmd, "pwd")) 
-        {
-            pwd(_com);
-        }
-        else if (match(_cmd, "head")) 
-        {
-            head(_new_path, _com);
-        }
-        else if (match(_cmd, "cat")) 
+        // now service known messages
+        char* result = _cmds.serviceMessage(_cmd);
+        // look at the result > 0 means we found somehting
+        if(result == (char *)EXIT)
         {
-            cat(_new_path, _com);
-        }
-        else if (match(_cmd, "mkdir")) 
-        {
-            mkdir(_new_path, 1023);
-        }
-        else if (match(_cmd, "debug")) 
-        {
-            _debug = !_debug;
+            done = 1;   // force an exit
         }
-        else if (match(_cmd, "touch"))
-        {
-            touch(_new_path, _com);
-        }
-        else if (match(_cmd, "rm"))
+        else if (result == (char *)UNKNOWN)    // didnt know what that was
         {
-            remove(_new_path);
-        }
-        else if (match(_cmd, "exit"))
-        {
-            done = true;
+            uint32_t cnt = 1;
+            LOG("Unknown Message from Terminal: Options are\n");
+            do
+            {
+                result = _cmds.messageLookup(cnt++);
+                _com->printf(" %s\n", result);
+            } while(result != NULL);
         }
         else
         {
-            _com->printf("%s: command not found\n", _cmd);
+            // that should have done something
         }
     }
 }
@@ -93,33 +81,33 @@
     char c;
     uint32_t done = 0;
     // clear the last command
-    memset(_cmd, 0, 64);
+//    memset(_cmdline, 0, SHELL_BUF_SIZE);
     _com->printf("# ", _cwd);
     do
     {
-        _cmd[i] = 0;
-        c = _com->getc();
-        if (c == '\r') 
+        _cmdline[i] = 0;    // clearing the next loc before using it is faster than memset
+        c = _com->getc();   // get a char
+        if (c == '\r')      // process on "enter"
         {
             done = 1;
         } 
-        else if (i < SHELL_BUF_MASK)
+        else if (i < SHELL_BUF_MASK)    // once full the user can only press enter
         {
-            if (c == 0x7f)
-            { // backspace
-                if (i > 0)
-                { // if we're at the beginning, do nothing
+            if (c == 0x7f)  // backspace
+            {
+                if (i > 0)  // if we're at the beginning, do nothing
+                {
                     i--;
                     _com->printf("\b \b");
                 }
             }
-            else
+            else    // valid keystrokes get stored and echo'd
             {
                 _com->putc(c);
-                _cmd[i++] = c;
+                _cmdline[i++] = c;
             }
         }
-    } while (0 == done);
+    } while(0 == done);
 
     _com->printf("\n");
 }
@@ -130,19 +118,19 @@
     char *v;
 
     // make sure pointers are valid (could validate RAM but that should be the caller responsibility)
-    if ((src == 0) || (dst == 0)) 
+    if ((dst == 0) || (src == 0)) 
     {
         return 0;
     }
-    // break up the string
+    // break up the string until delim is found
     while((*src != 0) && (*src != delim) && (i < max)) 
     {
         *(dst++) = *(src++);
         i++;
     }
-
-    *src = 0;
-    v = (*dst == '\0') ? src : (dst+1);
+    // return what comes after the delimiter - dst has before the delimiter
+    *dst = 0;
+    v = (*src == '\0') ? dst : (src+1);
 
     return v;
 }
@@ -184,14 +172,15 @@
 void SDShell::splitName(char *path, char *dirname, char *basename)
 {
     int sep = 0;
-    
+    // print the original path
     if (_debug)
     {
         LOG("%d\n", strlen(path));
     }
+    // find the directory backslash location in the path
     for (int i=strlen(path)-1; i >= 0; i--) 
     {
-        if (_debug)
+        if (_debug) // print what we found
         {
             LOG("- %c\n", path[i]);
         }
@@ -201,99 +190,154 @@
             break;
         }
     }
-    for (int j=0; j < sep; j++)
+    // extract the directory
+    for (int i=0; i < sep; i++)
     {
-        if (_debug)
+        if (_debug) // print what we found
         {
-            LOG("> %c\n", path[j]);
+            LOG("> %c\n", path[i]);
         }
-        dirname[j] = path[j];
-        dirname[j+1] = 0;
+        dirname[i] = path[i];
+        dirname[i+1] = 0;
     }
-    for (int k=sep+1; k < strlen(path); k++) 
+    // and then split the file from directory
+    for (int i=sep+1; i < strlen(path); i++) 
     {
-        if (_debug)
+        if (_debug) // print what we found
         {
-            LOG("* %c\n", path[k]);
+            LOG("* %c\n", path[i]);
         }
-        basename[k-(sep+1)] = path[k];
-        basename[k-sep] = 0;
+        basename[i-(sep+1)] = path[i];
+        basename[i-sep] = 0;
     }
-    if (_debug)
+    if (_debug) // print the the split
     {
         LOG("d:<%s> b:<%s>\n", dirname, basename);
     }
 }
 
-uint32_t SDShell::match(char *arg1, char *arg2)
+char *SDShell::ls(char *cmd)
 {
-    return (0 == strcmp(arg1, arg2)) ? 1 : 0;
+    if (_debug)
+    {
+        LOG("%s\n", _cwd);
+    }
+    
+    DIR *d = opendir(_newpath);
+    if (NULL != d)
+    {
+        struct dirent *p;
+        while ((p = readdir(d)) != NULL)
+        {
+            _com->printf(" %s\n", p->d_name);
+        }
+        closedir(d);
+    }
+    else
+    {
+        _com->printf("%s: No such directory\n", _newpath);
+    }
+    
+    return (char *)OK;
 }
 
-void SDShell::ls(char *path, Serial *pc)
+char *SDShell::cd(char *cmd)
 {
-    if (_debug) pc->printf("%s\n", _cwd);
-    DIR *d;
-    struct dirent *p;
+    strcpy(_cwd, _newpath);
+    
+    return (char *)OK;
+}
 
-    if ((d = opendir(path)) != NULL) {
-        while ((p = readdir(d)) != NULL) {
-            pc->printf(" %s\n", p->d_name);
-        }
-        closedir(d);
-    } else {
-        pc->printf("%s: No such directory\n", path);
-    }
+char *SDShell::pwd(char *path) 
+{
+    _com->printf("%s\n", _cwd);
+    
+    return (char *)OK;
 }
 
-void SDShell::cd(char *path)
+char *SDShell::head(char *cmd)
 {
-    strcpy(_cwd, path);
-}
-
-void SDShell::pwd(Serial *pc)
-{
-    pc->printf("%s\n", _cwd);
+    FILE *fp = fopen(_newpath, "r");
+    if (fp != NULL) 
+    {
+        uint32_t line = 0;
+        while ((0 == feof(fp)) && ((line++) < 10))
+        {
+            fgets(_buf, 512, fp);
+            _com->printf("%s", _buf);
+        }
+        fclose(fp);
+    } 
+    else
+    {
+        _com->printf("%s: No such file\n", _newpath);
+    }
+    
+    return (char *)OK;
 }
 
-void SDShell::head(char *path, Serial *pc)
+char *SDShell::cat(char *cmd)
 {
-    FILE *fp;
-    char line = 0;
-
-    if ((fp = fopen(path, "r")) != NULL) {
-        while (!feof(fp) && line++ < 10) {
-            fgets(_buf, 128, fp);
-            pc->printf("%s", _buf);
+    FILE *fp= fopen(_newpath, "r");
+    if (fp != NULL)
+    {
+        while (!feof(fp))
+        {
+            fread(_buf, 1, 512, fp);
+            _com->printf("%s", _buf);
         }
         fclose(fp);
-    } else {
-        pc->printf("%s: No such file\n", path);
     }
+    else
+    {
+        _com->printf("%s: No such file\n", _newpath);
+    }
+    
+    return (char *)OK;
 }
 
-void SDShell::cat(char *path, Serial *pc)
+char *SDShell::touch(char *cmd)
 {
-    FILE *fp;
+    FILE *fp = fopen(_newpath, "w");
+    if (fp != NULL)
+    {
+        _com->printf("%s: File created\n", _newpath);
+        fclose(fp);
+    }
+    else
+    {
+        _com->printf("%s: No such file\n", _newpath);
+    }
+    
+    return (char *)OK;
+}
 
-    if ((fp = fopen(path, "r")) != NULL) {
-        while (!feof(fp)) {
-            fgets(_buf, 128, fp);
-            pc->printf("%s", _buf);
-        }
-        fclose(fp);
-    } else {
-        pc->printf("%s: No such file\n", path);
-    }
+char *SDShell::create(char *cmd)
+{
+    mkdir(_newpath, 1023);
+    
+    return (char *)OK;
 }
 
-void SDShell::touch(char *path, Serial *pc)
+char *SDShell::rm(char *cmd)
 {
-    FILE *fp;
-    if ((fp = fopen(path, "w")) != NULL) {
-        fclose(fp);
-    } else {
-        pc->printf("%s: No such file\n", path);
-    }
+    remove(_newpath);
+    
+    return (char *)OK;
 }
 
+char *SDShell::exit(char *cmd)
+{
+    return (char *)EXIT;
+}
+
+char *SDShell::debug(char *cmd)
+{
+    _debug = !_debug;
+    
+    return (char *)OK;
+}
+
+
+
+