#include "shell.h" 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*)) : cmds() { shellSetup = s; name = n; this->ps = ps; notLoop = false; } void Shell::launch(){ //launch setup if(notLoop) { throw ShellLaunchInSetupException(); return; } if(shellSetup!=0) { notLoop = true; (*shellSetup)(this); notLoop = false; } //launch loop string* line; vector* args; int status; do { bool readSuccess; do{ cout << ps << " "; try{ line = read_line(); readSuccess = true; } catch (IsUndoingLineException){ cout << "\n"; readSuccess = false; } }while(!readSuccess); args = split_line(line); status = execute(args); } while (status); } int Shell::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 << name <<": command " << args->operator [](0) << " not found\n"; } exit(EXIT_FAILURE); } else if (pid < 0) { // Error forking cerr << name <<": error forking\n"; } else { // Parent process do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } return 1; } int Shell::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 launch(args); } return a; } void Shell::EofHandler(int){ undoingLine = true; } 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; } vector* Shell::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; } bool Shell::undoingLine = false; void Shell::addCmd(Command* cmd){ cmds.add(cmd); } size_t Shell::howManyCmds(){ return cmds.howMany(); }