Simple embedded shell with runtime pluggable commands.

Dependents:   DataBus2018

Implements a simple unix-like shell for embedded systems with a pluggable command architecture.

Revision:
20:53f0b5dc30f9
Parent:
19:bf5f5ea4e762
Child:
21:5d7ac1f0b842
--- a/SimpleShell.cpp	Sat Dec 22 20:27:54 2018 +0000
+++ b/SimpleShell.cpp	Mon Dec 24 04:31:43 2018 +0000
@@ -1,324 +0,0 @@
-#include "SimpleShell.h"
-#include <ctype.h>
-#include <string>
-
-#define ESC     0x1b
-#define UP      0x41
-#define DOWN    0x42
-#define RIGHT   0x43
-#define LEFT    0x44
-#define HOME    0x31
-#define INS     0x32
-#define DEL     0x33
-#define PGUP    0x35
-#define PGDN    0x36
-#define TAIL    0x7e
-
-
-char *SimpleShell::canon(char *path) {
-    static char result[MAXBUF];
-    
-    if (path[0] != '/') {
-        strncpy(result, _cwd, MAXBUF);
-        strcat(result, "/");
-    }
-    strcat(result, path);
-    
-    return result;
-}
-
-
-SimpleShell::SimpleShell()
-{
-    lookupEnd = 0;
-
-    // Built-in shell commands
-    attach(callback(this, &SimpleShell::help), "help");
-    attach(callback(this, &SimpleShell::pwd), "pwd");
-    attach(callback(this, &SimpleShell::cat), "cat");
-    attach(callback(this, &SimpleShell::cd), "cd");
-    attach(callback(this, &SimpleShell::rm), "rm");
-    attach(callback(this, &SimpleShell::touch), "touch");
-    attach(callback(this, &SimpleShell::ls), "ls");
-}
-
-
-void SimpleShell::help(int argc, char **argv)
-{
-    printf("Available commands: ");
-    for (int i=0; i < lookupEnd; i++) {
-        printf("%s ", lookup[i].command);
-    }
-    printf("\n\n");
-}
-
-
-void SimpleShell::cd(int argc, char **argv) 
-{
-    if (argc == 2) {
-        strncpy(_cwd, argv[1], MAXBUF);
-    } else {
-        puts("usage: cd directory");
-    }
-    return;
-}
-
-
-void SimpleShell::pwd(int argc, char **argv)
-{
-    puts(_cwd);
-    return;
-}
-
-
-void SimpleShell::ls(int argc, char **argv)
-{
-    DIR *d;
-    struct dirent *p;
-    char *path;
-
-    if (argc == 1) {
-        path = _cwd;
-    } else if (argc == 2) {
-        path = argv[1];
-    } else {
-        puts("usage: ls [directory]");
-        return;
-    }
-    
-    int cols=0;
-    if ((d = opendir(path)) != NULL) {
-        while ((p = readdir(d)) != NULL) {
-            if (p->d_name && p->d_name[0] != 0xff) {
-                if (cols++ > 3) {
-                    putc('\n', stdout);
-                    cols = 0;
-                }
-                printf("%-15s  ", p->d_name);
-            }
-        }
-        putc('\n', stdout);
-        if (cols < 3)
-            putc('\n', stdout);
-        closedir(d);
-    } else {
-        puts(path);
-        puts(": No such directory\n");
-    }
-
-    return;
-}
-
-
-void SimpleShell::rm(int argc, char **argv)
-{
-    if (argc >= 2) {
-        for (int i=1; i < argc; i++) {
-            if (remove(canon(argv[i]))) {
-                printf("%s: cannot remove\n", argv[i]);
-            }
-        }
-    } else {
-        puts("usage: rm [file1 [file2 ...]]");
-    }
-}
-
-
-void SimpleShell::touch(int argc, char **argv)
-{
-    FILE *fp;
-
-    if (argc >= 2) {
-        for (int i=1; i < argc; i++) {
-            if ((fp = fopen(canon(argv[i]), "w")) != NULL) {
-                fclose(fp);
-            } else {
-                printf("%s: cannot touch\n", argv[1]);
-            }
-        }
-    } else {
-        puts("usage: touch [file1 [file2 ...]]");
-    }
-}
-
-
-void SimpleShell::cat(int argc, char **argv)
-{
-    FILE *fp;
-    //int status=0;
-    char *buf = new char[MAXBUF];
-    
-    for (int i=1; i < argc; i++) {
-        //resolveDirectory(path, arg);
-        if ((fp = fopen(canon(argv[i]), "r")) != NULL) {
-            while (!feof(fp)) {
-                fgets(buf, MAXBUF-1, fp);
-                fputs(buf, stdout);
-            }
-            fclose(fp);
-        } else {
-            fputs(argv[i], stdout);
-            fputs(": No such file\n", stdout);
-            //status = 1;
-        }
-    }
-    delete[] buf;
-
-    return;
-}
-
-
-void SimpleShell::run()
-{
-    bool done=false;
-    callback_t cb;
-    //int status; // TODO implement command status return
-    std::string x;
-    
-    // Set current working directory
-    strncpy(_cwd, "/etc", MAXBUF);
-
-    printf("Type help for assistance.\n");
-    help(0, NULL);   
-    while (!done) {
-        printPrompt();
-        readCommand();
-        if (argv[0]) { // skip blank command
-            if (cb = findCommand()) {
-                cb.call(argc, argv);
-            } else {
-                printf("command <%s> not found\n", argv[0]);
-            }
-        }
-    }
-    puts("exiting shell\n");
-
-    return;
-}
-
-
-void SimpleShell::attach(callback_t cb, char *command) 
-{  
-    if (lookupEnd < MAXLOOKUP) {
-        lookup[lookupEnd].cb = cb;
-        lookup[lookupEnd].command = command;
-        lookupEnd++;
-    }
-        
-    return;
-}
-
-
-SimpleShell::callback_t SimpleShell::findCommand()
-{
-    SimpleShell::callback_t cb=NULL;
-    
-    for (int i=0; i < lookupEnd; i++) {
-        if (strncmp(argv[0], lookup[i].command, MAXBUF) == 0) {
-            cb = lookup[i].cb;
-            break;
-        }
-    }
-    
-    return cb;
-}
-
-
-void SimpleShell::printPrompt()
-{
-    fputc('(', stdout);
-    fputs(_cwd, stdout);
-    fputs(")# ", stdout);
-    
-    return;
-}
-
-
-void SimpleShell::readCommand()
-{
-    int i=0;
-    char c;
-    bool done = false;
-    static char cmd[MAXBUF];
-    
-    memset(cmd, 0, MAXBUF);
-    do {
-        cmd[i] = 0;
-        c = fgetc(stdin);
-        if (c == '\r') { // if return is hit, we're done, don't add \r to cmd
-            done = true;
-        } else if (c == ESC) { // keyboard escape codes (arrow keys, etc)
-            int c2 = getchar();
-            int c3 = getchar();
-
-            if (c2 == 0x4f && c3 == 0x46) {
-                printf("<END>");
-            } else if (c2 == 0x5b) {
-
-                if (c3 == UP) {
-                    printf("<UP>");
-                } else if (c3 == DOWN) {
-                    printf("<DOWN>");
-                } else if (c3 == RIGHT) {
-                    printf("<RIGHT>");
-                } else if (c3 == LEFT) {
-                    printf("<LEFT>");
-                } else if (c3 == HOME || c3 == INS || c3 == DEL ||
-                           c3 == PGUP || c3 == PGDN) {
-                    char c4 = getchar();
-                    if (c4 == TAIL) {
-                        if (c4 == HOME) {
-                            printf("<HOME>");
-                        } else if (c4 == INS) {
-                            printf("<INS>");
-                        } else if (c4 == DEL) {
-                            printf("<DEL>");
-                        } else if (c4 == PGUP) {
-                            printf("<PGUP>");
-                        } else if (c4 == PGDN) {
-                            printf("<PGDN>");
-                        }//if
-                    }//if
-                }//if
-            }//if            
-            //printf("\n");
-        } else if (i < MAXBUF-1) {
-            if (c == 0x7f || c == '\b') { // backspace or delete
-                if (i > 0) { // if we're at the beginning, do nothing
-                    i--;
-                    fputs("\b \b", stdout);
-                }
-            } else {
-                if (isprint(c))
-                    fputc(c, stdout);
-                cmd[i++] = c;
-            }
-        }
-
-    } while (!done);
-    fputc('\n', stdout);
-
-    // remove leading/trailing whitespace
-    char *s = cmd;
-    while (isspace(*s)) {
-        s++;
-    }
-    for (int j=i; j >= 0 && isspace(cmd[j]); j--) {
-        cmd[j] = '\0';
-    }
-
-    // split into command and arguments
-    argc = 0;
-    char *t;
-    
-    for (int i=0; i < MAXARGS; i++) {
-        argv[i] = NULL;
-    }    
-    t = strtok(s, " ");
-    while (t && argc < 10) {
-        argv[argc++] = t;
-        t = strtok(NULL, " ");
-    }
-
-    return;
-}
\ No newline at end of file