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:
Mon Dec 31 23:34:17 2018 +0000
Revision:
35:1a8c5fce8895
Parent:
31:27e8130a0d8f
trying wildcards still.

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 35:1a8c5fce8895 5 #include <vector>
shimniok 22:b0e6d416ce99 6
shimniok 25:9340833d92c0 7 /** A simple, flexible, embedded shell with dynamically added shell commands.
shimniok 26:0067bd31653f 8 * Shell commands must be: void(int argc, char **argv)
shimniok 26:0067bd31653f 9 * Built-in shell commands include:
shimniok 26:0067bd31653f 10 * help: display list of commands
shimniok 26:0067bd31653f 11 * cd: Change current directory
shimniok 26:0067bd31653f 12 * pwd: print working directory
shimniok 26:0067bd31653f 13 * ls: list files in directory
shimniok 26:0067bd31653f 14 * rm: remove a file
shimniok 26:0067bd31653f 15 * touch: create a file
shimniok 26:0067bd31653f 16 * cat: display contents of file
shimniok 26:0067bd31653f 17 * send: send a file with a simple file transfer protocol.
shimniok 26:0067bd31653f 18 * @see https://github.com/shimniok/ascii-transfer
shimniok 26:0067bd31653f 19 *
shimniok 22:b0e6d416ce99 20 * @code
shimniok 22:b0e6d416ce99 21 * #include "SimpleShell.h"
shimniok 22:b0e6d416ce99 22 *
shimniok 25:9340833d92c0 23 * void helloworld(int argc, char **argv) { printf("Hello world!\n"); }
shimniok 22:b0e6d416ce99 24 *
shimniok 22:b0e6d416ce99 25 * int main() {
shimniok 22:b0e6d416ce99 26 * SimpleShell sh;
shimniok 22:b0e6d416ce99 27 * sh.attach(helloworld, "test");
shimniok 22:b0e6d416ce99 28 * sh.run();
shimniok 22:b0e6d416ce99 29 * }
shimniok 22:b0e6d416ce99 30 * @endcode
shimniok 22:b0e6d416ce99 31 */
shimniok 22:b0e6d416ce99 32 class SimpleShell {
shimniok 22:b0e6d416ce99 33 public:
shimniok 22:b0e6d416ce99 34
shimniok 26:0067bd31653f 35 /// Callback type used for shell commands.
shimniok 27:51120f1cec44 36 typedef Callback<void(int,char**)> callback_t;
shimniok 28:753db82debb1 37
shimniok 26:0067bd31653f 38 /// Create a new shell instance.
shimniok 29:8d4132274445 39 SimpleShell(char *home);
shimniok 22:b0e6d416ce99 40
shimniok 22:b0e6d416ce99 41 /** Call this to run the shell.
shimniok 26:0067bd31653f 42 * @note The shell can be run in a new thread. Be sure to give it enough
shimniok 26:0067bd31653f 43 * stack space.
shimniok 22:b0e6d416ce99 44 * @code
shimniok 22:b0e6d416ce99 45 * SimpleShell sh;
shimniok 22:b0e6d416ce99 46 * sh.run();
shimniok 22:b0e6d416ce99 47 * thread.start(callback(&sh, &SimpleShell::run));
shimniok 22:b0e6d416ce99 48 * @endcode
shimniok 22:b0e6d416ce99 49 */
shimniok 22:b0e6d416ce99 50 void run();
shimniok 22:b0e6d416ce99 51
shimniok 26:0067bd31653f 52 /** Adds a shell command.
shimniok 22:b0e6d416ce99 53 * @param cb is the callback function that implements the command
shimniok 22:b0e6d416ce99 54 * @param command is the string used to invoke the command in the shell
shimniok 22:b0e6d416ce99 55 * @code
shimniok 22:b0e6d416ce99 56 * sh.attach(helloworld, "test");
shimniok 22:b0e6d416ce99 57 * @endcode
shimniok 22:b0e6d416ce99 58 */
shimniok 26:0067bd31653f 59 void command(callback_t cb, char *command);
shimniok 22:b0e6d416ce99 60
shimniok 31:27e8130a0d8f 61 /** Determine if the specified string includes a shell wildcard
shimniok 31:27e8130a0d8f 62 * @param s is the string to check for a wildcard character
shimniok 31:27e8130a0d8f 63 * @returns true or false
shimniok 31:27e8130a0d8f 64 */
shimniok 31:27e8130a0d8f 65 bool haswildcard(char *s);
shimniok 31:27e8130a0d8f 66
shimniok 26:0067bd31653f 67 /** Canonicalize path following unix-style convention.
shimniok 26:0067bd31653f 68 * The specified path can be absolute or relative path names. If relative,
shimniok 26:0067bd31653f 69 * the path is appended to cwd.
shimniok 26:0067bd31653f 70 * @param path is the specified path
shimniok 26:0067bd31653f 71 * @returns canonicalized path name
shimniok 26:0067bd31653f 72 */
shimniok 26:0067bd31653f 73 char *canon(char *path);
shimniok 26:0067bd31653f 74
shimniok 26:0067bd31653f 75 /** Get the basename of specified path.
shimniok 35:1a8c5fce8895 76 * For example, basename("/foo/bar/whee") returns "whee"
shimniok 26:0067bd31653f 77 * @param path is the path specification, assumed to be canonicalized
shimniok 26:0067bd31653f 78 * @returns the basename of the path
shimniok 26:0067bd31653f 79 */
shimniok 26:0067bd31653f 80 char *basename(char *path);
shimniok 35:1a8c5fce8895 81
shimniok 35:1a8c5fce8895 82 /** Get the parent directory of specified path.
shimniok 35:1a8c5fce8895 83 * For example, basename("/foo/bar/whee") returns "/foo/bar"
shimniok 35:1a8c5fce8895 84 * @param path is the path specification, assumed to be canonicalized
shimniok 35:1a8c5fce8895 85 * @returns the parent directory of the path
shimniok 35:1a8c5fce8895 86 */
shimniok 35:1a8c5fce8895 87 char *dirname(char *path);
shimniok 35:1a8c5fce8895 88
shimniok 35:1a8c5fce8895 89 /** Runs a callback on each matching file in the specified pattern
shimniok 35:1a8c5fce8895 90 * @param pattern is a filename pattern ala Linux fnmatch(3)
shimniok 35:1a8c5fce8895 91 * @param cb is the int(char*) function on which each file match is called
shimniok 35:1a8c5fce8895 92 * @return false if cb returns non-zero on any file, true otherwise
shimniok 35:1a8c5fce8895 93 *
shimniok 35:1a8c5fce8895 94 * @code
shimniok 35:1a8c5fce8895 95 * if (foreach("/test/\*.txt", callback(remove)) {
shimniok 35:1a8c5fce8895 96 * printf("error!\n");
shimniok 35:1a8c5fce8895 97 * }
shimniok 35:1a8c5fce8895 98 * @endcode
shimniok 35:1a8c5fce8895 99 */
shimniok 35:1a8c5fce8895 100 char *foreach(char *pattern);
shimniok 22:b0e6d416ce99 101
shimniok 22:b0e6d416ce99 102 private:
shimniok 22:b0e6d416ce99 103 /// Maximum number of commands
shimniok 26:0067bd31653f 104 static const int MAXLOOKUP=24;
shimniok 22:b0e6d416ce99 105
shimniok 22:b0e6d416ce99 106 /// Maximum command line buffer size
shimniok 22:b0e6d416ce99 107 static const int MAXBUF=64;
shimniok 35:1a8c5fce8895 108
shimniok 35:1a8c5fce8895 109 /// Maximum filename size
shimniok 35:1a8c5fce8895 110 static const int MAXNAMESIZE=64;
shimniok 22:b0e6d416ce99 111
shimniok 22:b0e6d416ce99 112 /// internal struct to contain a single command
shimniok 22:b0e6d416ce99 113 typedef struct {
shimniok 22:b0e6d416ce99 114 char *command;
shimniok 22:b0e6d416ce99 115 callback_t cb;
shimniok 22:b0e6d416ce99 116 } command_entry_t;
shimniok 22:b0e6d416ce99 117
shimniok 35:1a8c5fce8895 118 /// internal file list for wildcards
shimniok 35:1a8c5fce8895 119 typedef vector<char*> filelist_t;
shimniok 35:1a8c5fce8895 120
shimniok 22:b0e6d416ce99 121 /** finds and eturns the callback for a command
shimniok 22:b0e6d416ce99 122 * @return Callback to a function returning void
shimniok 22:b0e6d416ce99 123 */
shimniok 22:b0e6d416ce99 124 callback_t findCommand();
shimniok 22:b0e6d416ce99 125
shimniok 22:b0e6d416ce99 126 /// Built-in shell command to display list of commands
shimniok 22:b0e6d416ce99 127 void help(int argc, char **argv);
shimniok 22:b0e6d416ce99 128
shimniok 22:b0e6d416ce99 129 /// Change current directory
shimniok 22:b0e6d416ce99 130 void cd(int argc, char **argv);
shimniok 22:b0e6d416ce99 131
shimniok 22:b0e6d416ce99 132 /// Built-in shell command to print working directory
shimniok 22:b0e6d416ce99 133 void pwd(int argc, char **argv);
shimniok 22:b0e6d416ce99 134
shimniok 22:b0e6d416ce99 135 /// Built-in shell command to list files in directory
shimniok 22:b0e6d416ce99 136 void ls(int argc, char **argv);
shimniok 22:b0e6d416ce99 137
shimniok 22:b0e6d416ce99 138 /// Built-in shell command to remove a file
shimniok 22:b0e6d416ce99 139 void rm(int argc, char **argv);
shimniok 22:b0e6d416ce99 140
shimniok 22:b0e6d416ce99 141 /// Built-in shell command to create a file
shimniok 22:b0e6d416ce99 142 void touch(int argc, char **argv);
shimniok 22:b0e6d416ce99 143
shimniok 22:b0e6d416ce99 144 /// Built-in shell command to display contents of file
shimniok 22:b0e6d416ce99 145 void cat(int argc, char **argv);
shimniok 23:b1e49cfcaef6 146
shimniok 23:b1e49cfcaef6 147 /// Built-in shell command to display contents of file
shimniok 23:b1e49cfcaef6 148 void send(int argc, char **argv);
shimniok 22:b0e6d416ce99 149
shimniok 22:b0e6d416ce99 150 /// Prints command prompt
shimniok 22:b0e6d416ce99 151 void printPrompt(void);
shimniok 22:b0e6d416ce99 152
shimniok 22:b0e6d416ce99 153 /// Reads a command from the prompt (with editing)
shimniok 22:b0e6d416ce99 154 void readCommand();
shimniok 22:b0e6d416ce99 155
shimniok 22:b0e6d416ce99 156 /// Command lookup table
shimniok 22:b0e6d416ce99 157 command_entry_t lookup[MAXLOOKUP];
shimniok 22:b0e6d416ce99 158
shimniok 22:b0e6d416ce99 159 /// Current end of lookup table
shimniok 22:b0e6d416ce99 160 int lookupEnd;
shimniok 22:b0e6d416ce99 161
shimniok 22:b0e6d416ce99 162 /// Maximum number of arguments
shimniok 30:35522ea06236 163 static const int MAXARGS=5;
shimniok 22:b0e6d416ce99 164
shimniok 22:b0e6d416ce99 165 /// Command and arguments
shimniok 22:b0e6d416ce99 166 char *argv[MAXARGS];
shimniok 22:b0e6d416ce99 167
shimniok 22:b0e6d416ce99 168 /// Size of argv
shimniok 22:b0e6d416ce99 169 int argc;
shimniok 22:b0e6d416ce99 170
shimniok 22:b0e6d416ce99 171 /// Current working directory
shimniok 22:b0e6d416ce99 172 char _cwd[MAXBUF];
shimniok 29:8d4132274445 173
shimniok 29:8d4132274445 174 /// Home directory
shimniok 29:8d4132274445 175 char _home[MAXBUF];
shimniok 22:b0e6d416ce99 176
shimniok 22:b0e6d416ce99 177 }; // class
shimniok 22:b0e6d416ce99 178
shimniok 22:b0e6d416ce99 179 #endif