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; +} +