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).

This commit is contained in:
Claudio Maggioni 2016-03-13 17:16:34 +01:00
parent e9e95a519d
commit 13db9109d9
10 changed files with 127 additions and 74 deletions

View file

@ -7,9 +7,11 @@ SOURCES += main.cpp \
command.cpp \ command.cpp \
commands.cpp \ commands.cpp \
cmds.cpp \ cmds.cpp \
shell.cpp shell.cpp \
commandexecutor.cpp
HEADERS += \ HEADERS += \
command.h \ command.h \
shell.h \ shell.h \
cmds.h cmds.h \
commandexecutor.h

View file

@ -3,9 +3,10 @@
*/ */
#include "cmds.h" #include "cmds.h"
using namespace std; using namespace std;
int Cmds::cdExecute(const vector<string>* args){ int Cmds::cdExecute(const vector<string>* args, CommandExecutor*){
if (args->operator[](1) == "\0") { if (args->operator[](1) == "\0") {
cerr << "expected argument to \"cd\"\n"; cerr << "expected argument to \"cd\"\n";
} else { } else {
@ -16,11 +17,11 @@ int Cmds::cdExecute(const vector<string>* args){
return 1; return 1;
} }
int Cmds::exitExecute(const vector<string>*){ int Cmds::exitExecute(const vector<string>*, CommandExecutor*){
return 0; return 0; //TODO: better exit signal giving
} }
int Cmds::helpExecute(const vector<string>*){ int Cmds::helpExecute(const vector<string>*, CommandExecutor*){
cout << " info" << endl; cout << " info" << endl;
return 1; return 1;
} }

8
cmds.h
View file

@ -1,6 +1,6 @@
#ifndef CMDS_H #ifndef CMDS_H
#define CMDS_H #define CMDS_H
#include "commandexecutor.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
@ -9,9 +9,9 @@ using std::string;
using std::vector; using std::vector;
namespace Cmds { namespace Cmds {
int cdExecute(const vector<string>* args); int cdExecute(const vector<string>* args, CommandExecutor*);
int exitExecute(const vector<string>*); int exitExecute(const vector<string>*, CommandExecutor*);
int helpExecute(const vector<string>*); int helpExecute(const vector<string>*, CommandExecutor*);
} }
#endif // CMDS_H #endif // CMDS_H

View file

@ -1,12 +1,13 @@
#include "shell.h" #include "shell.h"
Command::Command(const string& n, int (*funcptr)(const vector<string>* args)) : name(n) , funcCommand(funcptr){ Command::Command(const string& n, int (*funcptr)(const vector<string>* args, CommandExecutor*)) : name(n) , funcCommand(funcptr){
checkObj(); checkObj();
numCom++; numCom++;
} }
int Command::execute(const vector<string>* args){ int Command::execute(const vector<string>* args, CommandExecutor* ciao){
return (*funcCommand)(args); if(args==nullptr) return -1;
return (*funcCommand)(args, ciao);
} }
string Command::getName(){ string Command::getName(){

View file

@ -2,6 +2,8 @@
#define COMMAND_H #define COMMAND_H
#include <string> #include <string>
#include <vector> #include <vector>
#include "shell.h"
#include "commandexecutor.h"
using std::string; using std::string;
using std::vector; using std::vector;
@ -10,15 +12,15 @@ class Command
{ {
const string name; const string name;
static unsigned int numCom; static unsigned int numCom;
int (*funcCommand)(const vector<string>*); int (*funcCommand)(const vector<string>*,CommandExecutor*);
void checkObj(); void checkObj();
public: public:
Command(const string& n, int (*funcptr)(const vector<string>* args)); Command(const string& n, int (*funcptr)(const vector<string>* args, CommandExecutor*));
Command(const Command&); Command(const Command&);
~Command(); ~Command();
string getName(); string getName();
int execute(const vector<string>*); int execute(const vector<string>*, CommandExecutor* ciao);
}; };
class CommandNameNotValidException{}; class CommandNameNotValidException{};

6
commandexecutor.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "commandexecutor.h"
CommandExecutor::CommandExecutor()
{
}

15
commandexecutor.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef COMMANDEXECUTOR_H
#define COMMANDEXECUTOR_H
#include <vector>
#include <string>
class CommandExecutor
{
public:
virtual int executeCmd(std::vector<std::string>* args) = 0;
virtual int executeCmd(const std::string& args) = 0;
virtual size_t howManyCmds() const = 0;
CommandExecutor();
};
#endif // COMMANDEXECUTOR_H

View file

@ -1,23 +1,25 @@
#include "shell.h" #include "shell.h"
Shell::Commands::Commands() Shell::Commands::Commands(Shell* s) : commands(), threadCommands()
{ {
parent = s;
if(created) throw CommandsAlreadyCreatedException(); if(created) throw CommandsAlreadyCreatedException();
created=true; created=true;
} }
void Shell::Commands::add(Command* cmd){ void Shell::Commands::add(Command* cmd, bool isthread){
commands.push_back(cmd); 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(); return commands.size();
} }
int Shell::Commands::launch(const vector<string>* args){ int Shell::Commands::launch(const vector<string>* args, bool launchThread){
for(unsigned int i=0; i<commands.size(); i++){ for(unsigned int i=0; i<(launchThread ? threadCommands.size() : commands.size()); i++){
if((commands[i]->getName())==args->operator [](0)){ if((launchThread ? threadCommands[i]->getName() : commands[i]->getName())==args->operator [](0)){
return commands[i]->execute(args); return (launchThread ? threadCommands[i]->execute(args, parent) : commands[i]->execute(args, parent));
} }
} }
throw CommandNotFoundException(); throw CommandNotFoundException();

View file

@ -20,7 +20,7 @@ void Shell::setName(const string &value)
name = 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; shellSetup = s;
name = n; name = n;
@ -57,17 +57,26 @@ void Shell::launch(){
} }
}while(!readSuccess); }while(!readSuccess);
args = split_line(line); args = split_line(line);
status = execute(args); status = executeCmd(args);
delete args;
} while (status); } while (status);
} }
int Shell::launch(vector<string>* args) int Shell::launchCmd(vector<string>* args)
{ {
pid_t pid;
int status; int status;
pid = fork(); pid_t pid = fork();
if (pid == 0) { if (pid == 0) {
//child process
//execute threadCommand
int a;
try {
a=cmds.launch(args, true);
}
catch (CommandNotFoundException){
//execute bash command or program
vector<char *> argv(args->size() + 1); vector<char *> argv(args->size() + 1);
size_t i; size_t i;
for (i = 0; i != args->size()-1; ++i) for (i = 0; i != args->size()-1; ++i)
@ -75,38 +84,45 @@ int Shell::launch(vector<string>* args)
argv[i] = &(args->operator[](i)[0]); argv[i] = &(args->operator[](i)[0]);
} }
argv[i] = NULL; argv[i] = NULL;
if(execvp(argv[0], argv.data()) == -1) { if((a=execvp(argv[0], argv.data())) == -1) {
cerr << name <<": command " << args->operator [](0) << " not found\n"; cerr << name <<": command " << args->operator [](0) << " not found\n";
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
exit(EXIT_SUCCESS);
}
else if (pid < 0) { else if (pid < 0) {
// Error forking // Error forking
cerr << name <<": error forking\n"; cerr << name <<": error forking the process\n";
} }
else { else {
// Parent process // Parent process
do { do {
//wait until child finished
waitpid(pid, &status, WUNTRACED); waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); } while (!WIFEXITED(status) && !WIFSIGNALED(status));
} }
return 1; return 1;
} }
int Shell::execute(vector<string>* args) int Shell::executeCmd(vector<string>* args)
{ {
if (args->operator [](0) == "\0") { if (args->operator [](0) == "\0") {
// An empty command was entered. // An empty command was entered.
return 1; return 1;
} }
int a; int ret;
try { try {
a=cmds.launch(args); ret = cmds.launch(args, false);
} }
catch (CommandNotFoundException){ catch(CommandNotFoundException) {
return launch(args); ret = launchCmd(args);
} }
return a; return ret;
}
inline int Shell::executeCmd(const std::string &args){
return executeCmd(split_line(&args));
} }
void Shell::EofHandler(int){ void Shell::EofHandler(int){
@ -135,7 +151,7 @@ string* Shell::read_line()
return buffer; return buffer;
} }
vector<string>* Shell::split_line(string* line) vector<string>* Shell::split_line(const string* line)
{ {
vector<string>* tokens = new vector<string>(); vector<string>* tokens = new vector<string>();
string ln = *line; string ln = *line;
@ -150,10 +166,10 @@ vector<string>* Shell::split_line(string* line)
bool Shell::undoingLine = false; bool Shell::undoingLine = false;
void Shell::addCmd(Command* cmd){ void Shell::addCmd(Command* cmd, bool isthread){
cmds.add(cmd); cmds.add(cmd, isthread);
} }
size_t Shell::howManyCmds(){ size_t Shell::howManyCmds() const{
return cmds.howMany(); return cmds.howMany();
} }

40
shell.h
View file

@ -10,6 +10,8 @@
#include <vector> #include <vector>
#include <csignal> #include <csignal>
#include "command.h" #include "command.h"
//#include "commands.h"
#include "commandexecutor.h"
using std::string; using std::string;
using std::cin; using std::cin;
using std::cout; using std::cout;
@ -19,20 +21,25 @@ using std::vector;
using std::istringstream; using std::istringstream;
using std::nullptr_t; using std::nullptr_t;
class Shell class Shell : public CommandExecutor
{ {
class Commands class Commands
{ {
vector<Command*> commands; Shell* parent;
static bool created; vector<Command*> commands; //commands that work the same thread of the shell
Commands(Commands&); vector<Command*> threadCommands; //commands that work on a different thread
public:
Commands();
void add(Command*);
size_t howMany();
int launch(const vector<string>* args);
};
//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<string>* args, bool launchThread=false);
};
static bool undoingLine; static bool undoingLine;
Commands cmds; Commands cmds;
string ps; string ps;
@ -40,16 +47,15 @@ class Shell
void (*shellSetup)(Shell *); void (*shellSetup)(Shell *);
bool notLoop; bool notLoop;
int launch(vector<string>* args); int launchCmd(vector<string>* args);
int execute(vector<string>* args);
static void EofHandler(int); static void EofHandler(int);
string* read_line(); string* read_line();
vector<string>* split_line(string* line); vector<string>* split_line(const string* line);
class IsUndoingLineException {}; class IsUndoingLineException {};
public: 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; string getPs() const;
void setPs(const string &value); void setPs(const string &value);
string getName() const; string getName() const;
@ -57,8 +63,10 @@ public:
void launch(); void launch();
//for in-shell commands //for in-shell commands
void addCmd(Command *cmd); void addCmd(Command *cmd, bool isThread=false);
size_t howManyCmds(); size_t howManyCmds() const;
int executeCmd(vector<string>* args);
int executeCmd(const string& args);
//exceptions //exceptions
class CommandsAlreadyCreatedException{}; class CommandsAlreadyCreatedException{};