#include "shell.h" namespace mshconsole { string Shell::getPs() const { return ps; } void Shell::setPs(const string &value) { ps = value; } string Shell::getName() const { return name; } void Shell::setName(const string &value) { name = value; } Shell::Shell( string n, string ps,void (*s)(Shell*), void (*pss)(Shell*)) : cmds(this) { shellSetup = s; name = n; this->ps = ps; shellPostSetup = pss; notLoop = false; } int Shell::launch(){ //launch setup if(notLoop) { return -1; } if(shellSetup!=0) { notLoop = true; (*shellSetup)(this); notLoop = false; } //launch loop string* line; struct Params p; int exitCode; try{ do { bool readSuccess; do{ cout << ps << " "; try{ line = read_line(); readSuccess = true; } catch (IsUndoingLineException){ cout << "\n"; readSuccess = false; } }while(!readSuccess); p = split_line(line); executeCmd(p); } while (1); } catch(CommandExecutor::ExitException c) { exitCode=c.getCode(); } //launch postSetup if(shellPostSetup!=0) { shellPostSetup(this); } return exitCode; } int Shell::launchCmd(const struct Params& p) { using std::exit; int status; pid_t pid = fork(); if (pid == 0) { //child process //execute threadCommand int a; try { a=cmds.launch(p, true); } catch (CommandNotFoundException){ //execute bash command or program if((a=execvp(p.argv[0], p.argv)) == -1) { cerr << name <<": command " << p.argv[0] << " not found\n"; } exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } else if (pid < 0) { // Error forking 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::executeCmd(const struct Params& p) { if (!p.argc) { //empty line return 1; } int ret; try { ret = cmds.launch(p, false); } catch(CommandNotFoundException) { ret = launchCmd(p); } return ret; } inline int Shell::executeCmd(const std::string &args){ return executeCmd(split_line(&args)); } void Shell::EofHandler(int){ undoingLine = true; } void Shell::setShellSetup(void (*s)(Shell *)){ shellSetup=s; } void (*Shell::getShellSetup())(Shell*) { return shellSetup; } void Shell::setShellPostSetup(void (*s)(Shell *)){ shellPostSetup=s; } void (*Shell::getShellPostSetup())(Shell*) { return shellPostSetup; } void setEofHandler(void (*funcptr)(int)){ struct sigaction *sa = new struct sigaction(); sa->sa_handler = funcptr; sa->sa_flags = 0; // not SA_RESTART!; sigaction(SIGINT, sa, NULL); delete sa; } string* Shell::read_line() { string* buffer = new string(); setEofHandler(EofHandler); getline(cin,*buffer); // get command cin.clear(); // clear flags if(undoingLine){ undoingLine=false; throw IsUndoingLineException(); } return buffer; } struct Params Shell::split_line(const string* line){ struct Params p; stringToArgcArgv(*line, &(p.argc), &(p.argv)); return p; } bool Shell::undoingLine = false; void Shell::addCmd(Command* cmd, bool isthread){ cmds.add(cmd, isthread); } size_t Shell::howManyCmds() const{ return cmds.howMany(); } }