Simple embedded shell with runtime pluggable commands.
Implements a simple unix-like shell for embedded systems with a pluggable command architecture.
SimpleShell.cpp
- Committer:
- shimniok
- Date:
- 2018-12-13
- Revision:
- 11:23f61057d877
- Parent:
- 10:c3faa7ffd23b
- Parent:
- 8:41b7274a9753
- Child:
- 12:ecf3fc049bca
File content as of revision 11:23f61057d877:
#include "SimpleShell.h" #include <ctype.h> #define ESC 0x1b SimpleShell::SimpleShell() { lookupEnd = 0; // Built-in shell commands attach(callback(this, &SimpleShell::help), "help"); // TODO: cd } void SimpleShell::help() { printf("Available commands: "); for (int i=0; i < lookupEnd; i++) { printf("%s ", lookup[i].command); } printf("\n\n"); } void SimpleShell::run() { bool done=false; Callback<void()> cb; int status; // TODO implement command status return strcpy(_cwd, "/log"); printf("Type help for assistance.\n"); help(); while (!done) { printPrompt(); readCommand(); if (cmd[0]) { // skip blank command if (cb = findCommand()) { cb.call(); } else { printf("command <%s> not found\n", cmd); } } } puts("exiting shell\n"); return; } void SimpleShell::attach(Callback<void()> cb, char *command) { if (lookupEnd < MAXLOOKUP) { lookup[lookupEnd].cb = cb; lookup[lookupEnd].command = command; lookupEnd++; } return; } Callback<void()> SimpleShell::findCommand() { Callback<void()> cb=NULL; for (int i=0; i < lookupEnd; i++) { if (strncmp(cmd, 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; 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) char c2 = getchar(); char c3 = getchar(); if (c2 == 0x4f && c3 == 0x46) { printf("<END>"); } else if (c2 == 0x5b) { switch (c3) { case 0x41 : // up printf("<UP>"); break; case 0x42 : // down printf("<DOWN>"); break; case 0x43 : // right printf("<RIGHT>"); break; case 0x44 : // left printf("<LEFT>"); break; case 0x31 : // home case 0x32 : // ins case 0x33: // del case 0x35: // pgup case 0x36: // pgdn char c4 = getchar(); if (c4 == 0x7e) { switch (c3) { case 0x31 : printf("<HOME>"); break; case 0x32 : // ins printf("<INS>"); break; case 0x33: // del printf("<DEL>"); break; case 0x35: // pgup printf("<PGUP>"); break; case 0x36: // pgdn printf("<PGDN>"); break; default: break; }//switch }//if default: //printf("<0x%02x>", c3); break; }//switch }//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); // chomp for (int j=i; j >= 0; j--) { if (isspace(cmd[j])) { cmd[j] = '\0'; } } return; }