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:
Wed Dec 12 18:30:49 2018 +0000
Revision:
8:41b7274a9753
Parent:
5:8f486f4d29d3
Child:
11:23f61057d877
Added built-in help shell cmd, removed debug prints, display help on start.

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