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 \
commands.cpp \
cmds.cpp \
shell.cpp
shell.cpp \
commandexecutor.cpp
HEADERS += \
command.h \
shell.h \
cmds.h
cmds.h \
commandexecutor.h

View File

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

8
cmds.h
View File

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

View File

@ -1,12 +1,13 @@
#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();
numCom++;
}
int Command::execute(const vector<string>* args){
return (*funcCommand)(args);
int Command::execute(const vector<string>* args, CommandExecutor* ciao){
if(args==nullptr) return -1;
return (*funcCommand)(args, ciao);
}
string Command::getName(){

View File

@ -2,6 +2,8 @@
#define COMMAND_H
#include <string>
#include <vector>
#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<string>*);
int (*funcCommand)(const vector<string>*,CommandExecutor*);
void checkObj();
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();
string getName();
int execute(const vector<string>*);
int execute(const vector<string>*, CommandExecutor* ciao);
};
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"
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<string>* args){
for(unsigned int i=0; i<commands.size(); i++){
if((commands[i]->getName())==args->operator [](0)){
return commands[i]->execute(args);
int Shell::Commands::launch(const vector<string>* 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();

View File

@ -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<string>* args)
int Shell::launchCmd(vector<string>* args)
{
pid_t pid;
int status;
pid = fork();
pid_t pid = fork();
if (pid == 0) {
vector<char *> 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<char *> 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<string>* args)
int Shell::executeCmd(vector<string>* 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<string>* Shell::split_line(string* line)
vector<string>* Shell::split_line(const string* line)
{
vector<string>* tokens = new vector<string>();
string ln = *line;
@ -150,10 +166,10 @@ vector<string>* 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();
}

40
shell.h
View File

@ -10,6 +10,8 @@
#include <vector>
#include <csignal>
#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<Command*> commands;
static bool created;
Commands(Commands&);
public:
Commands();
void add(Command*);
size_t howMany();
int launch(const vector<string>* args);
};
Shell* parent;
vector<Command*> commands; //commands that work the same thread of the shell
vector<Command*> 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<string>* 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<string>* args);
int execute(vector<string>* args);
int launchCmd(vector<string>* args);
static void EofHandler(int);
string* read_line();
vector<string>* split_line(string* line);
vector<string>* 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<string>* args);
int executeCmd(const string& args);
//exceptions
class CommandsAlreadyCreatedException{};