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:
jekain314
Date:
Wed May 08 06:16:46 2013 +0000
Revision:
8:30aa615d4508
Parent:
7:7892fcd8a1ad
Child:
9:5e1764ff5dfa
Changed parser to accept '\r' or '\n'. Minor change to bcat but not relevant. may consider renaming the feature.

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 5:3417ba8cb1e4 21 _cmds.attachMsg("bcat" , this, &SDShell::bcat);
sam_grove 2:b3107e463974 22 _cmds.attachMsg("mkdir", this, &SDShell::create);
sam_grove 2:b3107e463974 23 _cmds.attachMsg("touch", this, &SDShell::touch);
sam_grove 2:b3107e463974 24 _cmds.attachMsg("rm" , this, &SDShell::rm);
sam_grove 2:b3107e463974 25 _cmds.attachMsg("exit" , this, &SDShell::exit);
sam_grove 2:b3107e463974 26 _cmds.attachMsg("debug", this, &SDShell::debug);
sam_grove 2:b3107e463974 27
sam_grove 0:618e98bf18ce 28 return;
sam_grove 0:618e98bf18ce 29 }
sam_grove 0:618e98bf18ce 30
sam_grove 2:b3107e463974 31 void SDShell::shell(Serial &com, SDFileSystem &storage, char const *cwd)
sam_grove 0:618e98bf18ce 32 {
sam_grove 1:514f321aa528 33 uint32_t done = 0;
sam_grove 1:514f321aa528 34
sam_grove 1:514f321aa528 35 // get local copies of the initialized objects
sam_grove 0:618e98bf18ce 36 _com = &com;
sam_grove 1:514f321aa528 37 _storage = &storage;
sam_grove 1:514f321aa528 38
sam_grove 1:514f321aa528 39 // put the current working directory to the root of the card - should be pulled in I think
sam_grove 2:b3107e463974 40 strcpy(_cwd, cwd);
sam_grove 1:514f321aa528 41
sam_grove 1:514f321aa528 42 while(0 == done)
sam_grove 0:618e98bf18ce 43 {
sam_grove 1:514f321aa528 44 // gather input from the Serial object
sam_grove 1:514f321aa528 45 shellInput();
sam_grove 1:514f321aa528 46 // break up the command line arguemnt
sam_grove 2:b3107e463974 47 _arg = split(_cmd, _cmdline, 64, ' ');
sam_grove 1:514f321aa528 48 // look at the arg and get paths and files separated if present
sam_grove 2:b3107e463974 49 resolveDirectory(_newpath, _arg);
sam_grove 2:b3107e463974 50 // print parsed members if we're debugging
sam_grove 1:514f321aa528 51 if(_debug)
sam_grove 1:514f321aa528 52 {
sam_grove 2:b3107e463974 53 LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmdline, _cmd, _arg, _newpath);
sam_grove 1:514f321aa528 54 }
sam_grove 2:b3107e463974 55 // now service known messages
sam_grove 2:b3107e463974 56 char* result = _cmds.serviceMessage(_cmd);
sam_grove 2:b3107e463974 57 // look at the result > 0 means we found somehting
sam_grove 2:b3107e463974 58 if(result == (char *)EXIT)
sam_grove 1:514f321aa528 59 {
sam_grove 2:b3107e463974 60 done = 1; // force an exit
sam_grove 1:514f321aa528 61 }
sam_grove 2:b3107e463974 62 else if (result == (char *)UNKNOWN) // didnt know what that was
sam_grove 1:514f321aa528 63 {
sam_grove 2:b3107e463974 64 uint32_t cnt = 1;
sam_grove 2:b3107e463974 65 LOG("Unknown Message from Terminal: Options are\n");
jekain314 4:6ff0a3d92778 66 do{
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
jekain314 8:30aa615d4508 90 if ((c == '\r') || (c == '\n')) // 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 5:3417ba8cb1e4 299 char *SDShell::bcat(char *cmd)
jekain314 4:6ff0a3d92778 300 {
jekain314 8:30aa615d4508 301 uint8_t buf[4] = {NULL};
jekain314 4:6ff0a3d92778 302 FILE *fp= fopen(_newpath, "rb");
jekain314 4:6ff0a3d92778 303 if (fp != NULL)
jekain314 4:6ff0a3d92778 304 {
jekain314 4:6ff0a3d92778 305 while (!feof(fp))
jekain314 4:6ff0a3d92778 306 {
jekain314 8:30aa615d4508 307 fread(buf, 1, 1, fp);
jekain314 8:30aa615d4508 308 _com->putc(buf[0]);
jekain314 4:6ff0a3d92778 309 }
jekain314 4:6ff0a3d92778 310 fclose(fp);
jekain314 4:6ff0a3d92778 311 }
jekain314 4:6ff0a3d92778 312 else
jekain314 4:6ff0a3d92778 313 {
jekain314 4:6ff0a3d92778 314 _com->printf("%s: No such file\n", _newpath);
jekain314 4:6ff0a3d92778 315 }
jekain314 4:6ff0a3d92778 316 return (char *)OK;
jekain314 4:6ff0a3d92778 317 }
jekain314 4:6ff0a3d92778 318
sam_grove 2:b3107e463974 319 char *SDShell::touch(char *cmd)
sam_grove 1:514f321aa528 320 {
sam_grove 2:b3107e463974 321 FILE *fp = fopen(_newpath, "w");
sam_grove 2:b3107e463974 322 if (fp != NULL)
sam_grove 2:b3107e463974 323 {
sam_grove 2:b3107e463974 324 _com->printf("%s: File created\n", _newpath);
sam_grove 2:b3107e463974 325 fclose(fp);
sam_grove 2:b3107e463974 326 }
sam_grove 2:b3107e463974 327 else
sam_grove 2:b3107e463974 328 {
sam_grove 2:b3107e463974 329 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 330 }
sam_grove 2:b3107e463974 331
sam_grove 2:b3107e463974 332 return (char *)OK;
sam_grove 2:b3107e463974 333 }
sam_grove 0:618e98bf18ce 334
sam_grove 2:b3107e463974 335 char *SDShell::create(char *cmd)
sam_grove 2:b3107e463974 336 {
sam_grove 2:b3107e463974 337 mkdir(_newpath, 1023);
sam_grove 2:b3107e463974 338
sam_grove 2:b3107e463974 339 return (char *)OK;
sam_grove 1:514f321aa528 340 }
sam_grove 1:514f321aa528 341
sam_grove 2:b3107e463974 342 char *SDShell::rm(char *cmd)
sam_grove 1:514f321aa528 343 {
sam_grove 2:b3107e463974 344 remove(_newpath);
sam_grove 2:b3107e463974 345
sam_grove 2:b3107e463974 346 return (char *)OK;
sam_grove 1:514f321aa528 347 }
sam_grove 1:514f321aa528 348
sam_grove 2:b3107e463974 349 char *SDShell::exit(char *cmd)
sam_grove 2:b3107e463974 350 {
sam_grove 2:b3107e463974 351 return (char *)EXIT;
sam_grove 2:b3107e463974 352 }
sam_grove 2:b3107e463974 353
sam_grove 2:b3107e463974 354 char *SDShell::debug(char *cmd)
sam_grove 2:b3107e463974 355 {
sam_grove 2:b3107e463974 356 _debug = !_debug;
sam_grove 2:b3107e463974 357
sam_grove 2:b3107e463974 358 return (char *)OK;
sam_grove 2:b3107e463974 359 }
sam_grove 2:b3107e463974 360
sam_grove 5:3417ba8cb1e4 361 char SDShell::btoa(uint8_t b)
sam_grove 5:3417ba8cb1e4 362 {
sam_grove 5:3417ba8cb1e4 363 return ((b&0xf) < 0xa) ? ((b&0xf)+0x30) : ((b&0xf)+0x37);
sam_grove 5:3417ba8cb1e4 364 }
sam_grove 2:b3107e463974 365
sam_grove 2:b3107e463974 366
sam_grove 2:b3107e463974 367
sam_grove 5:3417ba8cb1e4 368