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:
parent
e9e95a519d
commit
13db9109d9
10 changed files with 127 additions and 74 deletions
6
Msh.pro
6
Msh.pro
|
@ -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
|
||||||
|
|
9
cmds.cpp
9
cmds.cpp
|
@ -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
8
cmds.h
|
@ -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
|
||||||
|
|
|
@ -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(){
|
||||||
|
|
|
@ -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
6
commandexecutor.cpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "commandexecutor.h"
|
||||||
|
|
||||||
|
CommandExecutor::CommandExecutor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
15
commandexecutor.h
Normal file
15
commandexecutor.h
Normal 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
|
18
commands.cpp
18
commands.cpp
|
@ -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();
|
||||||
|
|
50
shell.cpp
50
shell.cpp
|
@ -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
40
shell.h
|
@ -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{};
|
||||||
|
|
Loading…
Reference in a new issue