#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*), void (*pss)(Shell*)) : cmds(this) { shellSetup = s; name = n; this->ps = ps; shellPostSetup = pss; 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 = executeCmd(args); delete args; } while (status); if(shellPostSetup!=0) { shellPostSetup(this); } } int Shell::launchCmd(vector* args) { int status; pid_t pid = fork(); if (pid == 0) { //child process //execute threadCommand int a; try { a=cmds.launch(args, true); } catch (CommandNotFoundException){ //execute bash command or program 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((a=execvp(argv[0], argv.data())) == -1) { cerr << name <<": command " << args->operator [](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(vector* args) { if (args->operator [](0) == "\0") { // An empty command was entered. return 1; } int ret; try { ret = cmds.launch(args, false); } catch(CommandNotFoundException) { ret = launchCmd(args); } 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; } vector* Shell::split_line(const 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, bool isthread){ cmds.add(cmd, isthread); } size_t Shell::howManyCmds() const{ return cmds.howMany(); }