<commit_before>//THINGS TO DO:
//

#include <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <boost/tokenizer.hpp>
#include <queue>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

using namespace std;
using namespace boost;

bool runexec(vector<string> argv);	//will use system calls to run the commands provided and returns only 0 when sucessful

bool runio(queue<string> &cmds, queue<string> &connect);

string findconnect(string str);		//outputs a string of every connector

queue<string> findio(string str);			//outputs a string of each io redirection or pipe

queue<char> strtoq(string connect);		//converts the string of connectors to a queue

queue<string> parseline(string str, bool iomode);	//separate commands by connectors from the original string

vector<string> parsecommand(bool &end, string str);

string checkcomment(string str);		//checks and takes out comments on the command line

void printinfo();		//prints the username and machine name before the prompt

bool iomode(string line);

int main(int argc, char** argv) {
	string input;
	bool end = false;
	while(!end) {
		fflush(stdout);
		printinfo();
		cout << "$ ";
		getline(cin, input);
		input = checkcomment(input);
		string constr;			
		queue<string> iosym;
		queue<char> connect;		//connect stores every connector
		queue<string> cmds;

		bool redirect = iomode(input);
		if(redirect) {
			//PARSE BY '>', '<', AND '|' CHARACTERS
			iosym = findio(input);			
			int iosymsize = iosym.size();
			cmds = parseline(input, redirect);
			int cmdsize = cmds.size();
			if(iosymsize >= cmdsize) {
				cout << "Error: Too many IO redirection symbols" << endl;
			}
			else {
				end = runio(cmds, iosym);
			}
		}
		else {
			//PARSE BY '&', '|', AND ';' CHARACTERS
			constr = findconnect(input);			
			connect = strtoq(constr);		//connect stores every connector
			cmds = parseline(input, redirect);

			bool cmdend = false;		//tells if a command should end
			bool cmdfail = false;		//tracks if a command has failed
			while(!cmds.empty() && !cmdend && !end) {
				cmdend = false;
				vector<string> cstr;
				cstr = parsecommand(end, cmds.front());
				if(!end) {
					cmdfail = runexec(cstr);		//cmdfail tells if the command failed, 0 if failed, 1 if not
					cmds.pop();
					char next = connect.front();
					connect.pop();
					if(next=='&' && !cmdfail) {		//if command fails and next connector is &&,
						cmdend = true;				// then no other remaining commands are run
					}
					if(next=='|' && cmdfail) {
						cmdend = true;
					}
				}
			}
		
		}
			
	}
	cout << "Exiting from rshell." << endl;
	return 0; 
}

//will use system calls to run the commands provided
bool runexec(const vector<string> argv) {
	bool cdflag = false;
	if(argv[0]=="cd") {
		cdflag = true;
	}
	char** cmd = new char*[argv.size()+1];
	for(unsigned int i=0; i<argv.size(); ++i) {
		cmd[i] = const_cast<char* >((argv[i]).c_str());
	}
	cmd[argv.size()] = '\0';
	int pid = fork();
	int status;
	if(pid==-1 ) {	//meaning fork() returned an error
		perror("Error with fork(). ");
		delete[] cmd;
		exit(1);
	}
	else if(pid==0) {	//meaning we're in the child process
		if(!cdflag && execvp(cmd[0], cmd)==-1) {
			perror("There was an error in execvp. " );
		}
		delete[] cmd;
		exit(1);
	}
	else if(pid>0) {	//meaning we're in the parent process
		if(wait(&status)==-1) {
			perror("There was an error with wait(). " );
			delete[] cmd;
			exit(1);
		}
		//Change directory here
		if(cdflag) {
			char *currdir = getenv("PWD");
			char *prevdir = getenv("OLDPWD");
			char *homedir = getenv("HOME");
			bool cdfail = false;
			if(cmd[1] == '\0') {	//cd to home directory
				if(chdir(homedir)==-1) {
					perror("Error with chdir. ");
					cdfail = true;
				}
				if(!cdfail) {
					cout << homedir << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", homedir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}	
			}
			else if(argv[1] == "-") {		//cd to previous directory
				if(chdir(prevdir)==-1) {
					perror("Error with chdir. ");
					cdfail = true;
				}
				if(!cdfail) {
					cout << prevdir << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", prevdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}
			}
			else {		//cd to path given
				//Need to do the ".." case
				//Find the "/.." then delete the directory before
				string newpath = currdir;
				string path = cmd[1];
				int location;
				/*if(path=="..") {
					int endslash = */
				newpath = newpath + '/' + path;
				location = newpath.find("..");
				cout << "location: " << location << endl;
				int newloc = newpath.find_last_of("/", location-2);
				string frontpath = newpath.substr(0, newloc);
				/*while(-1 != (location = newpath.find(".."))) {
					
				}*/
				string backpath = newpath.substr(location+2);
				newpath = frontpath + backpath;
				const char *cpath = newpath.c_str();
				if(chdir(cpath)==-1) {
					perror("Error with chdir. ");
					cout << "cpath: " << cpath << endl;
					cdfail = true;
				}
				if(!cdfail) { 
					cout << cpath << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", cpath, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}<commit_msg>got cd to work as intended<commit_after>//THINGS TO DO:
//

#include <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <boost/tokenizer.hpp>
#include <queue>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

using namespace std;
using namespace boost;

bool runexec(vector<string> argv);	//will use system calls to run the commands provided and returns only 0 when sucessful

bool runio(queue<string> &cmds, queue<string> &connect);

string findconnect(string str);		//outputs a string of every connector

queue<string> findio(string str);			//outputs a string of each io redirection or pipe

queue<char> strtoq(string connect);		//converts the string of connectors to a queue

queue<string> parseline(string str, bool iomode);	//separate commands by connectors from the original string

vector<string> parsecommand(bool &end, string str);

string checkcomment(string str);		//checks and takes out comments on the command line

void printinfo();		//prints the username and machine name before the prompt

bool iomode(string line);

int main(int argc, char** argv) {
	string input;
	bool end = false;
	while(!end) {
		fflush(stdout);
		printinfo();
		cout << "$ ";
		getline(cin, input);
		input = checkcomment(input);
		string constr;			
		queue<string> iosym;
		queue<char> connect;		//connect stores every connector
		queue<string> cmds;

		bool redirect = iomode(input);
		if(redirect) {
			//PARSE BY '>', '<', AND '|' CHARACTERS
			iosym = findio(input);			
			int iosymsize = iosym.size();
			cmds = parseline(input, redirect);
			int cmdsize = cmds.size();
			if(iosymsize >= cmdsize) {
				cout << "Error: Too many IO redirection symbols" << endl;
			}
			else {
				end = runio(cmds, iosym);
			}
		}
		else {
			//PARSE BY '&', '|', AND ';' CHARACTERS
			constr = findconnect(input);			
			connect = strtoq(constr);		//connect stores every connector
			cmds = parseline(input, redirect);

			bool cmdend = false;		//tells if a command should end
			bool cmdfail = false;		//tracks if a command has failed
			while(!cmds.empty() && !cmdend && !end) {
				cmdend = false;
				vector<string> cstr;
				cstr = parsecommand(end, cmds.front());
				if(!end) {
					cmdfail = runexec(cstr);		//cmdfail tells if the command failed, 0 if failed, 1 if not
					cmds.pop();
					char next = connect.front();
					connect.pop();
					if(next=='&' && !cmdfail) {		//if command fails and next connector is &&,
						cmdend = true;				// then no other remaining commands are run
					}
					if(next=='|' && cmdfail) {
						cmdend = true;
					}
				}
			}
		
		}
			
	}
	cout << "Exiting from rshell." << endl;
	return 0; 
}

//will use system calls to run the commands provided
bool runexec(const vector<string> argv) {
	bool cdflag = false;
	if(argv[0]=="cd") {
		cdflag = true;
	}
	char** cmd = new char*[argv.size()+1];
	for(unsigned int i=0; i<argv.size(); ++i) {
		cmd[i] = const_cast<char* >((argv[i]).c_str());
	}
	cmd[argv.size()] = '\0';
	int pid = fork();
	int status;
	if(pid==-1 ) {	//meaning fork() returned an error
		perror("Error with fork(). ");
		delete[] cmd;
		exit(1);
	}
	else if(pid==0) {	//meaning we're in the child process
		if(!cdflag) {
			if(execvp(cmd[0], cmd)==-1) {
				perror("There was an error in execvp. " );
			}
			cout << "cmd[0]: " << cmd[0] << endl;		//DELETE
			delete[] cmd;
			exit(1);
		}
		else {
			exit(0);
		}
	}
	else if(pid>0) {	//meaning we're in the parent process
		if(wait(&status)==-1) {
			perror("There was an error with wait(). " );
			delete[] cmd;
			exit(1);
		}
		//Change directory here
		if(cdflag) {
			char *currdir = getenv("PWD");
			char *prevdir = getenv("OLDPWD");
			char *homedir = getenv("HOME");
			bool cdfail = false;
			if(cmd[1] == '\0') {	//cd to home directory
				if(chdir(homedir)==-1) {
					perror("Error with chdir. ");
					cdfail = true;
				}
				if(!cdfail) {
					cout << homedir << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", homedir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}	
			}
			else if(argv[1] == "-") {		//cd to previous directory
				if(chdir(prevdir)==-1) {
					perror("Error with chdir. ");
					cdfail = true;
				}
				if(!cdfail) {
					cout << prevdir << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", prevdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}
			}
			else {		//cd to path given
				string newpath = currdir;
				string homepath = homedir;
				string path = cmd[1];
				if(path.size()<newpath.size() || path.substr(0,homepath.size()-1)!=homedir) {
					if(path.at(0)=='/' || newpath.back()=='/') {
						newpath = newpath + path;
					}
					else {
						newpath = newpath + "/" + path;
					}
					if(newpath.back()=='/') {
						newpath = newpath.substr(0, newpath.size()-1);
					}
					cout << "newpath: " << newpath << endl;
				}
					
				int location;
				while(-1 != (location = newpath.find(".."))) { 
					cout << "location: " << location << endl;
					int newloc = newpath.find_last_of("/", location-2);
					string frontpath = newpath.substr(0, newloc);
					string backpath = newpath.substr(location+2);
					newpath = frontpath + backpath;
				}
				const char *cpath = newpath.c_str();
				if(chdir(cpath)==-1) {
					perror("Error with chdir. ");
					cout << "cpath: " << cpath << endl;
					cdfail = true;
				}
				if(!cdfail) { 
					cout << cpath << endl;
					if(setenv("OLDPWD", currdir, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
					if(setenv("PWD", cpath, 1)==-1) {
						perror("Error with setenv().");
						exit(1);
					}
				}
{'fraction_non_alphanumeric': 0.1702968557878096, 'fraction_numerical': 0.008782715615668365, 'mean_word_length': 2.834006734006734, 'pattern_counts': {'":': 0, '<': 138, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5059534', 'n_tokens_mistral': 5020, 'n_tokens_neox': 4110, 'n_words': 1090}