Simple embedded shell with runtime pluggable commands.

Dependents:   DataBus2018

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

SimpleShell.h

Committer:
shimniok
Date:
2018-12-31
Revision:
35:1a8c5fce8895
Parent:
31:27e8130a0d8f

File content as of revision 35:1a8c5fce8895:

#ifndef __SIMPLESHELL_H
#define __SIMPLESHELL_H

#include "mbed.h"
#include <vector>

/** A simple, flexible, embedded shell with dynamically added shell commands.
 * Shell commands must be: void(int argc, char **argv)
 * Built-in shell commands include:
 * help: display list of commands
 * cd: Change current directory
 * pwd: print working directory
 * ls: list files in directory
 * rm: remove a file
 * touch: create a file
 * cat: display contents of file
 * send: send a file with a simple file transfer protocol. 
 * @see https://github.com/shimniok/ascii-transfer
 * 
 * @code
 * #include "SimpleShell.h"
 *
 * void helloworld(int argc, char **argv) { printf("Hello world!\n"); }
 *
 * int main() {
 *   SimpleShell sh;
 *   sh.attach(helloworld, "test");
 *   sh.run();
 * }
 * @endcode
 */
class SimpleShell {
public:

    /// Callback type used for shell commands.
    typedef Callback<void(int,char**)> callback_t;
    
    /// Create a new shell instance.
    SimpleShell(char *home);

    /** Call this to run the shell.
     * @note The shell can be run in a new thread. Be sure to give it enough
     * stack space.
     * @code
     * SimpleShell sh;
     * sh.run();
     * thread.start(callback(&sh, &SimpleShell::run));
     * @endcode
     */
    void run();

    /** Adds a shell command.
     * @param cb is the callback function that implements the command
     * @param command is the string used to invoke the command in the shell
     * @code
     * sh.attach(helloworld, "test");
     * @endcode
     */
    void command(callback_t cb, char *command);

    /** Determine if the specified string includes a shell wildcard
     * @param s is the string to check for a wildcard character
     * @returns true or false
     */
    bool haswildcard(char *s);

    /** Canonicalize path following unix-style convention.
     * The specified path can be absolute or relative path names. If relative,
     * the path is appended to cwd.
     * @param path is the specified path
     * @returns canonicalized path name
     */
    char *canon(char *path);

    /** Get the basename of specified path.
     * For example, basename("/foo/bar/whee") returns "whee"
     * @param path is the path specification, assumed to be canonicalized
     * @returns the basename of the path
     */
    char *basename(char *path);
    
    /** Get the parent directory of specified path.
     * For example, basename("/foo/bar/whee") returns "/foo/bar"
     * @param path is the path specification, assumed to be canonicalized
     * @returns the parent directory of the path
     */
    char *dirname(char *path);
    
    /** Runs a callback on each matching file in the specified pattern
     * @param pattern is a filename pattern ala Linux fnmatch(3)
     * @param cb is the int(char*) function on which each file match is called
     * @return false if cb returns non-zero on any file, true otherwise
     *
     * @code
     * if (foreach("/test/\*.txt", callback(remove)) {
     *     printf("error!\n");
     * }
     * @endcode
     */
    char *foreach(char *pattern);

private:
    /// Maximum number of commands
    static const int MAXLOOKUP=24;

    /// Maximum command line buffer size
    static const int MAXBUF=64;
    
    /// Maximum filename size
    static const int MAXNAMESIZE=64;

    /// internal struct to contain a single command
    typedef struct {
        char *command;
        callback_t cb;
    } command_entry_t;

    /// internal file list for wildcards
    typedef vector<char*> filelist_t;

    /** finds and eturns the callback for a command
     * @return Callback to a function returning void
     */
    callback_t findCommand();

    /// Built-in shell command to display list of commands
    void help(int argc, char **argv);

    /// Change current directory
    void cd(int argc, char **argv);

    /// Built-in shell command to print working directory
    void pwd(int argc, char **argv);

    /// Built-in shell command to list files in directory
    void ls(int argc, char **argv);

    /// Built-in shell command to remove a file
    void rm(int argc, char **argv);

    /// Built-in shell command to create a file
    void touch(int argc, char **argv);

    /// Built-in shell command to display contents of file
    void cat(int argc, char **argv);
    
    /// Built-in shell command to display contents of file
    void send(int argc, char **argv);

    /// Prints command prompt
    void printPrompt(void);

    /// Reads a command from the prompt (with editing)
    void readCommand();

    /// Command lookup table
    command_entry_t lookup[MAXLOOKUP];

    /// Current end of lookup table
    int lookupEnd;

    /// Maximum number of arguments
    static const int MAXARGS=5;

    /// Command and arguments
    char *argv[MAXARGS];

    /// Size of argv
    int argc;

    /// Current working directory
    char _cwd[MAXBUF];
    
    /// Home directory
    char _home[MAXBUF];

}; // class

#endif