From 854b218cb41809a5b688e6be538a9b83c640e79b Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Fri, 18 Mar 2016 18:48:16 +0100 Subject: [PATCH] Moved snippet in msh-console-snippet repository. All the code in the library is in the namespace mshconsole. Added CommandExecutor::exit() for exiting from the shell. --- .gitignore | 3 + CMakeLists.txt | 9 - msh-console-library/CMakeLists.txt | 6 +- msh-console-library/command.cpp | 48 ++-- msh-console-library/command.h | 29 +- msh-console-library/commandexecutor.cpp | 9 +- msh-console-library/commandexecutor.h | 21 +- msh-console-library/commands.cpp | 43 +-- msh-console-library/shell.cpp | 349 ++++++++++++------------ msh-console-library/shell.h | 93 +++---- snippet/CMakeLists.txt | 9 - snippet/cmds.cpp | 28 -- snippet/cmds.h | 17 -- snippet/main.cpp | 32 --- 14 files changed, 309 insertions(+), 387 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 snippet/CMakeLists.txt delete mode 100644 snippet/cmds.cpp delete mode 100644 snippet/cmds.h delete mode 100644 snippet/main.cpp diff --git a/.gitignore b/.gitignore index 1a755a1..5b7c88f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# autosaves +*.autosave + #kate directory files *.directory diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 65b9522..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -project(msh-console-test) -cmake_minimum_required(VERSION 2.8) -aux_source_directory(. SRC_LIST) - -# Recurse into the subdirectories. This does not actually -# cause another cmake executable to run. The same process will walk through -# the project's entire directory structure. -add_subdirectory (msh-console-library) -add_subdirectory (snippet) diff --git a/msh-console-library/CMakeLists.txt b/msh-console-library/CMakeLists.txt index 84414f7..969ba42 100644 --- a/msh-console-library/CMakeLists.txt +++ b/msh-console-library/CMakeLists.txt @@ -6,8 +6,4 @@ cmake_minimum_required(VERSION 2.8) # Create a library which includes the source listed. # The extension is already found. Any number of sources could be listed here. SET(CMAKE_CXX_FLAGS "-std=c++11") -add_library (msh-console command.cpp commandexecutor.cpp commandexecutor.h command.h commands.cpp shell.cpp shell.h) - -# Make sure the compiler can find include files for the library -# when other libraries or executables link to this library -target_include_directories (msh-console PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +add_library (mshconsole SHARED command.cpp commandexecutor.cpp commandexecutor.h command.h commands.cpp shell.cpp shell.h) diff --git a/msh-console-library/command.cpp b/msh-console-library/command.cpp index 93f0b7e..cf83401 100644 --- a/msh-console-library/command.cpp +++ b/msh-console-library/command.cpp @@ -1,34 +1,36 @@ #include "shell.h" +namespace mshconsole { -Command::Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)) : name(n) , funcCommand(funcptr){ - checkObj(); - numCom++; -} + Command::Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)) : name(n) , funcCommand(funcptr){ + checkObj(); + numCom++; + } -int Command::execute(const vector* args, CommandExecutor* ciao){ - if(args==nullptr) return -1; - return (*funcCommand)(args, ciao); -} + int Command::execute(const vector* args, CommandExecutor* ciao){ + if(args==nullptr) return -1; + return (*funcCommand)(args, ciao); + } -string Command::getName(){ - return this->name; -} + string Command::getName(){ + return this->name; + } -Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){ - checkObj(); - numCom++; -} + Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){ + checkObj(); + numCom++; + } -void Command::checkObj(){ - for(unsigned int i=0; i'a'&&name[i]<'z')||(name[i]>'A'&&name[i]<'Z'))){ - throw CommandNameNotValidException(); + void Command::checkObj(){ + for(unsigned int i=0; i'a'&&name[i]<'z')||(name[i]>'A'&&name[i]<'Z'))){ + throw CommandNameNotValidException(); + } } } -} -Command::~Command(){ - numCom--; -} + Command::~Command(){ + numCom--; + } unsigned int Command::numCom = 0; +} diff --git a/msh-console-library/command.h b/msh-console-library/command.h index ddf56a9..eeaf36d 100644 --- a/msh-console-library/command.h +++ b/msh-console-library/command.h @@ -8,21 +8,22 @@ using std::string; using std::vector; -class Command -{ - const string name; - static unsigned int numCom; - int (*funcCommand)(const vector*,CommandExecutor*); - void checkObj(); - -public: - Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)); - Command(const Command&); - ~Command(); - string getName(); - int execute(const vector*, CommandExecutor* ciao); -}; +namespace mshconsole{ + class Command + { + const string name; + static unsigned int numCom; + int (*funcCommand)(const vector*,CommandExecutor*); + void checkObj(); + public: + Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)); + Command(const Command&); + ~Command(); + string getName(); + int execute(const vector*, CommandExecutor* ciao); + }; +} class CommandNameNotValidException{}; #endif // COMMAND_H diff --git a/msh-console-library/commandexecutor.cpp b/msh-console-library/commandexecutor.cpp index 978d62f..a485c91 100644 --- a/msh-console-library/commandexecutor.cpp +++ b/msh-console-library/commandexecutor.cpp @@ -1,6 +1,7 @@ #include "commandexecutor.h" - -CommandExecutor::CommandExecutor() -{ - +namespace mshconsole { + CommandExecutor::CommandExecutor() {} + void CommandExecutor::exit(){ + throw CommandExecutor::ExitException(); + } } diff --git a/msh-console-library/commandexecutor.h b/msh-console-library/commandexecutor.h index 5a54499..0f034ee 100644 --- a/msh-console-library/commandexecutor.h +++ b/msh-console-library/commandexecutor.h @@ -3,13 +3,18 @@ #include #include -class CommandExecutor -{ -public: - virtual int executeCmd(std::vector* args) = 0; - virtual int executeCmd(const std::string& args) = 0; - virtual size_t howManyCmds() const = 0; - CommandExecutor(); -}; +namespace mshconsole{ + class CommandExecutor + { + protected: + class ExitException {}; + public: + virtual int executeCmd(std::vector* args) = 0; + virtual int executeCmd(const std::string& args) = 0; + virtual size_t howManyCmds() const = 0; + void exit(); + CommandExecutor(); + }; +} #endif // COMMANDEXECUTOR_H diff --git a/msh-console-library/commands.cpp b/msh-console-library/commands.cpp index 23ad5c2..84501b7 100644 --- a/msh-console-library/commands.cpp +++ b/msh-console-library/commands.cpp @@ -1,26 +1,27 @@ #include "shell.h" - -Shell::Commands::Commands(Shell* s) : commands(), threadCommands() -{ - parent = s; -} - -void Shell::Commands::add(Command* cmd, bool isthread){ - if(!isthread) commands.push_back(cmd); - else threadCommands.push_back(cmd); -} - -size_t Shell::Commands::howMany() const{ - return commands.size(); -} - -int Shell::Commands::launch(const vector* args, bool launchThread){ - for(unsigned int i=0; i<(launchThread ? threadCommands.size() : commands.size()); i++){ - if((launchThread ? threadCommands[i]->getName() : commands[i]->getName())==args->operator [](0)){ - return (launchThread ? threadCommands[i]->execute(args, parent) : commands[i]->execute(args, parent)); - } +namespace mshconsole { + Shell::Commands::Commands(Shell* s) : commands(), threadCommands() + { + parent = s; + } + + void Shell::Commands::add(Command* cmd, bool isthread){ + if(!isthread) commands.push_back(cmd); + else threadCommands.push_back(cmd); + } + + size_t Shell::Commands::howMany() const{ + return commands.size(); + } + + int Shell::Commands::launch(const vector* args, bool launchThread){ + for(unsigned int i=0; i<(launchThread ? threadCommands.size() : commands.size()); i++){ + if((launchThread ? threadCommands[i]->getName() : commands[i]->getName())==args->operator [](0)){ + return (launchThread ? threadCommands[i]->execute(args, parent) : commands[i]->execute(args, parent)); + } + } + throw CommandNotFoundException(); } - throw CommandNotFoundException(); } diff --git a/msh-console-library/shell.cpp b/msh-console-library/shell.cpp index d97c065..91cbf48 100644 --- a/msh-console-library/shell.cpp +++ b/msh-console-library/shell.cpp @@ -1,196 +1,203 @@ #include "shell.h" +namespace mshconsole { + string Shell::getPs() const + { + return ps; + } -string Shell::getPs() const -{ - return ps; -} + void Shell::setPs(const string &value) + { + ps = value; + } -void Shell::setPs(const string &value) -{ - ps = value; -} + string Shell::getName() const + { + return name; + } -string Shell::getName() const -{ - return name; -} + void Shell::setName(const string &value) + { + name = value; + } -void Shell::setName(const string &value) -{ - name = value; -} + Shell::Shell( string n, string ps,void (*s)(Shell*), void (*pss)(Shell*)) : cmds(this) + { + shellSetup = s; + name = n; + this->ps = ps; + shellPostSetup = pss; + notLoop = false; + } -Shell::Shell( string n, string ps,void (*s)(Shell*), void (*pss)(Shell*)) : cmds(this) -{ - shellSetup = s; - name = n; - this->ps = ps; - shellPostSetup = pss; - notLoop = false; -} + void Shell::launch(){ -void Shell::launch(){ - //launch setup - if(notLoop) { - throw ShellLaunchInSetupException(); - return; - } - if(shellSetup!=0) { - notLoop = true; - (*shellSetup)(this); - notLoop = false; - } - //launch loop - string* line; - vector* args; - int status; - do { - bool readSuccess; - do{ - cout << ps << " "; - try{ - line = read_line(); - readSuccess = true; - } - catch (IsUndoingLineException){ - cout << "\n"; - readSuccess = false; - } - }while(!readSuccess); - args = split_line(line); - status = executeCmd(args); - delete args; - } while (status); - if(shellPostSetup!=0) { - shellPostSetup(this); - } -} + //launch setup + if(notLoop) { + return; + } + if(shellSetup!=0) { + notLoop = true; + (*shellSetup)(this); + notLoop = false; + } -int Shell::launchCmd(vector* args) -{ - int status; + //launch loop + string* line; + vector* args; + int status; + try{ + do { + bool readSuccess; + do{ + cout << ps << " "; + try{ + line = read_line(); + readSuccess = true; + } + catch (IsUndoingLineException){ + cout << "\n"; + readSuccess = false; + } + }while(!readSuccess); + args = split_line(line); + status = executeCmd(args); + delete args; + } while (1); + } catch(CommandExecutor::ExitException) {} - pid_t pid = fork(); - if (pid == 0) { - //child process + //launch postSetup + if(shellPostSetup!=0) { + shellPostSetup(this); + } + } - //execute threadCommand - int a; - try { - a=cmds.launch(args, true); - } - catch (CommandNotFoundException){ - //execute bash command or program - vector argv(args->size() + 1); - size_t i; - for (i = 0; i != args->size()-1; ++i) - { - argv[i] = &(args->operator[](i)[0]); + int Shell::launchCmd(vector* args) + { + using std::exit; + int status; + + pid_t pid = fork(); + if (pid == 0) { + //child process + + //execute threadCommand + int a; + try { + a=cmds.launch(args, true); } - argv[i] = NULL; - if((a=execvp(argv[0], argv.data())) == -1) { - cerr << name <<": command " << args->operator [](0) << " not found\n"; + catch (CommandNotFoundException){ + //execute bash command or program + vector argv(args->size() + 1); + size_t i; + for (i = 0; i != args->size()-1; ++i) + { + argv[i] = &(args->operator[](i)[0]); + } + argv[i] = NULL; + if((a=execvp(argv[0], argv.data())) == -1) { + cerr << name <<": command " << args->operator [](0) << " not found\n"; + } + exit(EXIT_FAILURE); } - exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); + } + else if (pid < 0) { + // Error forking + cerr << name <<": error forking the process\n"; + } + else { + // Parent process + do { + //wait until child finished + waitpid(pid, &status, WUNTRACED); + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } - exit(EXIT_SUCCESS); - } - else if (pid < 0) { - // Error forking - cerr << name <<": error forking the process\n"; - } - else { - // Parent process - do { - //wait until child finished - waitpid(pid, &status, WUNTRACED); - } while (!WIFEXITED(status) && !WIFSIGNALED(status)); - } - return 1; -} - -int Shell::executeCmd(vector* args) -{ - if (args->operator [](0) == "\0") { - // An empty command was entered. return 1; } - int ret; - try { - ret = cmds.launch(args, false); + + int Shell::executeCmd(vector* args) + { + if (args->operator [](0) == "\0") { + // An empty command was entered. + return 1; + } + int ret; + try { + ret = cmds.launch(args, false); + } + catch(CommandNotFoundException) { + ret = launchCmd(args); + } + return ret; } - catch(CommandNotFoundException) { - ret = launchCmd(args); + + inline int Shell::executeCmd(const std::string &args){ + return executeCmd(split_line(&args)); } - return ret; -} -inline int Shell::executeCmd(const std::string &args){ - return executeCmd(split_line(&args)); -} - -void Shell::EofHandler(int){ - undoingLine = true; -} - -void Shell::setShellSetup(void (*s)(Shell *)){ - shellSetup=s; -} - -void (*Shell::getShellSetup())(Shell*) { - return shellSetup; -} - -void Shell::setShellPostSetup(void (*s)(Shell *)){ - shellPostSetup=s; -} - -void (*Shell::getShellPostSetup())(Shell*) { - return shellPostSetup; -} - - -void setEofHandler(void (*funcptr)(int)){ - struct sigaction *sa = new struct sigaction(); - sa->sa_handler = funcptr; - sa->sa_flags = 0; // not SA_RESTART!; - sigaction(SIGINT, sa, NULL); - delete sa; -} - -string* Shell::read_line() -{ - string* buffer = new string(); - setEofHandler(EofHandler); - getline(cin,*buffer); // get command - cin.clear(); // clear flags - - if(undoingLine){ - undoingLine=false; - throw IsUndoingLineException(); + void Shell::EofHandler(int){ + undoingLine = true; } - return buffer; -} -vector* Shell::split_line(const string* line) -{ - vector* tokens = new vector(); - string ln = *line; - istringstream is(ln); - int i; - for(i=0; getline(is, ln, ' '); i++){ - tokens->push_back(ln); + void Shell::setShellSetup(void (*s)(Shell *)){ + shellSetup=s; } - tokens->push_back("\0"); - return tokens; -} -bool Shell::undoingLine = false; + void (*Shell::getShellSetup())(Shell*) { + return shellSetup; + } -void Shell::addCmd(Command* cmd, bool isthread){ - cmds.add(cmd, isthread); -} + void Shell::setShellPostSetup(void (*s)(Shell *)){ + shellPostSetup=s; + } -size_t Shell::howManyCmds() const{ - return cmds.howMany(); + void (*Shell::getShellPostSetup())(Shell*) { + return shellPostSetup; + } + + + void setEofHandler(void (*funcptr)(int)){ + struct sigaction *sa = new struct sigaction(); + sa->sa_handler = funcptr; + sa->sa_flags = 0; // not SA_RESTART!; + sigaction(SIGINT, sa, NULL); + delete sa; + } + + string* Shell::read_line() + { + string* buffer = new string(); + setEofHandler(EofHandler); + getline(cin,*buffer); // get command + cin.clear(); // clear flags + + if(undoingLine){ + undoingLine=false; + throw IsUndoingLineException(); + } + return buffer; + } + + vector* Shell::split_line(const string* line) + { + vector* tokens = new vector(); + string ln = *line; + istringstream is(ln); + int i; + for(i=0; getline(is, ln, ' '); i++){ + tokens->push_back(ln); + } + tokens->push_back("\0"); + return tokens; + } + + bool Shell::undoingLine = false; + + void Shell::addCmd(Command* cmd, bool isthread){ + cmds.add(cmd, isthread); + } + + size_t Shell::howManyCmds() const{ + return cmds.howMany(); + } } diff --git a/msh-console-library/shell.h b/msh-console-library/shell.h index 192a0d8..f55fb2e 100644 --- a/msh-console-library/shell.h +++ b/msh-console-library/shell.h @@ -21,55 +21,56 @@ using std::vector; using std::istringstream; using std::nullptr_t; -class Shell : public CommandExecutor -{ - class Commands +namespace mshconsole { + + class Shell : public CommandExecutor { - Shell* parent; - vector commands; //commands that work the same thread of the shell - vector threadCommands; //commands that work on a different thread + class Commands + { + Shell* parent; + vector commands; //commands that work the same thread of the shell + vector threadCommands; //commands that work on a different thread + + public: + Commands(Shell*); + void add(Command*, bool isthread=false); + size_t howMany() const; + int launch(const vector* args, bool launchThread=false); + }; + static bool undoingLine; + Commands cmds; + string ps; + string name; + void (*shellSetup)(Shell *); + void (*shellPostSetup)(Shell *); + bool notLoop; + + int launchCmd(vector* args); + static void EofHandler(int); + string* read_line(); + vector* split_line(const string* line); + + class IsUndoingLineException {}; + class CommandNotFoundException {}; public: - Commands(Shell*); - void add(Command*, bool isthread=false); - size_t howMany() const; - int launch(const vector* args, bool launchThread=false); + Shell(string n="msh", string ps="MSH$", void (*s)(Shell*)=0, void (*pss)(Shell*)=0); + string getPs() const; + void setPs(const string &value); + string getName() const; + void setName(const string &value); + void launch(); + void setShellSetup(void (*)(Shell *)); + void (*getShellSetup())(Shell*); + void setShellPostSetup(void (*)(Shell *)); + void (*getShellPostSetup())(Shell*); + + //for in-shell commands + void addCmd(Command *cmd, bool isThread=false); + size_t howManyCmds() const; + int executeCmd(vector* args); + int executeCmd(const string& args); }; - static bool undoingLine; - Commands cmds; - string ps; - string name; - void (*shellSetup)(Shell *); - void (*shellPostSetup)(Shell *); - bool notLoop; - - int launchCmd(vector* args); - static void EofHandler(int); - string* read_line(); - vector* split_line(const string* line); - - class IsUndoingLineException {}; - -public: - Shell(string n="msh", string ps="MSH$", void (*s)(Shell*)=0, void (*pss)(Shell*)=0); - string getPs() const; - void setPs(const string &value); - string getName() const; - void setName(const string &value); - void launch(); - void setShellSetup(void (*)(Shell *)); - void (*getShellSetup())(Shell*); - void setShellPostSetup(void (*)(Shell *)); - void (*getShellPostSetup())(Shell*); - //for in-shell commands - void addCmd(Command *cmd, bool isThread=false); - size_t howManyCmds() const; - int executeCmd(vector* args); - int executeCmd(const string& args); - - //excepsetions - class CommandNotFoundException{}; - class ShellLaunchInSetupException{}; -}; +} #endif // SHELL_H diff --git a/snippet/CMakeLists.txt b/snippet/CMakeLists.txt deleted file mode 100644 index dfc4390..0000000 --- a/snippet/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# snippet for showing how the library works - -project(msh-console-library-snippet) -cmake_minimum_required(VERSION 2.8) - -SET(CMAKE_CXX_FLAGS "-std=c++11") -add_executable (../../build-msh-console/msh-console-test main.cpp cmds.cpp) -target_link_libraries (../../build-msh-console/msh-console-test LINK_PUBLIC msh-console) - diff --git a/snippet/cmds.cpp b/snippet/cmds.cpp deleted file mode 100644 index 4641550..0000000 --- a/snippet/cmds.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/** - builtin commands -*/ - -#include "cmds.h" - -using namespace std; - -int Cmds::cdExecute(const vector* args, CommandExecutor*){ - if (args->operator[](1) == "\0") { - cerr << "expected argument to \"cd\"\n"; - } else { - if (chdir(args->operator[](1).c_str()) != 0) { - cerr << "error"; - } - } - return 1; -} - -int Cmds::exitExecute(const vector*, CommandExecutor*){ - std::exit(EXIT_SUCCESS); -} - -int Cmds::helpExecute(const vector*, CommandExecutor*){ - cout << " info" << endl; - return 1; -} - diff --git a/snippet/cmds.h b/snippet/cmds.h deleted file mode 100644 index 04b5cbe..0000000 --- a/snippet/cmds.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef CMDS_H -#define CMDS_H -#include "../msh-console-library/commandexecutor.h" -#include -#include -#include -#include -using std::string; -using std::vector; - -namespace Cmds { - int cdExecute(const vector* args, CommandExecutor*); - int exitExecute(const vector*, CommandExecutor*); - int helpExecute(const vector*, CommandExecutor*); -} - -#endif // CMDS_H diff --git a/snippet/main.cpp b/snippet/main.cpp deleted file mode 100644 index 22879ce..0000000 --- a/snippet/main.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/** - Little snippet for library use. -*/ - -#include -#include -#include "../msh-console-library/shell.h" -#include "../msh-console-library/command.h" -#include "cmds.h" -using namespace std; -using namespace Cmds; - -static void setup(Shell *); - -int main(int argc, char **argv) -{ - string c = "msh-console-test"; - string ps = "[msh-console-test]:"; - Shell mshConsoleTest(c, ps, &setup); - - //add builtin commands - mshConsoleTest.addCmd(new Command("cd", &cdExecute)); - mshConsoleTest.addCmd(new Command("exit", &exitExecute)); - mshConsoleTest.addCmd(new Command("help", &helpExecute)); - mshConsoleTest.launch(); - return EXIT_SUCCESS; -} - -void setup(Shell *s){ - cout << "Now entering in test shell...\n" << endl; - s->executeCmd("stty -ctlecho"); -}