From 13db9109d9a48764cd8b7faf19c427bc6bf4cf22 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 13 Mar 2016 17:16:34 +0100 Subject: [PATCH] Command functions have now a CommandExecutor* arg, parent of Shell class. Added possibility to make a threadCommand (a built-in command that runs in his thread). --- Msh.pro | 6 ++-- cmds.cpp | 9 ++--- cmds.h | 8 ++--- command.cpp | 7 ++-- command.h | 8 +++-- commandexecutor.cpp | 6 ++++ commandexecutor.h | 15 ++++++++ commands.cpp | 18 +++++----- shell.cpp | 84 +++++++++++++++++++++++++++------------------ shell.h | 40 ++++++++++++--------- 10 files changed, 127 insertions(+), 74 deletions(-) create mode 100644 commandexecutor.cpp create mode 100644 commandexecutor.h diff --git a/Msh.pro b/Msh.pro index 82fe28e..dcb25ea 100644 --- a/Msh.pro +++ b/Msh.pro @@ -7,9 +7,11 @@ SOURCES += main.cpp \ command.cpp \ commands.cpp \ cmds.cpp \ - shell.cpp + shell.cpp \ + commandexecutor.cpp HEADERS += \ command.h \ shell.h \ - cmds.h + cmds.h \ + commandexecutor.h diff --git a/cmds.cpp b/cmds.cpp index b39d5a5..6ed319e 100644 --- a/cmds.cpp +++ b/cmds.cpp @@ -3,9 +3,10 @@ */ #include "cmds.h" + using namespace std; -int Cmds::cdExecute(const vector* args){ +int Cmds::cdExecute(const vector* args, CommandExecutor*){ if (args->operator[](1) == "\0") { cerr << "expected argument to \"cd\"\n"; } else { @@ -16,11 +17,11 @@ int Cmds::cdExecute(const vector* args){ return 1; } -int Cmds::exitExecute(const vector*){ - return 0; +int Cmds::exitExecute(const vector*, CommandExecutor*){ + return 0; //TODO: better exit signal giving } -int Cmds::helpExecute(const vector*){ +int Cmds::helpExecute(const vector*, CommandExecutor*){ cout << " info" << endl; return 1; } diff --git a/cmds.h b/cmds.h index e0f8925..9b6eec9 100644 --- a/cmds.h +++ b/cmds.h @@ -1,6 +1,6 @@ #ifndef CMDS_H #define CMDS_H - +#include "commandexecutor.h" #include #include #include @@ -9,9 +9,9 @@ using std::string; using std::vector; namespace Cmds { - int cdExecute(const vector* args); - int exitExecute(const vector*); - int helpExecute(const vector*); + int cdExecute(const vector* args, CommandExecutor*); + int exitExecute(const vector*, CommandExecutor*); + int helpExecute(const vector*, CommandExecutor*); } #endif // CMDS_H diff --git a/command.cpp b/command.cpp index 21751cf..93f0b7e 100644 --- a/command.cpp +++ b/command.cpp @@ -1,12 +1,13 @@ #include "shell.h" -Command::Command(const string& n, int (*funcptr)(const vector* args)) : name(n) , funcCommand(funcptr){ +Command::Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)) : name(n) , funcCommand(funcptr){ checkObj(); numCom++; } -int Command::execute(const vector* args){ - return (*funcCommand)(args); +int Command::execute(const vector* args, CommandExecutor* ciao){ + if(args==nullptr) return -1; + return (*funcCommand)(args, ciao); } string Command::getName(){ diff --git a/command.h b/command.h index e4ccb84..ddf56a9 100644 --- a/command.h +++ b/command.h @@ -2,6 +2,8 @@ #define COMMAND_H #include #include +#include "shell.h" +#include "commandexecutor.h" using std::string; using std::vector; @@ -10,15 +12,15 @@ class Command { const string name; static unsigned int numCom; - int (*funcCommand)(const vector*); + int (*funcCommand)(const vector*,CommandExecutor*); void checkObj(); public: - Command(const string& n, int (*funcptr)(const vector* args)); + Command(const string& n, int (*funcptr)(const vector* args, CommandExecutor*)); Command(const Command&); ~Command(); string getName(); - int execute(const vector*); + int execute(const vector*, CommandExecutor* ciao); }; class CommandNameNotValidException{}; diff --git a/commandexecutor.cpp b/commandexecutor.cpp new file mode 100644 index 0000000..978d62f --- /dev/null +++ b/commandexecutor.cpp @@ -0,0 +1,6 @@ +#include "commandexecutor.h" + +CommandExecutor::CommandExecutor() +{ + +} diff --git a/commandexecutor.h b/commandexecutor.h new file mode 100644 index 0000000..5a54499 --- /dev/null +++ b/commandexecutor.h @@ -0,0 +1,15 @@ +#ifndef COMMANDEXECUTOR_H +#define COMMANDEXECUTOR_H +#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(); +}; + +#endif // COMMANDEXECUTOR_H diff --git a/commands.cpp b/commands.cpp index f91d229..b140c3d 100644 --- a/commands.cpp +++ b/commands.cpp @@ -1,23 +1,25 @@ #include "shell.h" -Shell::Commands::Commands() +Shell::Commands::Commands(Shell* s) : commands(), threadCommands() { + parent = s; if(created) throw CommandsAlreadyCreatedException(); created=true; } -void Shell::Commands::add(Command* cmd){ - commands.push_back(cmd); +void Shell::Commands::add(Command* cmd, bool isthread){ + if(!isthread) commands.push_back(cmd); + else threadCommands.push_back(cmd); } -size_t Shell::Commands::howMany(){ +size_t Shell::Commands::howMany() const{ return commands.size(); } -int Shell::Commands::launch(const vector* args){ - for(unsigned int i=0; igetName())==args->operator [](0)){ - return commands[i]->execute(args); +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(); diff --git a/shell.cpp b/shell.cpp index 726aef8..facf731 100644 --- a/shell.cpp +++ b/shell.cpp @@ -20,7 +20,7 @@ void Shell::setName(const string &value) name = value; } -Shell::Shell( string n, string ps,void (*s)(Shell*)) : cmds() +Shell::Shell( string n, string ps,void (*s)(Shell*)) : cmds(this) { shellSetup = s; name = n; @@ -57,56 +57,72 @@ void Shell::launch(){ } }while(!readSuccess); args = split_line(line); - status = execute(args); + status = executeCmd(args); + delete args; } while (status); } -int Shell::launch(vector* args) +int Shell::launchCmd(vector* args) { - pid_t pid; int status; - pid = fork(); + pid_t pid = fork(); if (pid == 0) { - 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(execvp(argv[0], argv.data()) == -1) { - cerr << name <<": command " << args->operator [](0) << " not found\n"; - } - exit(EXIT_FAILURE); + //child process + + //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]); + } + 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_SUCCESS); } else if (pid < 0) { // Error forking - cerr << name <<": error forking\n"; + 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::execute(vector* args) +int Shell::executeCmd(vector* args) { - if (args->operator [](0) == "\0") { - // An empty command was entered. - return 1; - } - int a; - try { - a=cmds.launch(args); - } - catch (CommandNotFoundException){ - return launch(args); - } - return a; + 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; +} + +inline int Shell::executeCmd(const std::string &args){ + return executeCmd(split_line(&args)); } void Shell::EofHandler(int){ @@ -135,7 +151,7 @@ string* Shell::read_line() return buffer; } -vector* Shell::split_line(string* line) +vector* Shell::split_line(const string* line) { vector* tokens = new vector(); string ln = *line; @@ -150,10 +166,10 @@ vector* Shell::split_line(string* line) bool Shell::undoingLine = false; -void Shell::addCmd(Command* cmd){ - cmds.add(cmd); +void Shell::addCmd(Command* cmd, bool isthread){ + cmds.add(cmd, isthread); } -size_t Shell::howManyCmds(){ +size_t Shell::howManyCmds() const{ return cmds.howMany(); } diff --git a/shell.h b/shell.h index 188c6b7..26e57ca 100644 --- a/shell.h +++ b/shell.h @@ -10,6 +10,8 @@ #include #include #include "command.h" +//#include "commands.h" +#include "commandexecutor.h" using std::string; using std::cin; using std::cout; @@ -19,20 +21,25 @@ using std::vector; using std::istringstream; using std::nullptr_t; -class Shell +class Shell : public CommandExecutor { class Commands { - vector commands; - static bool created; - Commands(Commands&); - public: - Commands(); - void add(Command*); - size_t howMany(); - int launch(const vector* args); - }; + Shell* parent; + vector commands; //commands that work the same thread of the shell + vector threadCommands; //commands that work on a different thread + //just one instance of the object + static bool created; + Commands(const Commands&); + Commands operator=(const Commands&); + + 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; @@ -40,16 +47,15 @@ class Shell void (*shellSetup)(Shell *); bool notLoop; - int launch(vector* args); - int execute(vector* args); + int launchCmd(vector* args); static void EofHandler(int); string* read_line(); - vector* split_line(string* line); + vector* split_line(const string* line); class IsUndoingLineException {}; public: - Shell( string n="msh", string ps="MSH$",void (*s)(Shell*)=0); + Shell(string n="msh", string ps="MSH$", void (*s)(Shell*)=0); string getPs() const; void setPs(const string &value); string getName() const; @@ -57,8 +63,10 @@ public: void launch(); //for in-shell commands - void addCmd(Command *cmd); - size_t howManyCmds(); + void addCmd(Command *cmd, bool isThread=false); + size_t howManyCmds() const; + int executeCmd(vector* args); + int executeCmd(const string& args); //exceptions class CommandsAlreadyCreatedException{};