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 16:08:39 2013 +0000
Revision:
1:514f321aa528
Parent:
0:618e98bf18ce
Child:
2:b3107e463974
partially working implementation - has a bug in parsing come back to later

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 0:618e98bf18ce 16 return;
sam_grove 0:618e98bf18ce 17 }
sam_grove 0:618e98bf18ce 18
sam_grove 0:618e98bf18ce 19 void SDShell::shell(Serial &com, SDFileSystem &storage, char *cwd)
sam_grove 0:618e98bf18ce 20 {
sam_grove 1:514f321aa528 21 uint32_t done = 0;
sam_grove 1:514f321aa528 22
sam_grove 1:514f321aa528 23 // get local copies of the initialized objects
sam_grove 0:618e98bf18ce 24 _com = &com;
sam_grove 1:514f321aa528 25 _storage = &storage;
sam_grove 1:514f321aa528 26
sam_grove 1:514f321aa528 27 // put the current working directory to the root of the card - should be pulled in I think
sam_grove 1:514f321aa528 28 strcpy(_cwd, "/sd");
sam_grove 1:514f321aa528 29
sam_grove 1:514f321aa528 30 while(0 == done)
sam_grove 0:618e98bf18ce 31 {
sam_grove 1:514f321aa528 32 // gather input from the Serial object
sam_grove 1:514f321aa528 33 shellInput();
sam_grove 1:514f321aa528 34 // break up the command line arguemnt
sam_grove 1:514f321aa528 35 _arg = split(_cmd, _cmd_line, 64, ' ');
sam_grove 1:514f321aa528 36 // look at the arg and get paths and files separated if present
sam_grove 1:514f321aa528 37 resolveDirectory(_new_path, _arg);
sam_grove 1:514f321aa528 38 if(_debug)
sam_grove 1:514f321aa528 39 {
sam_grove 1:514f321aa528 40 LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmd_line, _cmd, _arg, _new_path);
sam_grove 1:514f321aa528 41 }
sam_grove 1:514f321aa528 42
sam_grove 1:514f321aa528 43 if (match(_cmd, "ls"))
sam_grove 1:514f321aa528 44 {
sam_grove 1:514f321aa528 45 ls(_new_path, _com);
sam_grove 1:514f321aa528 46 }
sam_grove 1:514f321aa528 47 else if (match(_cmd, "cd"))
sam_grove 0:618e98bf18ce 48 {
sam_grove 1:514f321aa528 49 cd(_new_path);
sam_grove 1:514f321aa528 50 }
sam_grove 1:514f321aa528 51 else if (match(_cmd, "pwd"))
sam_grove 1:514f321aa528 52 {
sam_grove 1:514f321aa528 53 pwd(_com);
sam_grove 1:514f321aa528 54 }
sam_grove 1:514f321aa528 55 else if (match(_cmd, "head"))
sam_grove 1:514f321aa528 56 {
sam_grove 1:514f321aa528 57 head(_new_path, _com);
sam_grove 1:514f321aa528 58 }
sam_grove 1:514f321aa528 59 else if (match(_cmd, "cat"))
sam_grove 1:514f321aa528 60 {
sam_grove 1:514f321aa528 61 cat(_new_path, _com);
sam_grove 0:618e98bf18ce 62 }
sam_grove 1:514f321aa528 63 else if (match(_cmd, "mkdir"))
sam_grove 1:514f321aa528 64 {
sam_grove 1:514f321aa528 65 mkdir(_new_path, 1023);
sam_grove 1:514f321aa528 66 }
sam_grove 1:514f321aa528 67 else if (match(_cmd, "debug"))
sam_grove 1:514f321aa528 68 {
sam_grove 1:514f321aa528 69 _debug = !_debug;
sam_grove 1:514f321aa528 70 }
sam_grove 1:514f321aa528 71 else if (match(_cmd, "touch"))
sam_grove 0:618e98bf18ce 72 {
sam_grove 1:514f321aa528 73 touch(_new_path, _com);
sam_grove 1:514f321aa528 74 }
sam_grove 1:514f321aa528 75 else if (match(_cmd, "rm"))
sam_grove 1:514f321aa528 76 {
sam_grove 1:514f321aa528 77 remove(_new_path);
sam_grove 1:514f321aa528 78 }
sam_grove 1:514f321aa528 79 else if (match(_cmd, "exit"))
sam_grove 1:514f321aa528 80 {
sam_grove 1:514f321aa528 81 done = true;
sam_grove 0:618e98bf18ce 82 }
sam_grove 0:618e98bf18ce 83 else
sam_grove 0:618e98bf18ce 84 {
sam_grove 1:514f321aa528 85 _com->printf("%s: command not found\n", _cmd);
sam_grove 0:618e98bf18ce 86 }
sam_grove 0:618e98bf18ce 87 }
sam_grove 1:514f321aa528 88 }
sam_grove 0:618e98bf18ce 89
sam_grove 1:514f321aa528 90 void SDShell::shellInput(void)
sam_grove 0:618e98bf18ce 91 {
sam_grove 1:514f321aa528 92 int i=0;
sam_grove 1:514f321aa528 93 char c;
sam_grove 1:514f321aa528 94 uint32_t done = 0;
sam_grove 1:514f321aa528 95 // clear the last command
sam_grove 1:514f321aa528 96 memset(_cmd, 0, 64);
sam_grove 1:514f321aa528 97 _com->printf("# ", _cwd);
sam_grove 1:514f321aa528 98 do
sam_grove 0:618e98bf18ce 99 {
sam_grove 1:514f321aa528 100 _cmd[i] = 0;
sam_grove 1:514f321aa528 101 c = _com->getc();
sam_grove 1:514f321aa528 102 if (c == '\r')
sam_grove 1:514f321aa528 103 {
sam_grove 1:514f321aa528 104 done = 1;
sam_grove 1:514f321aa528 105 }
sam_grove 1:514f321aa528 106 else if (i < SHELL_BUF_MASK)
sam_grove 0:618e98bf18ce 107 {
sam_grove 1:514f321aa528 108 if (c == 0x7f)
sam_grove 1:514f321aa528 109 { // backspace
sam_grove 1:514f321aa528 110 if (i > 0)
sam_grove 1:514f321aa528 111 { // if we're at the beginning, do nothing
sam_grove 1:514f321aa528 112 i--;
sam_grove 1:514f321aa528 113 _com->printf("\b \b");
sam_grove 1:514f321aa528 114 }
sam_grove 1:514f321aa528 115 }
sam_grove 1:514f321aa528 116 else
sam_grove 1:514f321aa528 117 {
sam_grove 1:514f321aa528 118 _com->putc(c);
sam_grove 1:514f321aa528 119 _cmd[i++] = c;
sam_grove 1:514f321aa528 120 }
sam_grove 0:618e98bf18ce 121 }
sam_grove 1:514f321aa528 122 } while (0 == done);
sam_grove 1:514f321aa528 123
sam_grove 1:514f321aa528 124 _com->printf("\n");
sam_grove 0:618e98bf18ce 125 }
sam_grove 0:618e98bf18ce 126
sam_grove 1:514f321aa528 127 char *SDShell::split(char *dst, char *src, int max, char delim)
sam_grove 0:618e98bf18ce 128 {
sam_grove 1:514f321aa528 129 int i = 0;
sam_grove 1:514f321aa528 130 char *v;
sam_grove 1:514f321aa528 131
sam_grove 1:514f321aa528 132 // make sure pointers are valid (could validate RAM but that should be the caller responsibility)
sam_grove 1:514f321aa528 133 if ((src == 0) || (dst == 0))
sam_grove 1:514f321aa528 134 {
sam_grove 1:514f321aa528 135 return 0;
sam_grove 1:514f321aa528 136 }
sam_grove 1:514f321aa528 137 // break up the string
sam_grove 1:514f321aa528 138 while((*src != 0) && (*src != delim) && (i < max))
sam_grove 0:618e98bf18ce 139 {
sam_grove 1:514f321aa528 140 *(dst++) = *(src++);
sam_grove 1:514f321aa528 141 i++;
sam_grove 1:514f321aa528 142 }
sam_grove 1:514f321aa528 143
sam_grove 1:514f321aa528 144 *src = 0;
sam_grove 1:514f321aa528 145 v = (*dst == '\0') ? src : (dst+1);
sam_grove 1:514f321aa528 146
sam_grove 1:514f321aa528 147 return v;
sam_grove 1:514f321aa528 148 }
sam_grove 1:514f321aa528 149
sam_grove 1:514f321aa528 150 void SDShell::resolveDirectory(char *newpath, char *path)
sam_grove 1:514f321aa528 151 {
sam_grove 1:514f321aa528 152 char basename[64], dirname[64];
sam_grove 1:514f321aa528 153
sam_grove 1:514f321aa528 154 // absolute path
sam_grove 1:514f321aa528 155 if (path[0] == '/')
sam_grove 1:514f321aa528 156 {
sam_grove 1:514f321aa528 157 strcpy(newpath, path);
sam_grove 1:514f321aa528 158 }
sam_grove 1:514f321aa528 159 // relative path
sam_grove 1:514f321aa528 160 else
sam_grove 1:514f321aa528 161 {
sam_grove 1:514f321aa528 162 strcpy(newpath, _cwd);
sam_grove 1:514f321aa528 163 // make sure something was passed
sam_grove 1:514f321aa528 164 if(path[0] != 0)
sam_grove 0:618e98bf18ce 165 {
sam_grove 1:514f321aa528 166 // add the backslash if the user didnt
sam_grove 1:514f321aa528 167 if(newpath[strlen(newpath)-1] != '/')
sam_grove 1:514f321aa528 168 {
sam_grove 1:514f321aa528 169 strcat(newpath, "/");
sam_grove 1:514f321aa528 170 }
sam_grove 1:514f321aa528 171 strcat(newpath, path);
sam_grove 0:618e98bf18ce 172 }
sam_grove 1:514f321aa528 173 // Resolve .. references
sam_grove 1:514f321aa528 174 splitName(newpath, dirname, basename);
sam_grove 1:514f321aa528 175 if (0 == strcmp(basename, ".."))
sam_grove 1:514f321aa528 176 {
sam_grove 1:514f321aa528 177 splitName(dirname, newpath, basename);
sam_grove 1:514f321aa528 178 }
sam_grove 0:618e98bf18ce 179 }
sam_grove 0:618e98bf18ce 180
sam_grove 1:514f321aa528 181 return;
sam_grove 0:618e98bf18ce 182 }
sam_grove 0:618e98bf18ce 183
sam_grove 1:514f321aa528 184 void SDShell::splitName(char *path, char *dirname, char *basename)
sam_grove 1:514f321aa528 185 {
sam_grove 1:514f321aa528 186 int sep = 0;
sam_grove 1:514f321aa528 187
sam_grove 1:514f321aa528 188 if (_debug)
sam_grove 1:514f321aa528 189 {
sam_grove 1:514f321aa528 190 LOG("%d\n", strlen(path));
sam_grove 1:514f321aa528 191 }
sam_grove 1:514f321aa528 192 for (int i=strlen(path)-1; i >= 0; i--)
sam_grove 1:514f321aa528 193 {
sam_grove 1:514f321aa528 194 if (_debug)
sam_grove 1:514f321aa528 195 {
sam_grove 1:514f321aa528 196 LOG("- %c\n", path[i]);
sam_grove 1:514f321aa528 197 }
sam_grove 1:514f321aa528 198 sep = i;
sam_grove 1:514f321aa528 199 if (path[i] == '/')
sam_grove 1:514f321aa528 200 {
sam_grove 1:514f321aa528 201 break;
sam_grove 1:514f321aa528 202 }
sam_grove 1:514f321aa528 203 }
sam_grove 1:514f321aa528 204 for (int j=0; j < sep; j++)
sam_grove 1:514f321aa528 205 {
sam_grove 1:514f321aa528 206 if (_debug)
sam_grove 1:514f321aa528 207 {
sam_grove 1:514f321aa528 208 LOG("> %c\n", path[j]);
sam_grove 1:514f321aa528 209 }
sam_grove 1:514f321aa528 210 dirname[j] = path[j];
sam_grove 1:514f321aa528 211 dirname[j+1] = 0;
sam_grove 1:514f321aa528 212 }
sam_grove 1:514f321aa528 213 for (int k=sep+1; k < strlen(path); k++)
sam_grove 1:514f321aa528 214 {
sam_grove 1:514f321aa528 215 if (_debug)
sam_grove 1:514f321aa528 216 {
sam_grove 1:514f321aa528 217 LOG("* %c\n", path[k]);
sam_grove 1:514f321aa528 218 }
sam_grove 1:514f321aa528 219 basename[k-(sep+1)] = path[k];
sam_grove 1:514f321aa528 220 basename[k-sep] = 0;
sam_grove 1:514f321aa528 221 }
sam_grove 1:514f321aa528 222 if (_debug)
sam_grove 1:514f321aa528 223 {
sam_grove 1:514f321aa528 224 LOG("d:<%s> b:<%s>\n", dirname, basename);
sam_grove 1:514f321aa528 225 }
sam_grove 1:514f321aa528 226 }
sam_grove 0:618e98bf18ce 227
sam_grove 1:514f321aa528 228 uint32_t SDShell::match(char *arg1, char *arg2)
sam_grove 1:514f321aa528 229 {
sam_grove 1:514f321aa528 230 return (0 == strcmp(arg1, arg2)) ? 1 : 0;
sam_grove 1:514f321aa528 231 }
sam_grove 1:514f321aa528 232
sam_grove 1:514f321aa528 233 void SDShell::ls(char *path, Serial *pc)
sam_grove 1:514f321aa528 234 {
sam_grove 1:514f321aa528 235 if (_debug) pc->printf("%s\n", _cwd);
sam_grove 1:514f321aa528 236 DIR *d;
sam_grove 1:514f321aa528 237 struct dirent *p;
sam_grove 0:618e98bf18ce 238
sam_grove 1:514f321aa528 239 if ((d = opendir(path)) != NULL) {
sam_grove 1:514f321aa528 240 while ((p = readdir(d)) != NULL) {
sam_grove 1:514f321aa528 241 pc->printf(" %s\n", p->d_name);
sam_grove 1:514f321aa528 242 }
sam_grove 1:514f321aa528 243 closedir(d);
sam_grove 1:514f321aa528 244 } else {
sam_grove 1:514f321aa528 245 pc->printf("%s: No such directory\n", path);
sam_grove 1:514f321aa528 246 }
sam_grove 1:514f321aa528 247 }
sam_grove 1:514f321aa528 248
sam_grove 1:514f321aa528 249 void SDShell::cd(char *path)
sam_grove 1:514f321aa528 250 {
sam_grove 1:514f321aa528 251 strcpy(_cwd, path);
sam_grove 1:514f321aa528 252 }
sam_grove 1:514f321aa528 253
sam_grove 1:514f321aa528 254 void SDShell::pwd(Serial *pc)
sam_grove 1:514f321aa528 255 {
sam_grove 1:514f321aa528 256 pc->printf("%s\n", _cwd);
sam_grove 1:514f321aa528 257 }
sam_grove 1:514f321aa528 258
sam_grove 1:514f321aa528 259 void SDShell::head(char *path, Serial *pc)
sam_grove 1:514f321aa528 260 {
sam_grove 1:514f321aa528 261 FILE *fp;
sam_grove 1:514f321aa528 262 char line = 0;
sam_grove 0:618e98bf18ce 263
sam_grove 1:514f321aa528 264 if ((fp = fopen(path, "r")) != NULL) {
sam_grove 1:514f321aa528 265 while (!feof(fp) && line++ < 10) {
sam_grove 1:514f321aa528 266 fgets(_buf, 128, fp);
sam_grove 1:514f321aa528 267 pc->printf("%s", _buf);
sam_grove 1:514f321aa528 268 }
sam_grove 1:514f321aa528 269 fclose(fp);
sam_grove 1:514f321aa528 270 } else {
sam_grove 1:514f321aa528 271 pc->printf("%s: No such file\n", path);
sam_grove 1:514f321aa528 272 }
sam_grove 1:514f321aa528 273 }
sam_grove 0:618e98bf18ce 274
sam_grove 1:514f321aa528 275 void SDShell::cat(char *path, Serial *pc)
sam_grove 1:514f321aa528 276 {
sam_grove 1:514f321aa528 277 FILE *fp;
sam_grove 0:618e98bf18ce 278
sam_grove 1:514f321aa528 279 if ((fp = fopen(path, "r")) != NULL) {
sam_grove 1:514f321aa528 280 while (!feof(fp)) {
sam_grove 1:514f321aa528 281 fgets(_buf, 128, fp);
sam_grove 1:514f321aa528 282 pc->printf("%s", _buf);
sam_grove 1:514f321aa528 283 }
sam_grove 1:514f321aa528 284 fclose(fp);
sam_grove 1:514f321aa528 285 } else {
sam_grove 1:514f321aa528 286 pc->printf("%s: No such file\n", path);
sam_grove 1:514f321aa528 287 }
sam_grove 1:514f321aa528 288 }
sam_grove 1:514f321aa528 289
sam_grove 1:514f321aa528 290 void SDShell::touch(char *path, Serial *pc)
sam_grove 1:514f321aa528 291 {
sam_grove 1:514f321aa528 292 FILE *fp;
sam_grove 1:514f321aa528 293 if ((fp = fopen(path, "w")) != NULL) {
sam_grove 1:514f321aa528 294 fclose(fp);
sam_grove 1:514f321aa528 295 } else {
sam_grove 1:514f321aa528 296 pc->printf("%s: No such file\n", path);
sam_grove 1:514f321aa528 297 }
sam_grove 1:514f321aa528 298 }
sam_grove 1:514f321aa528 299