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");
}
Committer:
sam_grove
Date:
Sat Apr 27 23:09:06 2013 +0000
Revision:
2:b3107e463974
Parent:
1:514f321aa528
Child:
4:6ff0a3d92778
Good working order - had bugs relating to using the wrong buffers and such. Should be corrected now

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 1:514f321aa528 1
sam_grove 1:514f321aa528 2 //http://mbed.org/users/shimniok/code/SDCardShell/file/792bddcf799d/main.cpp
sam_grove 0:618e98bf18ce 3
sam_grove 0:618e98bf18ce 4 #include "SDShell.h"
sam_grove 0:618e98bf18ce 5
sam_grove 0:618e98bf18ce 6 SDShell::SDShell()
sam_grove 0:618e98bf18ce 7 {
sam_grove 1:514f321aa528 8 _debug = 0;
sam_grove 1:514f321aa528 9
sam_grove 0:618e98bf18ce 10 return;
sam_grove 0:618e98bf18ce 11 }
sam_grove 0:618e98bf18ce 12
sam_grove 0:618e98bf18ce 13 void SDShell::init(void)
sam_grove 0:618e98bf18ce 14 {
sam_grove 1:514f321aa528 15 // add known commands to a linked list
sam_grove 2:b3107e463974 16 _cmds.attachMsg("ls" , this, &SDShell::ls);
sam_grove 2:b3107e463974 17 _cmds.attachMsg("cd" , this, &SDShell::cd);
sam_grove 2:b3107e463974 18 _cmds.attachMsg("pwd" , this, &SDShell::pwd);
sam_grove 2:b3107e463974 19 _cmds.attachMsg("head" , this, &SDShell::head);
sam_grove 2:b3107e463974 20 _cmds.attachMsg("cat" , this, &SDShell::cat);
sam_grove 2:b3107e463974 21 _cmds.attachMsg("mkdir", this, &SDShell::create);
sam_grove 2:b3107e463974 22 _cmds.attachMsg("touch", this, &SDShell::touch);
sam_grove 2:b3107e463974 23 _cmds.attachMsg("rm" , this, &SDShell::rm);
sam_grove 2:b3107e463974 24 _cmds.attachMsg("exit" , this, &SDShell::exit);
sam_grove 2:b3107e463974 25 _cmds.attachMsg("debug", this, &SDShell::debug);
sam_grove 2:b3107e463974 26
sam_grove 0:618e98bf18ce 27 return;
sam_grove 0:618e98bf18ce 28 }
sam_grove 0:618e98bf18ce 29
sam_grove 2:b3107e463974 30 void SDShell::shell(Serial &com, SDFileSystem &storage, char const *cwd)
sam_grove 0:618e98bf18ce 31 {
sam_grove 1:514f321aa528 32 uint32_t done = 0;
sam_grove 1:514f321aa528 33
sam_grove 1:514f321aa528 34 // get local copies of the initialized objects
sam_grove 0:618e98bf18ce 35 _com = &com;
sam_grove 1:514f321aa528 36 _storage = &storage;
sam_grove 1:514f321aa528 37
sam_grove 1:514f321aa528 38 // put the current working directory to the root of the card - should be pulled in I think
sam_grove 2:b3107e463974 39 strcpy(_cwd, cwd);
sam_grove 1:514f321aa528 40
sam_grove 1:514f321aa528 41 while(0 == done)
sam_grove 0:618e98bf18ce 42 {
sam_grove 1:514f321aa528 43 // gather input from the Serial object
sam_grove 1:514f321aa528 44 shellInput();
sam_grove 1:514f321aa528 45 // break up the command line arguemnt
sam_grove 2:b3107e463974 46 _arg = split(_cmd, _cmdline, 64, ' ');
sam_grove 1:514f321aa528 47 // look at the arg and get paths and files separated if present
sam_grove 2:b3107e463974 48 resolveDirectory(_newpath, _arg);
sam_grove 2:b3107e463974 49 // print parsed members if we're debugging
sam_grove 1:514f321aa528 50 if(_debug)
sam_grove 1:514f321aa528 51 {
sam_grove 2:b3107e463974 52 LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmdline, _cmd, _arg, _newpath);
sam_grove 1:514f321aa528 53 }
sam_grove 2:b3107e463974 54 // now service known messages
sam_grove 2:b3107e463974 55 char* result = _cmds.serviceMessage(_cmd);
sam_grove 2:b3107e463974 56 // look at the result > 0 means we found somehting
sam_grove 2:b3107e463974 57 if(result == (char *)EXIT)
sam_grove 1:514f321aa528 58 {
sam_grove 2:b3107e463974 59 done = 1; // force an exit
sam_grove 1:514f321aa528 60 }
sam_grove 2:b3107e463974 61 else if (result == (char *)UNKNOWN) // didnt know what that was
sam_grove 1:514f321aa528 62 {
sam_grove 2:b3107e463974 63 uint32_t cnt = 1;
sam_grove 2:b3107e463974 64 LOG("Unknown Message from Terminal: Options are\n");
sam_grove 2:b3107e463974 65 do
sam_grove 2:b3107e463974 66 {
sam_grove 2:b3107e463974 67 result = _cmds.messageLookup(cnt++);
sam_grove 2:b3107e463974 68 _com->printf(" %s\n", result);
sam_grove 2:b3107e463974 69 } while(result != NULL);
sam_grove 0:618e98bf18ce 70 }
sam_grove 0:618e98bf18ce 71 else
sam_grove 0:618e98bf18ce 72 {
sam_grove 2:b3107e463974 73 // that should have done something
sam_grove 0:618e98bf18ce 74 }
sam_grove 0:618e98bf18ce 75 }
sam_grove 1:514f321aa528 76 }
sam_grove 0:618e98bf18ce 77
sam_grove 1:514f321aa528 78 void SDShell::shellInput(void)
sam_grove 0:618e98bf18ce 79 {
sam_grove 1:514f321aa528 80 int i=0;
sam_grove 1:514f321aa528 81 char c;
sam_grove 1:514f321aa528 82 uint32_t done = 0;
sam_grove 1:514f321aa528 83 // clear the last command
sam_grove 2:b3107e463974 84 // memset(_cmdline, 0, SHELL_BUF_SIZE);
sam_grove 1:514f321aa528 85 _com->printf("# ", _cwd);
sam_grove 1:514f321aa528 86 do
sam_grove 0:618e98bf18ce 87 {
sam_grove 2:b3107e463974 88 _cmdline[i] = 0; // clearing the next loc before using it is faster than memset
sam_grove 2:b3107e463974 89 c = _com->getc(); // get a char
sam_grove 2:b3107e463974 90 if (c == '\r') // process on "enter"
sam_grove 1:514f321aa528 91 {
sam_grove 1:514f321aa528 92 done = 1;
sam_grove 1:514f321aa528 93 }
sam_grove 2:b3107e463974 94 else if (i < SHELL_BUF_MASK) // once full the user can only press enter
sam_grove 0:618e98bf18ce 95 {
sam_grove 2:b3107e463974 96 if (c == 0x7f) // backspace
sam_grove 2:b3107e463974 97 {
sam_grove 2:b3107e463974 98 if (i > 0) // if we're at the beginning, do nothing
sam_grove 2:b3107e463974 99 {
sam_grove 1:514f321aa528 100 i--;
sam_grove 1:514f321aa528 101 _com->printf("\b \b");
sam_grove 1:514f321aa528 102 }
sam_grove 1:514f321aa528 103 }
sam_grove 2:b3107e463974 104 else // valid keystrokes get stored and echo'd
sam_grove 1:514f321aa528 105 {
sam_grove 1:514f321aa528 106 _com->putc(c);
sam_grove 2:b3107e463974 107 _cmdline[i++] = c;
sam_grove 1:514f321aa528 108 }
sam_grove 0:618e98bf18ce 109 }
sam_grove 2:b3107e463974 110 } while(0 == done);
sam_grove 1:514f321aa528 111
sam_grove 1:514f321aa528 112 _com->printf("\n");
sam_grove 0:618e98bf18ce 113 }
sam_grove 0:618e98bf18ce 114
sam_grove 1:514f321aa528 115 char *SDShell::split(char *dst, char *src, int max, char delim)
sam_grove 0:618e98bf18ce 116 {
sam_grove 1:514f321aa528 117 int i = 0;
sam_grove 1:514f321aa528 118 char *v;
sam_grove 1:514f321aa528 119
sam_grove 1:514f321aa528 120 // make sure pointers are valid (could validate RAM but that should be the caller responsibility)
sam_grove 2:b3107e463974 121 if ((dst == 0) || (src == 0))
sam_grove 1:514f321aa528 122 {
sam_grove 1:514f321aa528 123 return 0;
sam_grove 1:514f321aa528 124 }
sam_grove 2:b3107e463974 125 // break up the string until delim is found
sam_grove 1:514f321aa528 126 while((*src != 0) && (*src != delim) && (i < max))
sam_grove 0:618e98bf18ce 127 {
sam_grove 1:514f321aa528 128 *(dst++) = *(src++);
sam_grove 1:514f321aa528 129 i++;
sam_grove 1:514f321aa528 130 }
sam_grove 2:b3107e463974 131 // return what comes after the delimiter - dst has before the delimiter
sam_grove 2:b3107e463974 132 *dst = 0;
sam_grove 2:b3107e463974 133 v = (*src == '\0') ? dst : (src+1);
sam_grove 1:514f321aa528 134
sam_grove 1:514f321aa528 135 return v;
sam_grove 1:514f321aa528 136 }
sam_grove 1:514f321aa528 137
sam_grove 1:514f321aa528 138 void SDShell::resolveDirectory(char *newpath, char *path)
sam_grove 1:514f321aa528 139 {
sam_grove 1:514f321aa528 140 char basename[64], dirname[64];
sam_grove 1:514f321aa528 141
sam_grove 1:514f321aa528 142 // absolute path
sam_grove 1:514f321aa528 143 if (path[0] == '/')
sam_grove 1:514f321aa528 144 {
sam_grove 1:514f321aa528 145 strcpy(newpath, path);
sam_grove 1:514f321aa528 146 }
sam_grove 1:514f321aa528 147 // relative path
sam_grove 1:514f321aa528 148 else
sam_grove 1:514f321aa528 149 {
sam_grove 1:514f321aa528 150 strcpy(newpath, _cwd);
sam_grove 1:514f321aa528 151 // make sure something was passed
sam_grove 1:514f321aa528 152 if(path[0] != 0)
sam_grove 0:618e98bf18ce 153 {
sam_grove 1:514f321aa528 154 // add the backslash if the user didnt
sam_grove 1:514f321aa528 155 if(newpath[strlen(newpath)-1] != '/')
sam_grove 1:514f321aa528 156 {
sam_grove 1:514f321aa528 157 strcat(newpath, "/");
sam_grove 1:514f321aa528 158 }
sam_grove 1:514f321aa528 159 strcat(newpath, path);
sam_grove 0:618e98bf18ce 160 }
sam_grove 1:514f321aa528 161 // Resolve .. references
sam_grove 1:514f321aa528 162 splitName(newpath, dirname, basename);
sam_grove 1:514f321aa528 163 if (0 == strcmp(basename, ".."))
sam_grove 1:514f321aa528 164 {
sam_grove 1:514f321aa528 165 splitName(dirname, newpath, basename);
sam_grove 1:514f321aa528 166 }
sam_grove 0:618e98bf18ce 167 }
sam_grove 0:618e98bf18ce 168
sam_grove 1:514f321aa528 169 return;
sam_grove 0:618e98bf18ce 170 }
sam_grove 0:618e98bf18ce 171
sam_grove 1:514f321aa528 172 void SDShell::splitName(char *path, char *dirname, char *basename)
sam_grove 1:514f321aa528 173 {
sam_grove 1:514f321aa528 174 int sep = 0;
sam_grove 2:b3107e463974 175 // print the original path
sam_grove 1:514f321aa528 176 if (_debug)
sam_grove 1:514f321aa528 177 {
sam_grove 1:514f321aa528 178 LOG("%d\n", strlen(path));
sam_grove 1:514f321aa528 179 }
sam_grove 2:b3107e463974 180 // find the directory backslash location in the path
sam_grove 1:514f321aa528 181 for (int i=strlen(path)-1; i >= 0; i--)
sam_grove 1:514f321aa528 182 {
sam_grove 2:b3107e463974 183 if (_debug) // print what we found
sam_grove 1:514f321aa528 184 {
sam_grove 1:514f321aa528 185 LOG("- %c\n", path[i]);
sam_grove 1:514f321aa528 186 }
sam_grove 1:514f321aa528 187 sep = i;
sam_grove 1:514f321aa528 188 if (path[i] == '/')
sam_grove 1:514f321aa528 189 {
sam_grove 1:514f321aa528 190 break;
sam_grove 1:514f321aa528 191 }
sam_grove 1:514f321aa528 192 }
sam_grove 2:b3107e463974 193 // extract the directory
sam_grove 2:b3107e463974 194 for (int i=0; i < sep; i++)
sam_grove 1:514f321aa528 195 {
sam_grove 2:b3107e463974 196 if (_debug) // print what we found
sam_grove 1:514f321aa528 197 {
sam_grove 2:b3107e463974 198 LOG("> %c\n", path[i]);
sam_grove 1:514f321aa528 199 }
sam_grove 2:b3107e463974 200 dirname[i] = path[i];
sam_grove 2:b3107e463974 201 dirname[i+1] = 0;
sam_grove 1:514f321aa528 202 }
sam_grove 2:b3107e463974 203 // and then split the file from directory
sam_grove 2:b3107e463974 204 for (int i=sep+1; i < strlen(path); i++)
sam_grove 1:514f321aa528 205 {
sam_grove 2:b3107e463974 206 if (_debug) // print what we found
sam_grove 1:514f321aa528 207 {
sam_grove 2:b3107e463974 208 LOG("* %c\n", path[i]);
sam_grove 1:514f321aa528 209 }
sam_grove 2:b3107e463974 210 basename[i-(sep+1)] = path[i];
sam_grove 2:b3107e463974 211 basename[i-sep] = 0;
sam_grove 1:514f321aa528 212 }
sam_grove 2:b3107e463974 213 if (_debug) // print the the split
sam_grove 1:514f321aa528 214 {
sam_grove 1:514f321aa528 215 LOG("d:<%s> b:<%s>\n", dirname, basename);
sam_grove 1:514f321aa528 216 }
sam_grove 1:514f321aa528 217 }
sam_grove 0:618e98bf18ce 218
sam_grove 2:b3107e463974 219 char *SDShell::ls(char *cmd)
sam_grove 1:514f321aa528 220 {
sam_grove 2:b3107e463974 221 if (_debug)
sam_grove 2:b3107e463974 222 {
sam_grove 2:b3107e463974 223 LOG("%s\n", _cwd);
sam_grove 2:b3107e463974 224 }
sam_grove 2:b3107e463974 225
sam_grove 2:b3107e463974 226 DIR *d = opendir(_newpath);
sam_grove 2:b3107e463974 227 if (NULL != d)
sam_grove 2:b3107e463974 228 {
sam_grove 2:b3107e463974 229 struct dirent *p;
sam_grove 2:b3107e463974 230 while ((p = readdir(d)) != NULL)
sam_grove 2:b3107e463974 231 {
sam_grove 2:b3107e463974 232 _com->printf(" %s\n", p->d_name);
sam_grove 2:b3107e463974 233 }
sam_grove 2:b3107e463974 234 closedir(d);
sam_grove 2:b3107e463974 235 }
sam_grove 2:b3107e463974 236 else
sam_grove 2:b3107e463974 237 {
sam_grove 2:b3107e463974 238 _com->printf("%s: No such directory\n", _newpath);
sam_grove 2:b3107e463974 239 }
sam_grove 2:b3107e463974 240
sam_grove 2:b3107e463974 241 return (char *)OK;
sam_grove 1:514f321aa528 242 }
sam_grove 1:514f321aa528 243
sam_grove 2:b3107e463974 244 char *SDShell::cd(char *cmd)
sam_grove 1:514f321aa528 245 {
sam_grove 2:b3107e463974 246 strcpy(_cwd, _newpath);
sam_grove 2:b3107e463974 247
sam_grove 2:b3107e463974 248 return (char *)OK;
sam_grove 2:b3107e463974 249 }
sam_grove 0:618e98bf18ce 250
sam_grove 2:b3107e463974 251 char *SDShell::pwd(char *path)
sam_grove 2:b3107e463974 252 {
sam_grove 2:b3107e463974 253 _com->printf("%s\n", _cwd);
sam_grove 2:b3107e463974 254
sam_grove 2:b3107e463974 255 return (char *)OK;
sam_grove 1:514f321aa528 256 }
sam_grove 1:514f321aa528 257
sam_grove 2:b3107e463974 258 char *SDShell::head(char *cmd)
sam_grove 1:514f321aa528 259 {
sam_grove 2:b3107e463974 260 FILE *fp = fopen(_newpath, "r");
sam_grove 2:b3107e463974 261 if (fp != NULL)
sam_grove 2:b3107e463974 262 {
sam_grove 2:b3107e463974 263 uint32_t line = 0;
sam_grove 2:b3107e463974 264 while ((0 == feof(fp)) && ((line++) < 10))
sam_grove 2:b3107e463974 265 {
sam_grove 2:b3107e463974 266 fgets(_buf, 512, fp);
sam_grove 2:b3107e463974 267 _com->printf("%s", _buf);
sam_grove 2:b3107e463974 268 }
sam_grove 2:b3107e463974 269 fclose(fp);
sam_grove 2:b3107e463974 270 }
sam_grove 2:b3107e463974 271 else
sam_grove 2:b3107e463974 272 {
sam_grove 2:b3107e463974 273 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 274 }
sam_grove 2:b3107e463974 275
sam_grove 2:b3107e463974 276 return (char *)OK;
sam_grove 1:514f321aa528 277 }
sam_grove 1:514f321aa528 278
sam_grove 2:b3107e463974 279 char *SDShell::cat(char *cmd)
sam_grove 1:514f321aa528 280 {
sam_grove 2:b3107e463974 281 FILE *fp= fopen(_newpath, "r");
sam_grove 2:b3107e463974 282 if (fp != NULL)
sam_grove 2:b3107e463974 283 {
sam_grove 2:b3107e463974 284 while (!feof(fp))
sam_grove 2:b3107e463974 285 {
sam_grove 2:b3107e463974 286 fread(_buf, 1, 512, fp);
sam_grove 2:b3107e463974 287 _com->printf("%s", _buf);
sam_grove 1:514f321aa528 288 }
sam_grove 1:514f321aa528 289 fclose(fp);
sam_grove 1:514f321aa528 290 }
sam_grove 2:b3107e463974 291 else
sam_grove 2:b3107e463974 292 {
sam_grove 2:b3107e463974 293 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 294 }
sam_grove 2:b3107e463974 295
sam_grove 2:b3107e463974 296 return (char *)OK;
sam_grove 1:514f321aa528 297 }
sam_grove 0:618e98bf18ce 298
sam_grove 2:b3107e463974 299 char *SDShell::touch(char *cmd)
sam_grove 1:514f321aa528 300 {
sam_grove 2:b3107e463974 301 FILE *fp = fopen(_newpath, "w");
sam_grove 2:b3107e463974 302 if (fp != NULL)
sam_grove 2:b3107e463974 303 {
sam_grove 2:b3107e463974 304 _com->printf("%s: File created\n", _newpath);
sam_grove 2:b3107e463974 305 fclose(fp);
sam_grove 2:b3107e463974 306 }
sam_grove 2:b3107e463974 307 else
sam_grove 2:b3107e463974 308 {
sam_grove 2:b3107e463974 309 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 310 }
sam_grove 2:b3107e463974 311
sam_grove 2:b3107e463974 312 return (char *)OK;
sam_grove 2:b3107e463974 313 }
sam_grove 0:618e98bf18ce 314
sam_grove 2:b3107e463974 315 char *SDShell::create(char *cmd)
sam_grove 2:b3107e463974 316 {
sam_grove 2:b3107e463974 317 mkdir(_newpath, 1023);
sam_grove 2:b3107e463974 318
sam_grove 2:b3107e463974 319 return (char *)OK;
sam_grove 1:514f321aa528 320 }
sam_grove 1:514f321aa528 321
sam_grove 2:b3107e463974 322 char *SDShell::rm(char *cmd)
sam_grove 1:514f321aa528 323 {
sam_grove 2:b3107e463974 324 remove(_newpath);
sam_grove 2:b3107e463974 325
sam_grove 2:b3107e463974 326 return (char *)OK;
sam_grove 1:514f321aa528 327 }
sam_grove 1:514f321aa528 328
sam_grove 2:b3107e463974 329 char *SDShell::exit(char *cmd)
sam_grove 2:b3107e463974 330 {
sam_grove 2:b3107e463974 331 return (char *)EXIT;
sam_grove 2:b3107e463974 332 }
sam_grove 2:b3107e463974 333
sam_grove 2:b3107e463974 334 char *SDShell::debug(char *cmd)
sam_grove 2:b3107e463974 335 {
sam_grove 2:b3107e463974 336 _debug = !_debug;
sam_grove 2:b3107e463974 337
sam_grove 2:b3107e463974 338 return (char *)OK;
sam_grove 2:b3107e463974 339 }
sam_grove 2:b3107e463974 340
sam_grove 2:b3107e463974 341
sam_grove 2:b3107e463974 342
sam_grove 2:b3107e463974 343