Simple embedded shell with runtime pluggable commands.

Dependents:   DataBus2018

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

Committer:
shimniok
Date:
Sun Dec 02 17:33:07 2018 +0000
Revision:
5:8f486f4d29d3
Parent:
4:8b8fa59d0015
Child:
8:41b7274a9753
Child:
10:c3faa7ffd23b
ignore blank command

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shimniok 0:49820d5a38c9 1 #include "SimpleShell.h"
shimniok 5:8f486f4d29d3 2 #include <ctype.h>
shimniok 0:49820d5a38c9 3
shimniok 0:49820d5a38c9 4 SimpleShell::SimpleShell()
shimniok 0:49820d5a38c9 5 {
shimniok 2:4f0affdb7db9 6 lookupEnd = 0;
shimniok 0:49820d5a38c9 7 }
shimniok 0:49820d5a38c9 8
shimniok 0:49820d5a38c9 9 void SimpleShell::run()
shimniok 0:49820d5a38c9 10 {
shimniok 0:49820d5a38c9 11 bool done=false;
shimniok 4:8b8fa59d0015 12 Callback<void()> cb;
shimniok 5:8f486f4d29d3 13 int status; // TODO implement command status return
shimniok 4:8b8fa59d0015 14
shimniok 0:49820d5a38c9 15 strcpy(_cwd, "/log");
shimniok 0:49820d5a38c9 16
shimniok 0:49820d5a38c9 17 printf("Type help for assistance.\n");
shimniok 0:49820d5a38c9 18 while (!done) {
shimniok 0:49820d5a38c9 19 printPrompt();
shimniok 0:49820d5a38c9 20 readCommand();
shimniok 5:8f486f4d29d3 21 if (cmd[0]) { // skip blank command
shimniok 5:8f486f4d29d3 22 if (cb = findCommand()) {
shimniok 5:8f486f4d29d3 23 cb.call();
shimniok 5:8f486f4d29d3 24 } else {
shimniok 5:8f486f4d29d3 25 printf("command <%s> not found\n", cmd);
shimniok 5:8f486f4d29d3 26 }
shimniok 4:8b8fa59d0015 27 }
shimniok 0:49820d5a38c9 28 }
shimniok 0:49820d5a38c9 29 puts("exiting shell\n");
shimniok 0:49820d5a38c9 30
shimniok 0:49820d5a38c9 31 return;
shimniok 0:49820d5a38c9 32 }
shimniok 0:49820d5a38c9 33
shimniok 0:49820d5a38c9 34
shimniok 2:4f0affdb7db9 35 void SimpleShell::attach(Callback<void()> cb, char *command)
shimniok 2:4f0affdb7db9 36 {
shimniok 2:4f0affdb7db9 37 if (lookupEnd < MAXLOOKUP) {
shimniok 2:4f0affdb7db9 38 lookup[lookupEnd].cb = cb;
shimniok 2:4f0affdb7db9 39 lookup[lookupEnd].command = command;
shimniok 2:4f0affdb7db9 40 lookupEnd++;
shimniok 2:4f0affdb7db9 41 }
shimniok 2:4f0affdb7db9 42
shimniok 2:4f0affdb7db9 43 for (int i=0; i < lookupEnd; i++) {
shimniok 2:4f0affdb7db9 44 printf("%s\n", lookup[i].command);
shimniok 2:4f0affdb7db9 45 }
shimniok 2:4f0affdb7db9 46
shimniok 2:4f0affdb7db9 47 return;
shimniok 1:998a7ed04f10 48 }
shimniok 1:998a7ed04f10 49
shimniok 1:998a7ed04f10 50
shimniok 3:ebb4893f033d 51 Callback<void()> SimpleShell::findCommand()
shimniok 3:ebb4893f033d 52 {
shimniok 3:ebb4893f033d 53 Callback<void()> cb=NULL;
shimniok 3:ebb4893f033d 54
shimniok 4:8b8fa59d0015 55 for (int i=0; i < lookupEnd; i++) {
shimniok 4:8b8fa59d0015 56 if (strncmp(cmd, lookup[i].command, MAXBUF) == 0) {
shimniok 4:8b8fa59d0015 57 cb = lookup[i].cb;
shimniok 4:8b8fa59d0015 58 break;
shimniok 4:8b8fa59d0015 59 }
shimniok 4:8b8fa59d0015 60 }
shimniok 4:8b8fa59d0015 61
shimniok 3:ebb4893f033d 62 return cb;
shimniok 3:ebb4893f033d 63 }
shimniok 3:ebb4893f033d 64
shimniok 3:ebb4893f033d 65
shimniok 0:49820d5a38c9 66 void SimpleShell::printPrompt()
shimniok 0:49820d5a38c9 67 {
shimniok 0:49820d5a38c9 68 fputc('(', stdout);
shimniok 0:49820d5a38c9 69 fputs(_cwd, stdout);
shimniok 0:49820d5a38c9 70 fputs(")# ", stdout);
shimniok 2:4f0affdb7db9 71
shimniok 2:4f0affdb7db9 72 return;
shimniok 0:49820d5a38c9 73 }
shimniok 0:49820d5a38c9 74
shimniok 0:49820d5a38c9 75
shimniok 0:49820d5a38c9 76 void SimpleShell::readCommand()
shimniok 0:49820d5a38c9 77 {
shimniok 0:49820d5a38c9 78 int i=0;
shimniok 0:49820d5a38c9 79 char c;
shimniok 0:49820d5a38c9 80 bool done = false;
shimniok 0:49820d5a38c9 81
shimniok 0:49820d5a38c9 82 memset(cmd, 0, MAXBUF);
shimniok 0:49820d5a38c9 83 do {
shimniok 0:49820d5a38c9 84 cmd[i] = 0;
shimniok 0:49820d5a38c9 85 c = fgetc(stdin);
shimniok 0:49820d5a38c9 86 if (c == '\r') { // if return is hit, we're done, don't add \r to cmd
shimniok 0:49820d5a38c9 87 done = true;
shimniok 0:49820d5a38c9 88 } else if (i < MAXBUF-1) {
shimniok 0:49820d5a38c9 89 if (c == 0x7f || c == '\b') { // backspace or delete
shimniok 0:49820d5a38c9 90 if (i > 0) { // if we're at the beginning, do nothing
shimniok 0:49820d5a38c9 91 i--;
shimniok 0:49820d5a38c9 92 fputs("\b \b", stdout);
shimniok 0:49820d5a38c9 93
shimniok 0:49820d5a38c9 94 }
shimniok 0:49820d5a38c9 95 } else {
shimniok 0:49820d5a38c9 96 fputc(c, stdout);
shimniok 0:49820d5a38c9 97 cmd[i++] = c;
shimniok 0:49820d5a38c9 98 }
shimniok 0:49820d5a38c9 99 }
shimniok 0:49820d5a38c9 100 } while (!done);
shimniok 0:49820d5a38c9 101 fputc('\n', stdout);
shimniok 0:49820d5a38c9 102
shimniok 5:8f486f4d29d3 103 // chomp
shimniok 5:8f486f4d29d3 104 for (int j=i; j >= 0; j--) {
shimniok 5:8f486f4d29d3 105 if (isspace(cmd[j])) {
shimniok 5:8f486f4d29d3 106 cmd[j] = '\0';
shimniok 5:8f486f4d29d3 107 }
shimniok 5:8f486f4d29d3 108 }
shimniok 5:8f486f4d29d3 109
shimniok 2:4f0affdb7db9 110 return;
shimniok 0:49820d5a38c9 111 }