msh-console/shell.cpp

175 lines
3.5 KiB
C++

#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(this)
{
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<string>* 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);
}
int Shell::launchCmd(vector<string>* 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<char *> 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<string>* 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 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<string>* Shell::split_line(const string* line)
{
vector<string>* tokens = new vector<string>();
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();
}