diff --git a/Msh.pro b/Msh.pro
new file mode 100644
index 0000000..fb8889c
--- /dev/null
+++ b/Msh.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG += console c++11
+CONFIG -= app_bundle
+CONFIG -= qt
+
+SOURCES += main.cpp \
+ command.cpp \
+ commands.cpp \
+ cmds.cpp
+
+HEADERS += \
+ command.h \
+ commands.h \
+ cmds.h
diff --git a/Msh.pro.user b/Msh.pro.user
new file mode 100644
index 0000000..a6b5d3c
--- /dev/null
+++ b/Msh.pro.user
@@ -0,0 +1,334 @@
+
+
+
+
+
+ EnvironmentId
+ {1e01437e-8028-453e-a499-fb71332d241a}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ true
+ false
+ 0
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ false
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ {0bde0d2e-5514-426b-bc4a-4b14b35c0599}
+ 0
+ 0
+ 0
+
+ /home/claudio/WorkSpace-C/build-Msh-Desktop-Debug
+
+
+ true
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ false
+ false
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ false
+
+
+
+ 2
+ Build
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ true
+ clean
+
+
+ 1
+ Clean
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Debug
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+ true
+
+
+ /home/claudio/WorkSpace-C/build-Msh-Desktop-Release
+
+
+ true
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ false
+
+ false
+ false
+ false
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ false
+
+
+
+ 2
+ Build
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ true
+ clean
+
+
+ 1
+ Clean
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Release
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ true
+
+
+ /home/claudio/WorkSpace-C/build-Msh-Desktop-Profile
+
+
+ true
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ true
+ false
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ false
+
+
+
+ 2
+ Build
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Make
+
+ Qt4ProjectManager.MakeStep
+
+ -w
+ -r
+
+ true
+ clean
+
+
+ 1
+ Clean
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Profile
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ true
+
+ 3
+
+
+ 0
+ Deploy
+
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+ Deploy locally
+
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+ 2
+
+ Msh
+
+ Qt4ProjectManager.Qt4RunConfiguration:/home/claudio/WorkSpace-C/Msh/Msh.pro
+ true
+
+ Msh.pro
+ false
+ true
+
+ 3768
+ false
+ true
+ false
+ false
+ true
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 18
+
+
+ Version
+ 18
+
+
diff --git a/cmds.cpp b/cmds.cpp
new file mode 100644
index 0000000..57b3937
--- /dev/null
+++ b/cmds.cpp
@@ -0,0 +1,29 @@
+/**
+ builtin commands
+*/
+
+#include "cmds.h"
+using namespace std;
+
+int Cmds::cdExecute(const vector* args){
+ if (args->operator[](1) == "\0") {
+ cerr << "msh: expected argument to \"cd\"\n";
+ } else {
+ if (chdir(args->operator[](1).c_str()) != 0) {
+ cerr << "msh";
+ }
+ }
+ return 1;
+}
+
+int Cmds::exitExecute(const vector*){
+ std::exit(0);
+}
+
+int Cmds::helpExecute(const vector*){
+ int i;
+ cout << "Claudio Maggioni's msh\n" << endl
+ << "Type program names and arguments, and hit enter.\n" << endl;
+ return 1;
+}
+
diff --git a/cmds.h b/cmds.h
new file mode 100644
index 0000000..f170d82
--- /dev/null
+++ b/cmds.h
@@ -0,0 +1,20 @@
+/**
+ builtin commands
+*/
+
+#ifndef CMDS_H
+#define CMDS_H
+#include
+#include
+#include
+#include
+using std::string;
+using std::vector;
+
+namespace Cmds {
+ int cdExecute(const vector* args);
+ int exitExecute(const vector*);
+ int helpExecute(const vector*);
+}
+
+#endif // CMDS_H
diff --git a/command.cpp b/command.cpp
new file mode 100644
index 0000000..f3f66b1
--- /dev/null
+++ b/command.cpp
@@ -0,0 +1,33 @@
+#include "command.h"
+
+Command::Command(const string& n, int (*funcptr)(const vector* args)) : name(n) , funcCommand(funcptr){
+ checkObj();
+ numCom++;
+}
+
+int Command::execute(const vector* args){
+ return (*funcCommand)(args);
+}
+
+string Command::getName(){
+ return this->name;
+}
+
+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();
+ }
+ }
+}
+
+Command::~Command(){
+ numCom--;
+}
+
+unsigned int Command::numCom = 0;
diff --git a/command.h b/command.h
new file mode 100644
index 0000000..16735a3
--- /dev/null
+++ b/command.h
@@ -0,0 +1,24 @@
+#ifndef COMMAND_H
+#define COMMAND_H
+#include
+#include
+using std::string;
+using std::vector;
+
+class Command
+{
+ const string name;
+ static unsigned int numCom;
+ int (*funcCommand)(const vector*);
+ void checkObj();
+public:
+ Command(const string& n, int (*funcptr)(const vector* args));
+ Command(const Command&);
+ ~Command();
+ int execute(const vector*);
+ string getName();
+};
+
+class CommandNameNotValidException{};
+
+#endif // COMMAND_H
diff --git a/commands.cpp b/commands.cpp
new file mode 100644
index 0000000..d16293c
--- /dev/null
+++ b/commands.cpp
@@ -0,0 +1,36 @@
+#include "commands.h"
+
+using namespace Cmds;
+
+Commands::Commands()
+{
+ if(created) throw CommandsAlreadyCreatedException();
+ created=true;
+
+ //add builtin commands
+ add(new Command("cd", &cdExecute));
+ add(new Command("exit", &exitExecute));
+ add(new Command("help", &helpExecute));
+}
+
+void Commands::add(Command* cmd){
+ commands.push_back(cmd);
+}
+
+int Commands::howMany(){
+ return commands.size();
+}
+
+int Commands::launch(const vector* args){
+ for(int i=0; igetName())==args->operator [](0)){
+ return commands[i]->execute(args);
+ }
+ }
+ throw CommandNotFoundException();
+}
+
+bool Commands::created = false;
+
+//builtin commands
+
diff --git a/commands.h b/commands.h
new file mode 100644
index 0000000..15ed0d0
--- /dev/null
+++ b/commands.h
@@ -0,0 +1,25 @@
+#ifndef COMMANDS_H
+#define COMMANDS_H
+#include
+#include
+#include
+#include "cmds.h"
+using std::string;
+using std::vector;
+
+class Commands
+{
+ vector commands;
+ static bool created;
+ Commands(Commands&);
+public:
+ Commands();
+ void add(Command*);
+ int howMany();
+ int launch(const vector* args);
+};
+
+class CommandsAlreadyCreatedException{};
+class CommandNotFoundException{};
+
+#endif // COMMANDS_H
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..3766267
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,147 @@
+/**
+ * Edit of lsh from https://github.com/brenns10/msh.git rewritten in C++
+ * by Claudio Maggiobi
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+using namespace std;
+
+Commands cmds;
+
+int msh_launch(vector* args)
+{
+ pid_t pid;
+ int status;
+
+ 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 << "msh: command " << args->operator [](0) << " not found\n";
+ }
+ exit(EXIT_FAILURE);
+ }
+ else if (pid < 0) {
+ // Error forking
+ cerr << "msh: error forking\n";
+ }
+ else {
+ // Parent process
+
+ do {
+ waitpid(pid, &status, WUNTRACED);
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+ }
+ return 1;
+}
+
+int msh_execute(vector* args)
+{
+ if (args->operator [](0) == "\0") {
+ // An empty command was entered.
+ return 1;
+ }
+ int a;
+ try {
+ a=cmds.launch(args);
+ }
+ catch (CommandNotFoundException){
+ return msh_launch(args);
+ }
+ return a;
+}
+
+class IsUndoingLineException {};
+
+bool undoingLine=false;
+
+void mshEofHandler(int){
+ undoingLine = true;
+}
+
+string* msh_read_line()
+{
+ string* buffer = new string();
+ struct sigaction *sa = new struct sigaction();
+ sa->sa_handler = mshEofHandler;
+ sa->sa_flags = 0; // not SA_RESTART!;
+ sigaction(SIGINT, sa, NULL);
+
+ getline(cin,*buffer); // get command
+ cin.clear(); // clear flags
+
+ if(undoingLine){
+ undoingLine=false;
+ throw IsUndoingLineException();
+ }
+
+ return buffer;
+}
+
+vector* msh_split_line(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;
+}
+
+inline void msh_loop(void)
+{
+ string* line;
+ vector* args;
+ int status;
+
+ do {
+ bool readSuccess;
+ do{
+ cout << "MSH$ ";
+ try{
+ line = msh_read_line();
+ readSuccess = true;
+ }
+ catch (IsUndoingLineException){
+ cout << "\n";
+ readSuccess = false;
+ }
+ }while(!readSuccess);
+ args = msh_split_line(line);
+ status = msh_execute(args);
+
+ } while (status);
+}
+
+int main(int argc, char **argv)
+{
+ // Load config files, if any.
+
+ // Run command loop
+
+ msh_loop();
+
+ // Perform any shutdown/cleanup.
+
+ return EXIT_SUCCESS;
+}
+