A UNIX emulation shell to access the underlying SDCard FileSystem through a terminal interface
Information
Dependencies not included with library:
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"); }
SDShell.cpp
- Committer:
- jekain314
- Date:
- 2013-05-05
- Revision:
- 4:6ff0a3d92778
- Parent:
- 2:b3107e463974
- Child:
- 5:3417ba8cb1e4
File content as of revision 4:6ff0a3d92778:
//http://mbed.org/users/shimniok/code/SDCardShell/file/792bddcf799d/main.cpp #include "SDShell.h" SDShell::SDShell() { _debug = 0; return; } 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("catb" , this, &SDShell::catb); _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 const *cwd) { uint32_t done = 0; // get local copies of the initialized objects _com = &com; _storage = &storage; // put the current working directory to the root of the card - should be pulled in I think strcpy(_cwd, cwd); while(0 == done) { // gather input from the Serial object shellInput(); // break up the command line arguemnt _arg = split(_cmd, _cmdline, 64, ' '); // look at the arg and get paths and files separated if present resolveDirectory(_newpath, _arg); // print parsed members if we're debugging if(_debug) { LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmdline, _cmd, _arg, _newpath); } // now service known messages char* result = _cmds.serviceMessage(_cmd); // look at the result > 0 means we found somehting if(result == (char *)EXIT) { done = 1; // force an exit } else if (result == (char *)UNKNOWN) // didnt know what that was { 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 { // that should have done something } } } void SDShell::shellInput(void) { int i=0; char c; uint32_t done = 0; // clear the last command // memset(_cmdline, 0, SHELL_BUF_SIZE); _com->printf("# ", _cwd); do { _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) // once full the user can only press enter { if (c == 0x7f) // backspace { if (i > 0) // if we're at the beginning, do nothing { i--; _com->printf("\b \b"); } } else // valid keystrokes get stored and echo'd { _com->putc(c); _cmdline[i++] = c; } } } while(0 == done); _com->printf("\n"); } char *SDShell::split(char *dst, char *src, int max, char delim) { int i = 0; char *v; // make sure pointers are valid (could validate RAM but that should be the caller responsibility) if ((dst == 0) || (src == 0)) { return 0; } // break up the string until delim is found while((*src != 0) && (*src != delim) && (i < max)) { *(dst++) = *(src++); i++; } // return what comes after the delimiter - dst has before the delimiter *dst = 0; v = (*src == '\0') ? dst : (src+1); return v; } void SDShell::resolveDirectory(char *newpath, char *path) { char basename[64], dirname[64]; // absolute path if (path[0] == '/') { strcpy(newpath, path); } // relative path else { strcpy(newpath, _cwd); // make sure something was passed if(path[0] != 0) { // add the backslash if the user didnt if(newpath[strlen(newpath)-1] != '/') { strcat(newpath, "/"); } strcat(newpath, path); } // Resolve .. references splitName(newpath, dirname, basename); if (0 == strcmp(basename, "..")) { splitName(dirname, newpath, basename); } } return; } 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) // print what we found { LOG("- %c\n", path[i]); } sep = i; if (path[i] == '/') { break; } } // extract the directory for (int i=0; i < sep; i++) { if (_debug) // print what we found { LOG("> %c\n", path[i]); } dirname[i] = path[i]; dirname[i+1] = 0; } // and then split the file from directory for (int i=sep+1; i < strlen(path); i++) { if (_debug) // print what we found { LOG("* %c\n", path[i]); } basename[i-(sep+1)] = path[i]; basename[i-sep] = 0; } if (_debug) // print the the split { LOG("d:<%s> b:<%s>\n", dirname, basename); } } char *SDShell::ls(char *cmd) { 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; } char *SDShell::cd(char *cmd) { strcpy(_cwd, _newpath); return (char *)OK; } char *SDShell::pwd(char *path) { _com->printf("%s\n", _cwd); return (char *)OK; } char *SDShell::head(char *cmd) { 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; } char *SDShell::cat(char *cmd) { FILE *fp= fopen(_newpath, "r"); if (fp != NULL) { while (!feof(fp)) { fread(_buf, 1, 512, fp); _com->printf("%s", _buf); } fclose(fp); } else { _com->printf("%s: No such file\n", _newpath); } return (char *)OK; } char *SDShell::catb(char *cmd) { FILE *fp= fopen(_newpath, "rb"); if (fp != NULL) { while (!feof(fp)) { fread(_buf, 1, 1, fp); _com->printf("%c", _buf); } fclose(fp); } else { _com->printf("%s: No such file\n", _newpath); } return (char *)OK; } char *SDShell::touch(char *cmd) { 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; } char *SDShell::create(char *cmd) { mkdir(_newpath, 1023); return (char *)OK; } char *SDShell::rm(char *cmd) { remove(_newpath); return (char *)OK; } char *SDShell::exit(char *cmd) { return (char *)EXIT; } char *SDShell::debug(char *cmd) { _debug = !_debug; return (char *)OK; }