@@ -30,6 +30,7 @@
#include <iostream>
#include <vector>
#include <string>
#include <stack>

//fork, execvp, wait, stat
#include <unistd.h>
@@ -45,7 +46,9 @@ using namespace std;
//Global Variables
const unsigned buffSize = BUFSIZ;

//rshell prompt


//----------------------------------------------------------------------------------------------------------rshell prompt
void initializeUser()
{
char* user = getlogin();
@@ -67,162 +70,240 @@ void initializeUser()
}
}

//rshell
bool rshell(vector<string>& set);
//test
bool test(const vector<string>& shadow);

int main()
//---------------------------------------------------------------------------------------------------------function for calling children to action
bool rshell(vector<string>& set)
{
//rshell

//fork
while(1)
{
string command;


//rshell prompt
initializeUser();

//retrieve line
getline(cin, command);

char instruct[512];

// Load command into instruct
for(int i = 0; i < static_cast<int>(command.size()); i++)
{
instruct[i] = command.at(i);
}

//NULL
instruct[command.size()] = '\0';

//first Initalization
vector<string> cmds;
//comment container
vector<string> comment;

char* token = strtok((char*)instruct, " ");

//Push main comment
if(token != '\0')
while(!set.empty())
{
if(set.at(0) == "exit")
{
comment.push_back(token);
exit(0);
}


//Insert arguments / cmds / connectors
while(token != NULL)


//Pid / Fork
pid_t pid = fork();
if(pid == -1)
{
token = strtok(NULL, " ");

//NULL Guard
if(token == NULL)
{
break;
}

comment.push_back(token);
perror("fork");
}

//Filter cmds: look for '#', ';'
for(int i = 0; i < comment.size(); i++)

//Child
if(pid == 0)
{
if(comment.at(i).at(0) == '#' || comment.at(i).at(0) == '\t')
{
break;
}
//Filter ';'
else if(comment.at(i).find(';') != string::npos)
{
int s_index = 0;
for(int j = 0; j < comment.at(i).size(); j++)
{

if(comment.at(i).find(';', j) != string::npos)
{
j = comment.at(i).find(';', j);
//Found/Parse/Push
string breaker = comment.at(i).substr(s_index, j - s_index);
string semi = comment.at(i).substr(j, 1);
s_index = (j + 1);
cmds.push_back(breaker);
cmds.push_back(semi);
}
else
{
string breaker = comment.at(i).substr(j, comment.at(i).size() - j);
//cout << "Breaker: " << breaker << endl;
cmds.push_back(breaker);
break;
}
//cout << "currently: " << j << endl;
}
}
else
{
cmds.push_back(comment.at(i));
}

//Convert in char* in order to call execvp
char* cmd_exe[512];
//Load cmd_exe
for(int i = 0; i < static_cast<int>(set.size()); i++)
{
cmd_exe[i] = (char*)set.at(i).c_str();
}

//Set NULL ending the command
cmd_exe[set.size()] = NULL;

//call execvp
if(execvp (cmd_exe[0], cmd_exe) == -1)
{
perror("exec");

exit(-1);
}

}


//Parent
if(pid > 0)
{
int status;

//Wait
waitpid(0, &status, 0);

//Error
if(status > 0)
{
return false;
}

return true;
}

set.clear();
}
return true;
}

//------------------------------------------------------------------------------------------------------------Test function

bool test(const vector<string>& shadow)
{
//Initialize struct
struct stat attributes;


//Check size of vector: base (1) and (2)
if(shadow.size() == 1)
{
return false;
}
else if(shadow.size() == 2)
{
return true;
}
//Assume the entire set is passed in; structure: test -flags /path/filename
// Ignore item 1, check flags

unsigned int index = 1;
bool reg = false;
bool dir = false;
bool key = false;


//While prefix has '-', look for specified flags.
while(index < shadow.size() && shadow.at(index).at(0) == '-')
{
//Base case: size != means too many flags, cout error.
if(shadow.at(index).size() != 2)
{
cout << "-Rshell: test: " << shadow.at(index) << ": unary operator expected" << endl;
return false;
}


//DEBUGGING PURPOSES: UNCOMMENT TO SEE ALL THE PARSED COMMENTS
cout << "-------------CMDS HAS---------------------" << endl;
for(int i = 0; i < cmds.size(); i++)
if(shadow.at(index).at(1) == 'e' && key == false)
{
key = true;
}
else if(shadow.at(index).at(1) == 'f' && key == false)
{
reg = true;
key = true;
}
else if(shadow.at(index).at(1) == 'd' && key == false)
{
dir = true;
key = true;
}
else
{
cout << "-Rshell: test: too many arguments" << endl;
return false;
}
index++;
}

//Next index is the specified name, if detect 'preceding \', then delete.
string name;
if(index < shadow.size())
{
if(shadow.at(index).at(0) == '/')
{
cout << cmds.at(i) << endl;
name = shadow.at(index).substr(1);
}

cout << "------------------------------------------" << endl;
//Check if cmds is empty
if(!cmds.empty())
else
{
while (cmds.at(cmds.size() - 1) == "&&" || cmds.at(cmds.size() - 1) == "||")
{
cout << "> ";

inputcont;
}
name = shadow.at(index);
}
//By now all are parsed by space

//boolean for determining successive operations
}

if(name == "")
{
return true;
}

cout << "name: " << name << endl;
// Pass struct memory as pointer on stat()
stat((char*)name.c_str(),&attributes);

//Perform checks
if(!access((char*)name.c_str(), F_OK))
{
if(reg)
{
if(S_ISREG(attributes.st_mode))
{
return true;
}
else
{
return false;
}
}

if(dir)
{
if(S_ISDIR(attributes.st_mode))
{
return true;
}
else
{
return false;
}
}
return true;
}

//This gives the error message "no such file or directory"
perror("rshell: ");
return false;
}

//=========================================================================================================================== Recursive Call

bool functionality (vector<string> cmds, unsigned &j) {

//boolean for determining successive operations
bool status = true;

//actual child-progress command storage
vector<string> set;
int j = 0;

if (cmds.at(j) == "(") {
j += 1;
status = functionality(cmds, j);
}

if(j >= cmds.size()) return status;

//Base case command
for(; j < static_cast<int>(cmds.size()); ++j) {

if ((cmds.at(j) != "||") &&
(cmds.at(j) != "&&") &&
(cmds.at(j) != ";") &&
(cmds.at(j) != "#") )
{
set.push_back(cmds.at(j));
}
else
{
break;
}
if ((j != 0 && cmds.at(j - 1) != ")") || j == 0) {
for(; j < cmds.size(); ++j) {



if ((cmds.at(j) != "||") &&
(cmds.at(j) != "&&") &&
(cmds.at(j) != ";") &&
(cmds.at(j) != "#") &&
(cmds.at(j) != ")") )
{
set.push_back(cmds.at(j));
}
else
{
break;
}
}
}
//DEBUGGING PURPOSES: UNCOMMENT TO SEE ALL THE PARSED COMMENTS
cout << "-------------SET HAS (1)------------------" << endl;
for(int i = 0; i < set.size(); i++)
{
cout << set.at(i) << endl;
}
// cout << "-------------SET HAS (1)------------------" << endl;
// for(unsigned int i = 0; i < set.size(); i++)
// {
// cout << set.at(i) << endl;
// }

cout << "------------------------------------------" << endl;
// cout << "------------------------------------------" << endl;

if(set.at(0) == "test")
if(!set.empty() && set.at(0) == "test")
{
cout << "Calling function bool test();" << endl;
if(test(set))

status = test(set);

if(status)
{
cout << "(True)" << endl;
}
@@ -241,7 +322,18 @@ int main()
//loading in successive commands after base case
for(int i = j; i < static_cast<int>(cmds.size()); i++)
{
if (cmds.at(j) == "(") {
j += 1;
status = functionality(cmds, j);
i = (int)j;
}

if(j >= cmds.size()) return status;

if (cmds.at(i) == ")") {
j = i + 1;
return status;
}
set.push_back(cmds.at(i));

if (set.size() > 1 && (cmds.at(i) == "||" ||
@@ -255,6 +347,7 @@ int main()
set.pop_back();
popfront();

//Either call rshell or test
status = rshell(set);
set.clear();
}
@@ -264,6 +357,7 @@ int main()
set.pop_back();
popfront();

//Either call rshell or test
if(status == true)
{
status = rshell(set);
@@ -276,6 +370,7 @@ int main()
set.pop_back();
popfront();

//Either call rshell or test
if(status == false)
{
status = rshell(set);
@@ -313,152 +408,205 @@ int main()
}
}

}
return status;

return 0;
}

//function for calling children to action
bool rshell(vector<string>& set)
//=========================================================================================================================== MAIN
//=========================================================================================================================== MAIN

int main()
{
while(!set.empty())
{
if(set.at(0) == "exit")
//rshell

//fork
while(1)
{
string command;


//rshell prompt
initializeUser();

//retrieve line and test incorrect line cases
while (command.empty()) {
cout << "Heilii@Alexina.Server $ ";
getline(cin, command);
bool reset = false;
bool statement = false;
bool statement2 = false;
bool statement3 = false;
// bool statement4 = false;

int parenCheckerO = 0;
int parenCheckerC = 0;

if(!command.empty()) {
for(unsigned parenChecker = 0; parenChecker < command.size(); ++ parenChecker) {
if (command.at(parenChecker) == '(') {++parenCheckerO; statement3 = true;}
for(unsigned stateChecker = parenChecker + 1; stateChecker < command.size(); ++ stateChecker) {
if (command.at(stateChecker) != ' ' && command.at(stateChecker) != ')') statement3 = false;
if (command.at(stateChecker) == ')') break;
}
if (statement3) {reset = true; break;}
if (command.at(parenChecker) == ')') {
++parenCheckerC;
// if( parenChecker + 1 < command.size()) {
// if (command.at(parenChecker + 1) != ';' ||
// command.at(parenChecker + 1) != '#' ||
// command.at(parenChecker + 1) != ')' ||) {
// if( parenChecker + 2 < command.size()) {
// if ((command.at(parenChecker + 1) == '|' && command.at(parenChecker + 2) != '|') ||
// (command.at(parenChecker + 1) == '&' && command.at(parenChecker + 2) != '&') ) {
// else if (command.at(parenChecker + 2) != ';' ||
// command.at(parenChecker + 2) != '#' ||
// command.at(parenChecker + 2) != ')' ||) {
// if( parenChecker + 3 < command.size()) {
// if ((command.at(parenChecker + 2) == '|' && command.at(parenChecker + 3) != '|') ||
// (command.at(parenChecker + 2) == '&' && command.at(parenChecker + 3) != '&') ){statement4 = true; reset = true;}
// }
// else {statement4 = true; reset = true;}
// }
// }
// }
// else {statement4 = true; reset = true;}
// }
// }
}
}
if (parenCheckerO != parenCheckerC) {reset = true; statement3 = true;}
if (command.at(0) == ' ') reset = true;
if(command.at(0) == ' ') reset = true;
if(command.at(0) == '#') reset = true;
if(command.at(0) == ';') {reset = true; statement = true;}
if(command.size() > 1) {
if(command.at(0) == '|' && command.at(1) == '|') {reset = true; statement2 = true;}
if(command.at(0) == '&' && command.at(1) == '&') {reset = true; statement2 = true;}
}
}
if(statement) cout << "bash: syntax error near unexpected token `;\'" << endl;
else if(statement2) cout << "bash: syntax error near unexpected token `" << command.at(0) << command.at(1) << "\'" << endl;
else if(statement3) cout << "bash: syntax error near unexpected token `)\'" << endl;
// else if(statement4) cout << "bash: syntax error after token `)\'" << endl;
if(reset) command.clear();
}

char instruct[512];

// Load command into instruct
for(int i = 0; i < static_cast<int>(command.size()); i++)
{
instruct[i] = command.at(i);
}

//NULL
instruct[command.size()] = '\0';

//first Initalization
vector<string> cmds;
//comment container
vector<string> comment;

char* token = strtok((char*)instruct, " ");

//Push main comment
if(token != '\0')
{
exit(0);
comment.push_back(token);
}


//Pid / Fork
pid_t pid = fork();
if(pid == -1)


//Insert arguments / cmds / connectors
while(token != NULL)
{
perror("fork");
token = strtok(NULL, " ");

//NULL Guard
if(token == NULL)
{
break;
}

comment.push_back(token);
}


//DEBUGGING PURPOSES: UNCOMMENT TO SEE ALL THE PARSED COMMENTS
// cout << "-------------CommentS HAS---------------------" << endl;
// for(unsigned int i = 0; i < comment.size(); i++)
// {
// cout << comment.at(i) << endl;
// }


//Child
if(pid == 0)
// cout << "------------------------------------------" << endl;

//Filter cmds: look for '#', ';', "||", "&&"
for(unsigned int i = 0; i < comment.size(); i++)
{

//Convert in char* in order to call execvp
char* cmd_exe[512];
//Load cmd_exe
for(int i = 0; i < static_cast<int>(set.size()); i++)
{
cmd_exe[i] = (char*)set.at(i).c_str();
}

//Set NULL ending the command
cmd_exe[set.size()] = NULL;

//call execvp
if(execvp (cmd_exe[0], cmd_exe) == -1)
{
perror("exec");

exit(-1);
}

if(comment.at(i).at(0) == '#' || comment.at(i).at(0) == '\t')
{
break;
}
//Filter ';'
else if(comment.at(i).find(';') != string::npos && comment.at(i).size() != 1)
{
cout << "What is my comment: " << comment.at(i) << endl;
int s_index = 0;
for(unsigned int j = 0; j < comment.at(i).size(); j++)
{

if(comment.at(i).find(';', j) != string::npos)
{
j = comment.at(i).find(';', j);
//Found/Parse/Push
string breaker = comment.at(i).substr(s_index, j - s_index);
string semi = comment.at(i).substr(j, 1);
s_index = (j + 1);
if (breaker != "") cmds.push_back(breaker);
cmds.push_back(semi);
}
else
{
string breaker = comment.at(i).substr(j, comment.at(i).size() - j);
//cout << "Breaker: " << breaker << endl;
cmds.push_back(breaker);
break;
}
//cout << "currently: " << j << endl;
}
}
else
{
cmds.push_back(comment.at(i));
}
}


//Parent
if(pid > 0)
{
int status;

//Wait
waitpid(0, &status, 0);

//Error
if(status > 0)
{
return false;
}

return true;
}

set.clear();
}
return true;
}


//DEBUGGING PURPOSES: UNCOMMENT TO SEE ALL THE PARSED COMMENTS
// cout << "-------------CMDS HAS---------------------" << endl;
// for(unsigned int i = 0; i < cmds.size(); i++)
// {
// cout << cmds.at(i) << endl;
// }

// cout << "------------------------------------------" << endl;
//Check if cmds is empty
if(!cmds.empty())
{
while (cmds.at(cmds.size() - 1) == "&&" || cmds.at(cmds.size() - 1) == "||")
{
cout << "> ";

inputcont;
}
}
//By now all are parsed by space

unsigned starter = 0;
functionality(cmds, starter);

}

//Test function
return 0;
}

bool test(const vector<string>& shadow)
{

//Initialize struct
struct stat attributes;

//Assume the entire set is passed in; structure: test -flags /path/filename
// Ignore item 1, check flags

int index = 1;
bool reg = false;
bool dir = false;
while(shadow.at(index) == "-e" || shadow.at(index) == "-f" || shadow.at(index) == "-d")
{
//We can ignore -e due to its default; we are always checking if it exists.
if(shadow.at(index) == "-f")
{
reg = true;
}
if(shadow.at(index) == "-d")
{
dir = true;
}
index++;
}


//Next index is the specified name, if detect 'preceding \', then delete.
string name;
if(shadow.at(index).at(0) == '/')
{
cout << "found one" << endl;
name = shadow.at(index).substr(1);
}
else
{
name = shadow.at(index);
}
cout << "name: " << name << endl;

// Pass struct memory as pointer on stat()
stat((char*)name.c_str(),&attributes);

//Perform checks
if(!access((char*)name.c_str(), F_OK))
{
if(reg)
{
cout << "-f: ";
if(S_ISREG(attributes.st_mode))
{
cout << "I AM REGULAR FILE" << endl;
}
else
{
cout << "NOPE IM NOT REGULAR" << endl;
}
}

if(dir)
{
cout << "-d: ";
if(S_ISDIR(attributes.st_mode))
{
cout << "I AM DIRECTORY" << endl;
}
else
{
cout << "NOPE IM NOT DIR" << endl;
}
}
return true;
}
return false;
}