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:
Thu Dec 27 15:50:34 2018 +0000
Revision:
30:35522ea06236
Parent:
29:8d4132274445
Child:
31:27e8130a0d8f
Fixed bug: too many command args causes crash

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shimniok 22:b0e6d416ce99 1 #ifndef __SIMPLESHELL_H
shimniok 22:b0e6d416ce99 2 #define __SIMPLESHELL_H
shimniok 22:b0e6d416ce99 3
shimniok 22:b0e6d416ce99 4 #include "mbed.h"
shimniok 22:b0e6d416ce99 5
shimniok 25:9340833d92c0 6 /** A simple, flexible, embedded shell with dynamically added shell commands.
shimniok 26:0067bd31653f 7 * Shell commands must be: void(int argc, char **argv)
shimniok 26:0067bd31653f 8 * Built-in shell commands include:
shimniok 26:0067bd31653f 9 * help: display list of commands
shimniok 26:0067bd31653f 10 * cd: Change current directory
shimniok 26:0067bd31653f 11 * pwd: print working directory
shimniok 26:0067bd31653f 12 * ls: list files in directory
shimniok 26:0067bd31653f 13 * rm: remove a file
shimniok 26:0067bd31653f 14 * touch: create a file
shimniok 26:0067bd31653f 15 * cat: display contents of file
shimniok 26:0067bd31653f 16 * send: send a file with a simple file transfer protocol.
shimniok 26:0067bd31653f 17 * @see https://github.com/shimniok/ascii-transfer
shimniok 26:0067bd31653f 18 *
shimniok 22:b0e6d416ce99 19 * @code
shimniok 22:b0e6d416ce99 20 * #include "SimpleShell.h"
shimniok 22:b0e6d416ce99 21 *
shimniok 25:9340833d92c0 22 * void helloworld(int argc, char **argv) { printf("Hello world!\n"); }
shimniok 22:b0e6d416ce99 23 *
shimniok 22:b0e6d416ce99 24 * int main() {
shimniok 22:b0e6d416ce99 25 * SimpleShell sh;
shimniok 22:b0e6d416ce99 26 * sh.attach(helloworld, "test");
shimniok 22:b0e6d416ce99 27 * sh.run();
shimniok 22:b0e6d416ce99 28 * }
shimniok 22:b0e6d416ce99 29 * @endcode
shimniok 22:b0e6d416ce99 30 */
shimniok 22:b0e6d416ce99 31 class SimpleShell {
shimniok 22:b0e6d416ce99 32 public:
shimniok 22:b0e6d416ce99 33
shimniok 26:0067bd31653f 34 /// Callback type used for shell commands.
shimniok 27:51120f1cec44 35 typedef Callback<void(int,char**)> callback_t;
shimniok 28:753db82debb1 36
shimniok 26:0067bd31653f 37 /// Create a new shell instance.
shimniok 29:8d4132274445 38 SimpleShell(char *home);
shimniok 22:b0e6d416ce99 39
shimniok 22:b0e6d416ce99 40 /** Call this to run the shell.
shimniok 26:0067bd31653f 41 * @note The shell can be run in a new thread. Be sure to give it enough
shimniok 26:0067bd31653f 42 * stack space.
shimniok 22:b0e6d416ce99 43 * @code
shimniok 22:b0e6d416ce99 44 * SimpleShell sh;
shimniok 22:b0e6d416ce99 45 * sh.run();
shimniok 22:b0e6d416ce99 46 * thread.start(callback(&sh, &SimpleShell::run));
shimniok 22:b0e6d416ce99 47 * @endcode
shimniok 22:b0e6d416ce99 48 */
shimniok 22:b0e6d416ce99 49 void run();
shimniok 22:b0e6d416ce99 50
shimniok 26:0067bd31653f 51 /** Adds a shell command.
shimniok 22:b0e6d416ce99 52 * @param cb is the callback function that implements the command
shimniok 22:b0e6d416ce99 53 * @param command is the string used to invoke the command in the shell
shimniok 22:b0e6d416ce99 54 * @code
shimniok 22:b0e6d416ce99 55 * sh.attach(helloworld, "test");
shimniok 22:b0e6d416ce99 56 * @endcode
shimniok 22:b0e6d416ce99 57 */
shimniok 26:0067bd31653f 58 void command(callback_t cb, char *command);
shimniok 22:b0e6d416ce99 59
shimniok 26:0067bd31653f 60 /** Canonicalize path following unix-style convention.
shimniok 26:0067bd31653f 61 * The specified path can be absolute or relative path names. If relative,
shimniok 26:0067bd31653f 62 * the path is appended to cwd.
shimniok 26:0067bd31653f 63 * @param path is the specified path
shimniok 26:0067bd31653f 64 * @returns canonicalized path name
shimniok 26:0067bd31653f 65 */
shimniok 26:0067bd31653f 66 char *canon(char *path);
shimniok 26:0067bd31653f 67
shimniok 26:0067bd31653f 68 /** Get the basename of specified path.
shimniok 26:0067bd31653f 69 * @param path is the path specification, assumed to be canonicalized
shimniok 26:0067bd31653f 70 * @returns the basename of the path
shimniok 26:0067bd31653f 71 */
shimniok 26:0067bd31653f 72 char *basename(char *path);
shimniok 22:b0e6d416ce99 73
shimniok 22:b0e6d416ce99 74 private:
shimniok 22:b0e6d416ce99 75 /// Maximum number of commands
shimniok 26:0067bd31653f 76 static const int MAXLOOKUP=24;
shimniok 22:b0e6d416ce99 77
shimniok 22:b0e6d416ce99 78 /// Maximum command line buffer size
shimniok 22:b0e6d416ce99 79 static const int MAXBUF=64;
shimniok 22:b0e6d416ce99 80
shimniok 22:b0e6d416ce99 81 /// internal struct to contain a single command
shimniok 22:b0e6d416ce99 82 typedef struct {
shimniok 22:b0e6d416ce99 83 char *command;
shimniok 22:b0e6d416ce99 84 callback_t cb;
shimniok 22:b0e6d416ce99 85 } command_entry_t;
shimniok 22:b0e6d416ce99 86
shimniok 22:b0e6d416ce99 87 /** finds and eturns the callback for a command
shimniok 22:b0e6d416ce99 88 * @return Callback to a function returning void
shimniok 22:b0e6d416ce99 89 */
shimniok 22:b0e6d416ce99 90 callback_t findCommand();
shimniok 22:b0e6d416ce99 91
shimniok 22:b0e6d416ce99 92 /// Built-in shell command to display list of commands
shimniok 22:b0e6d416ce99 93 void help(int argc, char **argv);
shimniok 22:b0e6d416ce99 94
shimniok 22:b0e6d416ce99 95 /// Change current directory
shimniok 22:b0e6d416ce99 96 void cd(int argc, char **argv);
shimniok 22:b0e6d416ce99 97
shimniok 22:b0e6d416ce99 98 /// Built-in shell command to print working directory
shimniok 22:b0e6d416ce99 99 void pwd(int argc, char **argv);
shimniok 22:b0e6d416ce99 100
shimniok 22:b0e6d416ce99 101 /// Built-in shell command to list files in directory
shimniok 22:b0e6d416ce99 102 void ls(int argc, char **argv);
shimniok 22:b0e6d416ce99 103
shimniok 22:b0e6d416ce99 104 /// Built-in shell command to remove a file
shimniok 22:b0e6d416ce99 105 void rm(int argc, char **argv);
shimniok 22:b0e6d416ce99 106
shimniok 22:b0e6d416ce99 107 /// Built-in shell command to create a file
shimniok 22:b0e6d416ce99 108 void touch(int argc, char **argv);
shimniok 22:b0e6d416ce99 109
shimniok 22:b0e6d416ce99 110 /// Built-in shell command to display contents of file
shimniok 22:b0e6d416ce99 111 void cat(int argc, char **argv);
shimniok 23:b1e49cfcaef6 112
shimniok 23:b1e49cfcaef6 113 /// Built-in shell command to display contents of file
shimniok 23:b1e49cfcaef6 114 void send(int argc, char **argv);
shimniok 22:b0e6d416ce99 115
shimniok 22:b0e6d416ce99 116 /// Prints command prompt
shimniok 22:b0e6d416ce99 117 void printPrompt(void);
shimniok 22:b0e6d416ce99 118
shimniok 22:b0e6d416ce99 119 /// Reads a command from the prompt (with editing)
shimniok 22:b0e6d416ce99 120 void readCommand();
shimniok 22:b0e6d416ce99 121
shimniok 22:b0e6d416ce99 122 /// Command lookup table
shimniok 22:b0e6d416ce99 123 command_entry_t lookup[MAXLOOKUP];
shimniok 22:b0e6d416ce99 124
shimniok 22:b0e6d416ce99 125 /// Current end of lookup table
shimniok 22:b0e6d416ce99 126 int lookupEnd;
shimniok 22:b0e6d416ce99 127
shimniok 22:b0e6d416ce99 128 /// Maximum number of arguments
shimniok 30:35522ea06236 129 static const int MAXARGS=5;
shimniok 22:b0e6d416ce99 130
shimniok 22:b0e6d416ce99 131 /// Command and arguments
shimniok 22:b0e6d416ce99 132 char *argv[MAXARGS];
shimniok 22:b0e6d416ce99 133
shimniok 22:b0e6d416ce99 134 /// Size of argv
shimniok 22:b0e6d416ce99 135 int argc;
shimniok 22:b0e6d416ce99 136
shimniok 22:b0e6d416ce99 137 /// Current working directory
shimniok 22:b0e6d416ce99 138 char _cwd[MAXBUF];
shimniok 29:8d4132274445 139
shimniok 29:8d4132274445 140 /// Home directory
shimniok 29:8d4132274445 141 char _home[MAXBUF];
shimniok 22:b0e6d416ce99 142
shimniok 22:b0e6d416ce99 143 }; // class
shimniok 22:b0e6d416ce99 144
shimniok 22:b0e6d416ce99 145 #endif