<commit_before>#include<iostream>
#include<fcntl.h>
#include<pwd.h>
#include<sstream>
#include<stdio.h>
#include<boost/tokenizer.hpp>
#include<errno.h>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/unistd.h>

using namespace std;
using namespace boost;

typedef tokenizer<char_separator<char> > Tok;

void readCommands(string str);
int conjunct(int n, stringstream& ss, const Tok::iterator &it);
void skipCommand(Tok::iterator &it, Tok &tokens);
void splitString(char** args, stringstream& ss, int n);
void ioRedir(const Tok::iterator &it, bool inRedir, bool append);
void resetIO(int in0, int out1);

int main(){

    cout << endl;
    string str = "";
    struct passwd *pass;

    pass = getpwuid(getuid());
    if(pass == NULL){
        perror("getpwuid()");
    }

    char* usrname = pass->pw_name;
    char hostname[128];

    int success = gethostname(hostname, sizeof hostname);
    if(success == -1){
        perror("gethostname()");
    }

    string userinfo = "";
    string username = "";

    if(usrname != NULL && success == 0){
        username = usrname;
        userinfo = username + "@" + hostname;
    }

    bool notExited = true;

    while(notExited){
        cout << userinfo << "$ ";
        getline(cin, str);
        readCommands(str);
    }

    return 0;
}

void readCommands(string str){

    char_separator<char> sep("\" ", ";#|&<>");

    Tok tokens(str, sep);
    stringstream ss;
    int in0;
    int out1;
    bool didRedir = false;
    int n = 0;

    if((in0 = dup(0)) == -1){
        perror("input-0");
        exit(-1);
    }

    if((out1 = dup(1)) == -1){
        perror("output-1");
        exit(-1);
    }

    for(Tok::iterator it = tokens.begin(); it != tokens.end(); it++){

        if(*it == ";"){
            conjunct(n, ss, it);
            n = 0;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it ==  "&"){
            if(conjunct(n, ss, it) == -1){
                skipCommand(it, tokens);
            }
            n = 0;
            if(it == tokens.end()) break;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it == "|"){
            Tok::iterator copy = it;
            copy++;
// Remove this part once we deal with piping
            if(copy != tokens.end() && *copy != "|") {
                conjunct(0, ss, it);
                skipCommand(it, tokens);
            }
//======
            if(copy != tokens.end() && *copy == "|"){
                if(conjunct(n, ss, it) != -1){
                    skipCommand(it, tokens);
                }
            }
            n = 0;
            if(it == tokens.end()) break;
            it++;
        }
        else if(*it == "<" || *it == ">"){

            another:

            bool inRedir = false;
            bool append = false;

            if(*it == "<") inRedir = true;

            it++;

            here:

            if(it == tokens.end()){
                cerr << "Bash: syntax error near unexpected token \'newline\'" << endl;
                exit(-1);
            }

            if(*it == ">"){
                append = true;
                it++;
                goto here;
            }

            ioRedir(it, inRedir, append);

            didRedir = true;

            it++;

            if(it == tokens.end()) break;

            if(*it == ">" || *it == "<") goto another;
        }

        if(*it == "#"){
            conjunct(n, ss, it);
            return;
        }

        if(*it != "&" && *it != "|"){
            ss << *it;
            ss << " ";
            n++;
        }
    }

    if(n > 0){
        Tok::iterator it = tokens.begin();
        conjunct(n, ss, it);
    }

    if(didRedir){
        resetIO(in0, out1);
    }
}

int conjunct(int n, stringstream& ss, const Tok::iterator &it){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return -1;
    }
    else if(n == 0 && *it == "#") return 0;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    int pid = fork();

    if(pid == -1){
        perror("There was an error with the fork().");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp((const char*) args[0], (char* const*) args)){
            perror(args[0]);
            exit(3);
        }
    }
    else if(pid > 0){
        if(-1 == wait(&status)){
            perror("There was an error with wait().");
            return -1;
        }

        if(WIFEXITED(status)){
            if(WEXITSTATUS(status) == 3){
                delete[] args;
                return -1;
            }
        }
    }
    delete[] args;

    return 0;
}

//TODO INPUT REDIRECTION
void ioRedir(const Tok::iterator &it, bool inRedir, bool append){

    if(*it == "&" || *it == "|" || *it == ";"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        exit(-1);
    }

    if(inRedir){
        string input = *it;

        int fdi;

        if((fdi = open((char*) input.c_str(), O_RDONLY)) == -1){
            perror("open input");
            exit(-1);
        }

        if(close(0) == -1){
            perror("close input");
            exit(-1);
        }

        if(dup(fdi) == -1){
            perror("dup input");
            exit(-1);
        }
        return;
    }
    else{
        string output = *it;

        int fdo;
        mode_t readWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

        if(append){
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_APPEND,  readWrite)) == -1){
                perror("open output");
                exit(-1);
            }
        }
        else{
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_TRUNC,  readWrite)) == -1){
                perror("open output append");
                exit(-1);
            }
        }

        if(close(1) == -1){
            perror("close output");
            exit(-1);
        }

        if(dup(fdo) == -1){
            perror("dup output");
            exit(-1);
        }
    }
}

void resetIO(int in0, int out1){

    if(close(0) == -1){
        perror("close fd");
        exit(-1);
    }

    if(dup2(in0, 0) == -1){
        perror("dup input - 0");
        exit(-1);
    }

    if(close(1) == -1){
        perror("close fd");
        exit(-1);
    }

    if(dup2(out1, 1) == -1){
        perror("dup output - 1");
        exit(-1);
    }
}

void skipCommand(Tok::iterator &it, Tok &tokens){
    while(it != tokens.end() && *it != ";"){
        it++;
    }
}

void splitString(char** args, stringstream& ss, int n){

    string *str = new string[n];

    for(int i = 0; i < n; i++){

        ss >> str[i];

        args[i] = (char*) str[i].c_str();
    }

    args[n] = NULL;

    char exitC[] = "exit";

    if(strcmp(args[0], exitC) == 0){
        cout << endl;
        exit(0);
    }

    delete[] str;
}
<commit_msg>almost done with piping<commit_after>#include<iostream>
#include<fcntl.h>
#include<pwd.h>
#include<sstream>
#include<stdio.h>
#include<boost/tokenizer.hpp>
#include<errno.h>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/unistd.h>

using namespace std;
using namespace boost;

typedef tokenizer<char_separator<char> > Tok;

void readCommands(string str);
int conjunct(int n, stringstream& ss, const Tok::iterator &it);
void skipCommand(Tok::iterator &it, Tok &tokens);
void splitString(char** args, stringstream& ss, int n);
void ioRedir(const Tok::iterator &it, bool inRedir, bool append);
void resetIO(int in0, int out1);
void pipeRedir(int fd[], bool pipeOut);
void resetPipe(int fd, bool isOut);

int main(){

    cout << endl;
    string str = "";
    struct passwd *pass;

    pass = getpwuid(getuid());
    if(pass == NULL){
        perror("getpwuid()");
    }

    char* usrname = pass->pw_name;
    char hostname[128];

    int success = gethostname(hostname, sizeof hostname);
    if(success == -1){
        perror("gethostname()");
    }

    string userinfo = "";
    string username = "";

    if(usrname != NULL && success == 0){
        username = usrname;
        userinfo = username + "@" + hostname;
    }

    bool notExited = true;

    while(notExited){
        cout << userinfo << "$ ";
        getline(cin, str);
        readCommands(str);
    }

    return 0;
}

void readCommands(string str){

    char_separator<char> sep("\" ", ";#|&<>");

    Tok tokens(str, sep);
    stringstream ss;
    int in0;
    int out1;
    int fd[2];
    bool pipeOut = false;
    bool didRedir = false;
    bool didPipe = false;
    int n = 0;

    if((in0 = dup(0)) == -1){
        perror("input-0");
        exit(-1);
    }

    if((out1 = dup(1)) == -1){
        perror("output-1");
        exit(-1);
    }

    if(pipe(fd) == -1){
        perror("pipe");
        exit(-1);
    }

    for(Tok::iterator it = tokens.begin(); it != tokens.end(); it++){

        if(*it == ";"){
            conjunct(n, ss, it);
            n = 0;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it ==  "&"){
            if(conjunct(n, ss, it) == -1){
                skipCommand(it, tokens);
            }
            n = 0;
            if(it == tokens.end()) break;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it == "|"){
            Tok::iterator copy = it;
            copy++;

            if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                conjunct(0, ss, it);
                skipCommand(it, tokens);
                return;
            }

            if(*copy == "|"){
                copy++;
                if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                    conjunct(0, ss, it);
                    skipCommand(it, tokens);
                    return;
                }

                if(conjunct(n, ss, it) != -1){
                    skipCommand(it, tokens);
                }
            }
            else{
                didPipe = true;
                pipeOut = true;
                pipeRedir(fd, pipeOut);
                if(conjunct(n, ss, it) == -1){
                    skipCommand(it, tokens);
                }
                pipeOut = false;
                pipeRedir(fd, pipeOut);

                n = 0;
                continue;
            }
//TODO Piping
            n = 0;
            if(it == tokens.end()) break;
            it++;
        }
        else if(*it == "<" || *it == ">"){

            another:

            bool inRedir = false;
            bool append = false;

            if(*it == "<") inRedir = true;

            it++;

            here:

            if(it == tokens.end()){
                cerr << "Bash: syntax error near unexpected token \'newline\'" << endl;
                exit(-1);
            }

            if(*it == ">"){
                append = true;
                it++;
                goto here;
            }

            ioRedir(it, inRedir, append);

            didRedir = true;

            it++;

            if(it == tokens.end()) break;

            if(*it == ">" || *it == "<") goto another;
        }

        if(*it == "#"){
            conjunct(n, ss, it);
            return;
        }

        if(*it != "&" && *it != "|"){
            ss << *it;
            ss << " ";
            n++;
        }
    }

    if(n > 0){
        Tok::iterator it = tokens.begin();
        if(didPipe){
            resetPipe(out1, true);
        }
        conjunct(n, ss, it);
        if(didPipe){
            resetPipe(in0, false);
        }
    }

    if(didRedir){
        resetIO(in0, out1);
    }
}

int conjunct(int n, stringstream& ss, const Tok::iterator &it){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return -1;
    }
    else if(n == 0 && *it == "#") return 0;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    int pid = fork();

    if(pid == -1){
        perror("There was an error with the fork().");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp((const char*) args[0], (char* const*) args)){
            perror(args[0]);
            exit(3);
        }
    }
    else if(pid > 0){
        if(-1 == wait(&status)){
            perror("There was an error with wait().");
            return -1;
        }

        if(WIFEXITED(status)){
            if(WEXITSTATUS(status) == 3){
                delete[] args;
                return -1;
            }
        }
    }
    delete[] args;

    return 0;
}

//TODO INPUT REDIRECTION
void ioRedir(const Tok::iterator &it, bool inRedir, bool append){

    if(*it == "&" || *it == "|" || *it == ";"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        exit(-1);
    }

    if(inRedir){
        string input = *it;

        int fdi;

        if((fdi = open((char*) input.c_str(), O_RDONLY)) == -1){
            perror("open input");
            exit(-1);
        }

        if(close(0) == -1){
            perror("close input");
            exit(-1);
        }

        if(dup(fdi) == -1){
            perror("dup input");
            exit(-1);
        }
        return;
    }
    else{
        string output = *it;

        int fdo;
        mode_t readWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

        if(append){
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_APPEND,  readWrite)) == -1){
                perror("open output");
                exit(-1);
            }
        }
        else{
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_TRUNC,  readWrite)) == -1){
                perror("open output append");
                exit(-1);
            }
        }

        if(close(1) == -1){
            perror("close output");
            exit(-1);
        }

        if(dup(fdo) == -1){
            perror("dup output");
            exit(-1);
        }
    }
}

void resetIO(int in0, int out1){

    if(close(0) == -1){
        perror("close fd");
        exit(-1);
    }

    if(dup2(in0, 0) == -1){
        perror("dup input - 0");
        exit(-1);
    }

    if(close(1) == -1){
        perror("close fd");
        exit(-1);
    }

    if(dup2(out1, 1) == -1){
        perror("dup output - 1");
        exit(-1);
    }
}

void resetPipe(int fd, bool isOut){
    if(isOut){
        if(dup2(fd, 1) == -1){
            perror("dup2 pipe output reset");
            exit(-1);
        }
    }
    else{
        if(dup2(fd, 0) == -1){
            perror("dup2 pipe input reset");
            exit(-1);
        }
    }
}

void pipeRedir(int fd[], bool pipeOut){
    if(pipeOut){
        if(dup2(fd[1], 1) == -1){
            perror("dup2: pipe out");
            exit(-1);
        }
    }
    else{
        if(dup2(fd[0], 0) == -1){
            perror("dup2: pipe in");
            exit(-1);
        }
    }
}

void skipCommand(Tok::iterator &it, Tok &tokens){
    while(it != tokens.end() && *it != ";"){
        it++;
    }
}

void splitString(char** args, stringstream& ss, int n){

    string *str = new string[n];

    for(int i = 0; i < n; i++){

        ss >> str[i];

        args[i] = (char*) str[i].c_str();
    }

    args[n] = NULL;

    char exitC[] = "exit";

    if(strcmp(args[0], exitC) == 0){
        cout << endl;
        exit(0);
    }

    delete[] str;
}
<|endoftext|>


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

int oldstdin = dup(0);
int oldstdout = dup(1);
int oldstderr = dup(2);

using namespace std;
using namespace boost;

void execvp(char **ye, int k) {
	ye[k] = NULL;
        int pid = fork();
        if(pid == -1) {
       		perror("fork");
                exit(1);
        }
        if(pid == 0) {
        	int r = execvp(ye[0], ye);
                if(r == -1) {
                       perror("execvp");
                       exit(1);
                }
        }
      	else {
        	if(-1 == waitpid(pid, &pid, 0)) {
                          perror("waitpid");
                }
        }

}

void rshell(string &x) {
	char *argv[9];
	int i = 0;
	string going;
	string saad;
	vector<string> arg_s;
	typedef tokenizer< char_separator<char> > tokenizer;
	char_separator<char> sep (" ", "<>>>\"#-;||&&", drop_empty_tokens);
	tokenizer tokens(x, sep);
	for(tokenizer::iterator tok_iter=tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {			 if(saad == "-") {
			going += *tok_iter;
			going += " ";
		 	saad.append(*tok_iter);
			arg_s.push_back(saad);
			argv[i] = new char[12];
			strcpy(argv[i], const_cast<char*>(saad.c_str()));
			if(*tok_iter == "exit")
				exit(0);
                        ++i;
                        continue;

		  }

                  if(*tok_iter == "-") {
                        saad = *tok_iter;
			going += *tok_iter;
			going += " ";
                        continue;
                  }

	          if(*tok_iter == "#") {
			break;
		  }

		  if(*tok_iter == ";") {
                        ++tok_iter;
                        rshell(going);
                        going.erase(0, going.find(*tok_iter, i));
                        arg_s.clear();
                        i = 0;
                        argv[i] = new char[12];
	          }

		  if(*tok_iter == "&") {
			++tok_iter;
			if(*tok_iter == "&") {
				++tok_iter;
				rshell(going);
				going.erase(0, going.find(*tok_iter, i));
				arg_s.clear();
				i = 0;
				argv[i] = new char[12];
			}
		  }

		  if(*tok_iter == "<") {
			++tok_iter;

			if(*tok_iter == "<") {
			//	going += *tok_iter;
				++tok_iter;
			//	going += *tok_iter;
				if(*tok_iter == "<") {
					//EXTRA CREDIT 1 HERE!!!!!!!!!!!
					string blah = "ok";
					void *buf;
					int fd2 = creat(const_cast<char*>(blah.c_str()), S_IRWXU);
					if(fd2 == -1) {
						perror("creat");
						exit(1);
					}
					++tok_iter;
					going += *tok_iter;
					string leggo;
					if(*tok_iter == "\"") {
						++tok_iter;
						while(*tok_iter != "\"") {
							cout << *tok_iter << endl;
							leggo += *tok_iter;
							leggo += " ";
							++tok_iter;
						}
						buf = malloc(leggo.length());
						//leggo += *tok_iter;
						//going += " ";
						//going += leggo;
						int bag = write(fd2, buf, leggo.length());
						if(bag == -1) {
							perror("write");
							exit(1);
						}
					}
				}
			}
			string cake = *tok_iter;
			int savestdin;
			if(-1 == (savestdin = dup(0))) {
				perror("dup");
				exit(1);
			}
			int fd = open(cake.c_str(), O_RDWR);
			if(fd == -1) {
				perror("open");
				exit(1);
			}
			int drag = dup2(fd, 0);
			if(drag == -1) {
				perror("dup2");
				exit(1);
			}
			//if(-1 == dup2(savestdin, 0))
			//{
			//	perror("dup2");
			//	exit(1);
			//}
			continue;
		  }

		  if(*tok_iter == ">") {
			++tok_iter;
			if(*tok_iter == ">") {
				++tok_iter;
				string swerve = *tok_iter;
				int fd2 = open(swerve.c_str(), O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
				if(fd2 == -1) {
					perror("open");
					exit(1);
				}
				int grag = dup2(fd2, 1);
				if(grag == -1) {
					perror("dup2");
					exit(1);
				}
				continue;
			}
			else {
				string hold = *tok_iter;
				int fd = open(hold.c_str(), O_RDWR|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR);
				if(fd == -1) {
					perror("open");
					exit(1);
				}
				int drag = dup2(fd, 1);
				if(drag == -1) {
					perror("dup2");
					exit(1);
				}
				continue;
			}
		  }

		  if(*tok_iter == "|") {
			++tok_iter;
			tokenizer::iterator coward;
			if(*tok_iter != "|") {
			//piping
			int pipefd[2];
			pid_t cpid;
			//char buf;
			if(pipe(pipefd) == -1) {
				perror("pipe");
				exit(1);
			}
			cpid = fork();
			if(cpid == -1) {
				perror("fork");
				exit(1);
			}
			else if(cpid == 0) {
				if(-1 == dup2(pipefd[1],1))
				{
					perror("dup2");
					exit(1);
				}
				if(-1 == close(pipefd[0]))
				{
					perror("close");
					exit(1);
				}
				argv[i] = NULL;
				if(-1 == execvp(argv[0], argv))
				{
					perror("execvp");
				}
				exit(1);
			}
			else if(cpid > 0)
			{
				int savestdin;
				if(-1 == (savestdin = dup(0)))
				{
					perror("dup");
					exit(1);
				}
				if(-1 == dup2(pipefd[0], 0)) {
					perror("dup2");
					exit(1);
				}
				if(-1 == close(pipefd[1])) {
					perror("close");
					exit(1);
				}
				if(-1 == waitpid(cpid, &cpid, 0)) {
					perror("waitpid");
					exit(1);
				}
				int pipefd2[2];
				pid_t cpid2;
				if(pipe(pipefd2) == -1) {
					perror("pipe");
					exit(1);
				}
				cpid2 = fork();
				if(cpid2 == -1) {
					perror("fork");
					exit(1);
				}
				else if(cpid2 == 0) {
					if(-1 == dup2(pipefd2[0], 0))
					{
						perror("dup2");
						exit(1);
					}
					if(-1 == close(pipefd2[1]))
					{
						perror("close");
						exit(1);
					}
					coward = tok_iter;
					char *toby[9];
					int l = 0;
					vector<string> baby;
					string mok;
					while(tok_iter != tokens.end()) {
						if(*tok_iter == "|")
							rshell(going);

						mok += *tok_iter;
						mok += " ";
						baby.push_back(*tok_iter);
						toby[l] = new char [12];
						strcpy(toby[l], const_cast<char*>(baby[l].c_str()));
						going += mok;
						++l;
					}
					toby[l] = NULL;
					if(-1 == execvp(toby[0], toby))
						perror("execvp");

					exit(1);
				}
				else if(cpid > 0) {
					int savestdout;
					if(-1 == (savestdout = dup(1)))
					{
						perror("dup");
						exit(1);
					}
					if(-1 == dup2(pipefd2[1], 1)) {
						perror("dup2");
						exit(1);
					}
					if(-1 == close(pipefd2[0])) {
						perror("close");
						exit(1);
					}
					if(-1 == waitpid(cpid2, &cpid2, 0)) {
						perror("waitpid");
						exit(1);
					}
					if(-1 == dup2(savestdout, 1))
						perror("dup2");
				}
					if(-1 == dup2(savestdin, 0))
						perror("dup2");
				}
				/*
				coward = tok_iter;
				char *toby[9];
				int l = 0;
				vector<string> baby;
				string mok;
				int kpid = fork();
				if(kpid == -1) {
					perror("fork");
					exit(1);
				}
				else if(kpid == 0) {
					if(-1 == dup2(pipefd[0], 0)) {
						perror("dup2");
						exit(1);
					}
					//if(-1 == close(pipefd[1]))
					//{
					//	perror("close");
					//	exit(1);
					//}
					while(tok_iter != tokens.end()) {
						if(*tok_iter == "|")
							rshell(going);

						mok += *tok_iter;
						mok += " ";
						baby.push_back(*tok_iter);
						toby[l] = new char[12];
						strcpy(toby[i], const_cast<char*>(baby[l].c_str()));
						going += mok;
						//APPEND TOBY TO ARGV SOMEHOW
						++l;
					}
					toby[l] = NULL;
					if(-1 == execvp(toby[0], toby)) {
						perror("execvp");
					}
					exit(1);
				}
				else if(kpid > 0) {
					if(-1 == waitpid(kpid, &kpid, 0)) {
						perror("waitpid");
						exit(1);
					}
				}

				tok_iter = coward;

				if(-1 == dup2(savestdin, 0)) {
					perror("dup2");
					exit(1);
				}
				}
				continue;
				*/
			}
			//end piping

			if(*tok_iter == "|") {
				++tok_iter;
				rshell(going);
				going.erase(0, going.find(*tok_iter, i));
				arg_s.clear();
				i = 0;
				argv[i] = new char[12];
			}

		  }

		  going += *tok_iter;
		  going += " ";

		  arg_s.push_back(*tok_iter);
		  argv[i] = new char[12];
	 	  strcpy(argv[i], const_cast<char*>(arg_s[i].c_str()));

		  if(*tok_iter == "exit")
			exit(0);

		  ++i;

	}

	execvp(argv, i);

	return;
}

int main()
{
	string args;
	while(1 != 2)
	{
		cout << "$ ";
		getline(cin, args);
		rshell(args);

		int ok = dup2(oldstdin, 0);
		if(ok == -1) {
			perror("dup2");
			exit(1);
		}
		int ok2 = dup2(oldstdout, 1);
		if(ok2 == -1) {
			perror("dup2");
			exit(1);
		}
		int ok3 = dup2(oldstderr, 2);
		if(ok3 == -1) {
			perror("dup2");
			exit(1);
		}
	}

	return 0;
}
<commit_msg>piping updated in rshell.cpp<commit_after>#include <boost/tokenizer.hpp>
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <sstream>
#include <vector>
#include <sys/stat.h>
#include <fcntl.h>

int oldstdin = dup(0);
int oldstdout = dup(1);
int oldstderr = dup(2);

using namespace std;
using namespace boost;

void execvp(char **ye, int k) {
	ye[k] = NULL;
        int pid = fork();
        if(pid == -1) {
       		perror("fork");
                exit(1);
        }
        if(pid == 0) {
        	int r = execvp(ye[0], ye);
                if(r == -1) {
                       perror("execvp");
                       exit(1);
                }
        }
      	else {
        	if(-1 == waitpid(pid, &pid, 0)) {
                          perror("waitpid");
                }
        }

}

void rshell(string &x) {
	char *argv[9];
	int i = 0;
	string going;
	string saad;
	vector<string> arg_s;
	typedef tokenizer< char_separator<char> > tokenizer;
	char_separator<char> sep (" ", "<>>>\"#-;||&&", drop_empty_tokens);
	tokenizer tokens(x, sep);
	for(tokenizer::iterator tok_iter=tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {			 if(saad == "-") {
			going += *tok_iter;
			going += " ";
		 	saad.append(*tok_iter);
			arg_s.push_back(saad);
			argv[i] = new char[12];
			strcpy(argv[i], const_cast<char*>(saad.c_str()));
			if(*tok_iter == "exit")
				exit(0);
                        ++i;
                        continue;

		  }

                  if(*tok_iter == "-") {
                        saad = *tok_iter;
			going += *tok_iter;
			going += " ";
                        continue;
                  }

	          if(*tok_iter == "#") {
			break;
		  }

		  if(*tok_iter == ";") {
                        ++tok_iter;
                        rshell(going);
                        going.erase(0, going.find(*tok_iter, i));
                        arg_s.clear();
                        i = 0;
                        argv[i] = new char[12];
	          }

		  if(*tok_iter == "&") {
			++tok_iter;
			if(*tok_iter == "&") {
				++tok_iter;
				rshell(going);
				going.erase(0, going.find(*tok_iter, i));
				arg_s.clear();
				i = 0;
				argv[i] = new char[12];
			}
		  }

		  if(*tok_iter == "<") {
			++tok_iter;

			if(*tok_iter == "<") {
			//	going += *tok_iter;
				++tok_iter;
			//	going += *tok_iter;
				if(*tok_iter == "<") {
					//EXTRA CREDIT 1 HERE!!!!!!!!!!!
					string blah = "ok";
					void *buf;
					int fd2 = creat(const_cast<char*>(blah.c_str()), S_IRWXU);
					if(fd2 == -1) {
						perror("creat");
						exit(1);
					}
					++tok_iter;
					going += *tok_iter;
					string leggo;
					if(*tok_iter == "\"") {
						++tok_iter;
						while(*tok_iter != "\"") {
							cout << *tok_iter << endl;
							leggo += *tok_iter;
							leggo += " ";
							++tok_iter;
						}
						buf = malloc(leggo.length());
						//leggo += *tok_iter;
						//going += " ";
						//going += leggo;
						int bag = write(fd2, buf, leggo.length());
						if(bag == -1) {
							perror("write");
							exit(1);
						}
					}
				}
			}
			string cake = *tok_iter;
			int savestdin;
			if(-1 == (savestdin = dup(0))) {
				perror("dup");
				exit(1);
			}
			int fd = open(cake.c_str(), O_RDWR);
			if(fd == -1) {
				perror("open");
				exit(1);
			}
			int drag = dup2(fd, 0);
			if(drag == -1) {
				perror("dup2");
				exit(1);
			}
			//if(-1 == dup2(savestdin, 0))
			//{
			//	perror("dup2");
			//	exit(1);
			//}
			continue;
		  }

		  if(*tok_iter == ">") {
			++tok_iter;
			if(*tok_iter == ">") {
				++tok_iter;
				string swerve = *tok_iter;
				int fd2 = open(swerve.c_str(), O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
				if(fd2 == -1) {
					perror("open");
					exit(1);
				}
				int grag = dup2(fd2, 1);
				if(grag == -1) {
					perror("dup2");
					exit(1);
				}
				continue;
			}
			else {
				string hold = *tok_iter;
				int fd = open(hold.c_str(), O_RDWR|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR);
				if(fd == -1) {
					perror("open");
					exit(1);
				}
				int drag = dup2(fd, 1);
				if(drag == -1) {
					perror("dup2");
					exit(1);
				}
				continue;
			}
		  }

		  if(*tok_iter == "|") {
			++tok_iter;
			tokenizer::iterator coward;
			if(*tok_iter != "|") {
			//piping
			int pipefd[2];
			pid_t cpid;
			//char buf;
			if(pipe(pipefd) == -1) {
				perror("pipe");
				exit(1);
			}
			cpid = fork();
			if(cpid == -1) {
				perror("fork");
				exit(1);
			}
			else if(cpid == 0) {
				if(-1 == dup2(pipefd[1],1))
				{
					perror("dup2");
					exit(1);
				}
				if(-1 == close(pipefd[0]))
				{
					perror("close");
					exit(1);
				}
				argv[i] = NULL;
				if(-1 == execvp(argv[0], argv))
				{
					perror("execvp");
				}
				exit(1);
			}
			else if(cpid > 0)
			{
				int savestdin;
				if(-1 == (savestdin = dup(0)))
				{
					perror("dup");
					exit(1);
				}
				if(-1 == dup2(pipefd[0], 0)) {
					perror("dup2");
					exit(1);
				}
				if(-1 == close(pipefd[1])) {
					perror("close");
					exit(1);
				}
				if(-1 == waitpid(cpid, &cpid, 0)) {
					perror("waitpid");
					exit(1);
				}
				int pipefd2[2];
				pid_t cpid2;
				if(pipe(pipefd2) == -1) {
					perror("pipe");
					exit(1);
				}
				cpid2 = fork();
				if(cpid2 == -1) {
					perror("fork");
					exit(1);
				}
				else if(cpid2 == 0) {
					if(-1 == dup2(pipefd2[1], 1))
					{
						perror("dup2");
						exit(1);
					}
					if(-1 == close(pipefd2[0]))
					{
						perror("close");
						exit(1);
					}
					coward = tok_iter;
					char *toby[9];
					int l = 0;
					vector<string> baby;
					string mok;
					while(tok_iter != tokens.end()) {
						if(*tok_iter == "|")
							rshell(going);

						mok += *tok_iter;
						mok += " ";
						baby.push_back(*tok_iter);
						toby[l] = new char [12];
						strcpy(toby[l], const_cast<char*>(baby[l].c_str()));
						going += mok;
						++l;
					}
					toby[l] = NULL;
					if(-1 == execvp(toby[0], toby))
						perror("execvp");

					exit(1);
				}
				else if(cpid > 0) {
					int savestdin;
					if(-1 == (savestdin = dup(0)))
					{
						perror("dup");
						exit(1);
					}
					if(-1 == dup2(pipefd2[0], 0)) {
						perror("dup2");
						exit(1);
					}
					if(-1 == close(pipefd2[1])) {
						perror("close");
						exit(1);
					}
					if(-1 == waitpid(cpid2, &cpid2, 0)) {
						perror("waitpid");
						exit(1);
					}
					//if(-1 == dup2(savestdout, 1))
					//	perror("dup2");
				}
					//if(-1 == dup2(savestdin, 0))
					//	perror("dup2");
					continue;
				}
				/*
				coward = tok_iter;
				char *toby[9];
				int l = 0;
				vector<string> baby;
				string mok;
				int kpid = fork();
				if(kpid == -1) {
					perror("fork");
					exit(1);
				}
				else if(kpid == 0) {
					if(-1 == dup2(pipefd[0], 0)) {
						perror("dup2");
						exit(1);
					}
					//if(-1 == close(pipefd[1]))
					//{
					//	perror("close");
					//	exit(1);
					//}
					while(tok_iter != tokens.end()) {
						if(*tok_iter == "|")
							rshell(going);

						mok += *tok_iter;
						mok += " ";
						baby.push_back(*tok_iter);
						toby[l] = new char[12];
						strcpy(toby[i], const_cast<char*>(baby[l].c_str()));
						going += mok;
						//APPEND TOBY TO ARGV SOMEHOW
						++l;
					}
					toby[l] = NULL;
					if(-1 == execvp(toby[0], toby)) {
						perror("execvp");
					}
					exit(1);
				}
				else if(kpid > 0) {
					if(-1 == waitpid(kpid, &kpid, 0)) {
						perror("waitpid");
						exit(1);
					}
				}

				tok_iter = coward;

				if(-1 == dup2(savestdin, 0)) {
					perror("dup2");
					exit(1);
				}
				}
				continue;
				*/
			}
			//end piping

			if(*tok_iter == "|") {
				++tok_iter;
				rshell(going);
				going.erase(0, going.find(*tok_iter, i));
				arg_s.clear();
				i = 0;
				argv[i] = new char[12];
			}

		  }

		  going += *tok_iter;
		  going += " ";

		  arg_s.push_back(*tok_iter);
		  argv[i] = new char[12];
	 	  strcpy(argv[i], const_cast<char*>(arg_s[i].c_str()));

		  if(*tok_iter == "exit")
			exit(0);

		  ++i;

	}

	execvp(argv, i);

	return;
}

int main()
{
	string args;
	while(1 != 2)
	{
		cout << "$ ";
		getline(cin, args);
		rshell(args);

		int ok = dup2(oldstdin, 0);
		if(ok == -1) {
			perror("dup2");
			exit(1);
		}
		int ok2 = dup2(oldstdout, 1);
		if(ok2 == -1) {
			perror("dup2");
			exit(1);
		}
		int ok3 = dup2(oldstderr, 2);
		if(ok3 == -1) {
			perror("dup2");
			exit(1);
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <vector>
#include <stdlib.h>
#include <fcntl.h>

using namespace std;

void parse(char * line, vector<string> & input) {

    char * pch;
	pch = strtok (line, " \n");
	while (pch!= NULL) {

	    // Ignore after comments
	    if (*pch == '#')
		break;

	    // Check for && and ||
	    // Break input up
	    char * a = strstr(pch, "&&");
	    char * b = strstr(pch, "||");
	    char * c = strstr(pch, ";");
        char * d = strstr(pch, "<");
        char * e = strstr(pch, ">");
        char * f = strstr(pch, "|");

	    // If there are connectors, break up the string
	    // into parts and add them individually to the vector
	    if (a!=NULL || b!=NULL || c!=NULL || d!=NULL || e!=NULL || f!=NULL) {
		while (strlen(pch) != 0 ) {

		    // Checks for && and ||
		    if ((pch[0] == '&' && pch[1] == '&') ||
			(pch[0] == '|' && pch[1] == '|')) {

			    string tmp;
			    tmp += *pch;
			    tmp += *(pch+1);
			    tmp[2] = '\0';

			    input.push_back(tmp);
			    memmove(pch, pch+2, strlen(pch) - 2);
			    pch[strlen(pch)-2] = '\0';
		    }
		    // Check for semicolons
		    else if (*pch == ';') {
			    input.push_back(";");
			    memmove(pch, pch+1, strlen(pch) -1);
			    pch[strlen(pch)-1] = '\0';
		    }
            // Check for input/output redirectors
            else if (*pch == '<') {
                input.push_back("<");
                memmove(pch, pch+1, strlen(pch) -1);
                pch[strlen(pch)-1] = '\0';
            }
            else if (*pch == '>') {
                if (*(pch+1) == '>') {
                    input.push_back(">>");
                    memmove(pch, pch+2, strlen(pch) -2);
                    pch[strlen(pch)-2] = '\0';
                }
                else {
                    input.push_back(">");
                    memmove(pch, pch+1, strlen(pch) -1);
                    pch[strlen(pch)-1] = '\0';
                }
            }
            else if (*pch == '|') {
                input.push_back("|");
                memmove(pch, pch+1, strlen(pch) -1);
                pch[strlen(pch) -1] = '\0';
            }
		    else {
			string word;
			int numletters = 0;

			char *z = pch;
			while (z!=a && z!=b && z!=c && z!=d && z!=e && z!=f) {
			    if (*z == '\0')
				break;
			    word += *z;
			    numletters++;
			    z++;
			}
			input.push_back(word);
			memmove(pch, pch+numletters, strlen(pch) -numletters);
			pch[strlen(pch)-numletters] = '\0';
		    }

		    a = strstr(pch, "&&");
		    b = strstr(pch, "||");
		    c = strstr(pch, ";");
            d = strstr(pch, "<");
            e = strstr(pch, ">");
            f = strstr(pch, "|");
		}
	    }

	    // If no connectors, just add to vector
	    if (*pch != '\0' && *pch != '\n' && *pch != '#')
		input.push_back(pch);
	    pch = strtok (NULL, " \n");
	}
}

void execute(const vector<string> & input, int start, int end) {

    //Call execvp, based on which elements in the string vector to use
    char * argv[5];

	    int i = 0;

	    for (i = 0; i <= (end - start); i++) {
		argv[i] = new char[5];
	    }

        //debug
        //cerr << "sent to execvp:\n";

	    for (i = 0; i < (end-start); i++) {
		strcpy(argv[i], input[i+start].c_str());
	    //cerr << input[i+start] << endl;
        }

        //debug
        //cerr << endl;

	    argv[i] = NULL;

	    int status = execvp(argv[0], argv);
	    if (status == -1)
		perror("execvp");
		exit(1);
}

int main() {

    vector<string> input;
    int status=0;

    int savestdin;
    if ((savestdin = dup(0)) == -1)
        perror("dup");

    int savestdout;
    if ((savestdout = dup(1)) == -1)
        perror("dup");

    // Get username
    char * usrname = getlogin();
    if (usrname == NULL){
	perror ("getlogin");
	exit(1);
    }

    // Get hostname
    char hostname[20];

    if (gethostname(hostname, sizeof hostname) ==-1) {
	perror("gethostname");
	exit(1);
    }

    // Main loop
    while (1) {

   	 //Restore stdin and stdout
        if ((dup2(savestdin,0)) == -1)
            perror("dup2");

        if ((dup2(savestdout,0)) == -1)
            perror("dup2");

	status = 0;

	if (input.size() != 0)
	    input.clear();

	cout << usrname << "@" << hostname <<"$ ";

	string string1;
	getline(cin, string1);
	char * line = new char [string1.length() + 1];
	strcpy(line, string1.c_str());

	parse(line, input);

	delete line;

	if (input.size() == 0)
	    continue;

    for (int i = 0; i < input.size(); i++) {
	    if (strcmp(input[i].c_str(), "exit") == 0) exit(0);
    }

	int pid=fork();
    if (pid == -1)
        perror ("fork");
	int pid2;
	if (pid == 0) {

	    int start = 0;
	    int end = input.size();
	    unsigned i;

loop:
	    end = input.size();

        for (i = start; i < input.size(); ) {
            //input output redirection
            if (input[i] == ">" || input[i] == ">>" || input[i]=="<" || input[i] == "|") {

                if (input[i] == ">") {

                        int fdo = open(input[i+1].c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
                        if (fdo==-1)
                            perror("open");

                        status = close(STDOUT_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdo)) == -1)
                            perror("dup");

                        if ((close(fdo)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i+2]=="<" || input[i+2] == "|")
                            continue;

                        end = i;
                        break;
                    }

                else if (input[i] == ">>") {

                        int fdo = open(input[i+1].c_str(), O_CREAT | O_WRONLY | O_APPEND,
                                     S_IRUSR | S_IWUSR);
                        if (fdo==-1)
                            perror("open");

                        status = close(STDOUT_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdo)) == -1)
                            perror("dup");

                        if ((close(fdo)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i+2]=="<" || input[i+2] == "|")
                            continue;

                        end = i;
                        break;
                }

                else if (input[i] == "<") {

                        int fdi = open(input[i+1].c_str(), O_RDONLY, 0);
                        if (fdi==-1)
                            perror("open");

                        status = close(STDIN_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdi)) == -1)
                            perror("dup");

                        if ((close(fdi)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i+2]=="<" || input[i+2] == "|")
                            continue;

                        end = i;
                        break;
                }

                else if (input[i] == "|") {
                    int pfd[2];

                    if ((pipe(pfd)) == -1)
                        perror("pipe");

                    int pid3 = fork();
                    if (pid3 == -1) {
                        perror("fork");
                        exit(1);
                    }
                    if (pid3==0) {
                        cout << "This is the child process";

                        if ((dup2(pfd[1], 1)) == -1)
                            perror("dup2");

                        if ((close(pfd[0])) == -1)
                            perror("close");

                        end = i;
                        break;

                    }
                    else {
                        close(STDIN_FILENO);
                        dup2(pfd[0], 0);
                        close(pfd[1]);

                        if (-1 == wait(0))
                            perror("wait");

                        start = i+1;
                        goto loop;

                    }

                }
            }

            else if (input[i] == ";" || input[i] == "&&" || input[i] == "||") {
		        string connector = input[i];

		        pid2 = fork();
		        if (pid2 == -1) {
			        perror("fork");
			        exit(1);
		        }
		        if (pid2!=0) {
			        if (-1 == wait(&status))
			            perror("wait");

			        if (connector == "&&" && status != 0)
			            exit(1);

			        if (connector == "||" && status == 0)
			            exit(0);

			        start = i + 1;
			        goto loop;

		        }
		        else {
			        end = i;
			        break;
		        }
		    }
	    i++;
        }

	    execute(input, start, end);

	}
	else {
	    status = wait(NULL);
	    if (status == -1)
		perror("wait");
	}
    }

    return 0;
}
<commit_msg>Fixed combining pipes and io redirection<commit_after>#include <iostream>
#include <unistd.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <vector>
#include <stdlib.h>
#include <fcntl.h>

using namespace std;

void parse(char * line, vector<string> & input) {

    char * pch;
	pch = strtok (line, " \n");
	while (pch!= NULL) {

	    // Ignore after comments
	    if (*pch == '#')
		break;

	    // Check for && and ||
	    // Break input up
	    char * a = strstr(pch, "&&");
	    char * b = strstr(pch, "||");
	    char * c = strstr(pch, ";");
        char * d = strstr(pch, "<");
        char * e = strstr(pch, ">");
        char * f = strstr(pch, "|");

	    // If there are connectors, break up the string
	    // into parts and add them individually to the vector
	    if (a!=NULL || b!=NULL || c!=NULL || d!=NULL || e!=NULL || f!=NULL) {
		while (strlen(pch) != 0 ) {

		    // Checks for && and ||
		    if ((pch[0] == '&' && pch[1] == '&') ||
			(pch[0] == '|' && pch[1] == '|')) {

			    string tmp;
			    tmp += *pch;
			    tmp += *(pch+1);
			    tmp[2] = '\0';

			    input.push_back(tmp);
			    memmove(pch, pch+2, strlen(pch) - 2);
			    pch[strlen(pch)-2] = '\0';
		    }
		    // Check for semicolons
		    else if (*pch == ';') {
			    input.push_back(";");
			    memmove(pch, pch+1, strlen(pch) -1);
			    pch[strlen(pch)-1] = '\0';
		    }
            // Check for input/output redirectors
            else if (*pch == '<') {
                input.push_back("<");
                memmove(pch, pch+1, strlen(pch) -1);
                pch[strlen(pch)-1] = '\0';
            }
            else if (*pch == '>') {
                if (*(pch+1) == '>') {
                    input.push_back(">>");
                    memmove(pch, pch+2, strlen(pch) -2);
                    pch[strlen(pch)-2] = '\0';
                }
                else {
                    input.push_back(">");
                    memmove(pch, pch+1, strlen(pch) -1);
                    pch[strlen(pch)-1] = '\0';
                }
            }
            else if (*pch == '|') {
                input.push_back("|");
                memmove(pch, pch+1, strlen(pch) -1);
                pch[strlen(pch) -1] = '\0';
            }
		    else {
			string word;
			int numletters = 0;

			char *z = pch;
			while (z!=a && z!=b && z!=c && z!=d && z!=e && z!=f) {
			    if (*z == '\0')
				break;
			    word += *z;
			    numletters++;
			    z++;
			}
			input.push_back(word);
			memmove(pch, pch+numletters, strlen(pch) -numletters);
			pch[strlen(pch)-numletters] = '\0';
		    }

		    a = strstr(pch, "&&");
		    b = strstr(pch, "||");
		    c = strstr(pch, ";");
            d = strstr(pch, "<");
            e = strstr(pch, ">");
            f = strstr(pch, "|");
		}
	    }

	    // If no connectors, just add to vector
	    if (*pch != '\0' && *pch != '\n' && *pch != '#')
		input.push_back(pch);
	    pch = strtok (NULL, " \n");
	}
}

void execute(const vector<string> & input, int start, int end) {

    //Call execvp, based on which elements in the string vector to use
    char * argv[5];

	    int i = 0;

	    for (i = 0; i <= (end - start); i++) {
		argv[i] = new char[5];
	    }

        //debug
        //cerr << "sent to execvp:\n";

	    for (i = 0; i < (end-start); i++) {
		strcpy(argv[i], input[i+start].c_str());
	    //cerr << input[i+start] << endl;
        }

        //debug
        //cerr << endl;

	    argv[i] = NULL;

	    int status = execvp(argv[0], argv);
	    if (status == -1)
		perror("execvp");
		exit(1);
}

int main() {

    vector<string> input;
    int status=0;

    int savestdin;
    if ((savestdin = dup(0)) == -1)
        perror("dup");

    int savestdout;
    if ((savestdout = dup(1)) == -1)
        perror("dup");

    // Get username
    char * usrname = getlogin();
    if (usrname == NULL){
	perror ("getlogin");
	exit(1);
    }

    // Get hostname
    char hostname[20];

    if (gethostname(hostname, sizeof hostname) ==-1) {
	perror("gethostname");
	exit(1);
    }

    // Main loop
    while (1) {

   	 //Restore stdin and stdout
        if ((dup2(savestdin,0)) == -1)
            perror("dup2");

        if ((dup2(savestdout,0)) == -1)
            perror("dup2");

	status = 0;

	if (input.size() != 0)
	    input.clear();

	cout << usrname << "@" << hostname <<"$ ";

	string string1;
	getline(cin, string1);
	char * line = new char [string1.length() + 1];
	strcpy(line, string1.c_str());

	parse(line, input);

	delete line;

	if (input.size() == 0)
	    continue;

    for (int i = 0; i < input.size(); i++) {
	    if (strcmp(input[i].c_str(), "exit") == 0) exit(0);
    }

	int pid=fork();
    if (pid == -1)
        perror ("fork");
	int pid2;
	if (pid == 0) {

	    int start = 0;
	    int end = input.size();
	    unsigned i;

loop:
	    end = input.size();

        for (i = start; i < input.size(); ) {
            //input output redirection
            if (input[i] == ">" || input[i] == ">>" || input[i]=="<" || input[i] == "|") {

                if (input[i] == ">") {

                        int fdo = open(input[i+1].c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
                        if (fdo==-1)
                            perror("open");

                        status = close(STDOUT_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdo)) == -1)
                            perror("dup");

                        if ((close(fdo)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i]=="<" || input[i] == "|")
                            continue;

                        end = i;
                        break;
                    }

                else if (input[i] == ">>") {

                        int fdo = open(input[i+1].c_str(), O_CREAT | O_WRONLY | O_APPEND,
                                     S_IRUSR | S_IWUSR);
                        if (fdo==-1)
                            perror("open");

                        status = close(STDOUT_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdo)) == -1)
                            perror("dup");

                        if ((close(fdo)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i]=="<" || input[i] == "|")
                            continue;

                        end = i;
                        break;
                }

                else if (input[i] == "<") {

                        int fdi = open(input[i+1].c_str(), O_RDONLY, 0);
                        if (fdi==-1)
                            perror("open");

                        status = close(STDIN_FILENO);
                        if (status == -1)
                            perror("close");

                        if ((dup(fdi)) == -1)
                            perror("dup");

                        if ((close(fdi)) == -1)
                            perror("close");

                        input.erase(input.begin() + i);

                        input.erase(input.begin() + i);

                        if (input[i] == ">" || input[i] == ">>" ||
                                        input[i]=="<" || input[i] == "|")
                            continue;

                        end = i;
                        break;
                }

                else if (input[i] == "|") {
                    int pfd[2];

                    if ((pipe(pfd)) == -1)
                        perror("pipe");

                    int pid3 = fork();
                    if (pid3 == -1) {
                        perror("fork");
                        exit(1);
                    }
                    if (pid3==0) {
                        cout << "This is the child process";

                        if ((dup2(pfd[1], 1)) == -1)
                            perror("dup2");

                        if ((close(pfd[0])) == -1)
                            perror("close");

                        end = i;
                        break;

                    }
                    else {
                        close(STDIN_FILENO);
                        dup2(pfd[0], 0);
                        close(pfd[1]);

                        if (-1 == wait(0))
                            perror("wait");

                        start = i+1;
                        goto loop;

                    }

                }
            }

            else if (input[i] == ";" || input[i] == "&&" || input[i] == "||") {
		        string connector = input[i];

		        pid2 = fork();
		        if (pid2 == -1) {
			        perror("fork");
			        exit(1);
		        }
		        if (pid2!=0) {
			        if (-1 == wait(&status))
			            perror("wait");

			        if (connector == "&&" && status != 0)
			            exit(1);

			        if (connector == "||" && status == 0)
			            exit(0);

			        start = i + 1;
			        goto loop;

		        }
		        else {
			        end = i;
			        break;
		        }
		    }
	    i++;
        }

	    execute(input, start, end);

	}
	else {
	    status = wait(NULL);
	    if (status == -1)
		perror("wait");
	}
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <memory>
#include <algorithm>
#include <iterator>
// #include <iostream>

#include "s_rules.hh"
#include "s_closure.hh"
#include "cons_util.hh"
#include "env.hh"
#include "zs_error.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_util.hh"
#include "printer.hh"

using namespace std;

namespace {

Lisp_ptr pick_first(Lisp_ptr p){
  if(p.tag() == Ptr_tag::cons){
    auto c = p.get<Cons*>();
    if(!c) throw zs_error("syntax-rules: the pattern is empty list\n");

    return c->car();
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();
    assert(v);
    if(v->empty()) throw zs_error("syntax-rules: the pattern is empty vector\n");

    return (*v)[0];
  }else{
    throw zs_error("syntax-rules: informal pattern passed! (%s)\n", stringify(p.tag()));
  }
}

} // namespace

namespace Procedure{

constexpr ProcInfo SyntaxRules::sr_procinfo;

SyntaxRules::SyntaxRules(Env* e, Lisp_ptr lits, Lisp_ptr rules)
  : env_(e), literals_(), rules_(){
  for(auto i : lits){
    if(!identifierp(i))
      throw builtin_identifier_check_failed("syntax-rules", i);

    literals_.push_back(i);
  }
  literals_.shrink_to_fit();

  for(auto i : rules){
    bind_cons_list_strict
      (i,
       [&](Lisp_ptr pat, Lisp_ptr tmpl){
        // checks forms
        pick_first(pat);
        pick_first(tmpl);

        rules_.push_back({pat, tmpl});
      });
  }
  rules_.shrink_to_fit();
}

SyntaxRules::~SyntaxRules() = default;

std::pair<Env*, Lisp_ptr> SyntaxRules::match(Lisp_ptr form, Env* form_env) const{
  // check form
  pick_first(form);

  static constexpr auto env_cleaner = [](Env* e){
    e->visit_map([](Env::map_type& map){
        for(auto i : map){
          if(auto sc = i.second.get<SyntacticClosure*>()){
            delete sc;
          }
        }
        map.clear();
      });
  };

  static constexpr auto env_deleter = [&](Env* e){
    env_cleaner(e);
    delete e;
  };

  unique_ptr<Env, decltype(env_deleter)> env{env_->push(), env_deleter};

  for(auto i : rules_){
    auto ignore_ident = pick_first(i.first);
    if(try_match_1(env.get(), i.first, form, form_env, ignore_ident)){
      return {env.release(), i.second};
    }else{
      env_cleaner(env.get());
    }
  }

  throw zs_error("syntax-rules error: no matching pattern found!\n");
}

bool SyntaxRules::try_match_1(Env* env, Lisp_ptr pattern,
                              Lisp_ptr form, Env* form_env,
                              Lisp_ptr ignore_ident) const{
  static const auto check_duplicate = [env](Lisp_ptr ident){
    assert(identifierp(ident));

    env->visit_map([&ident](const Env::map_type& map){
        if(map.find(ident) != map.end()){
          throw zs_error("syntax-rules error: duplicated pattern variable! (%s)\n",
                         identifier_symbol(ident)->name().c_str());
        }
      });
  };

  // cout << __func__ << endl;
  // cout << "pattern " << pattern << ", form " << form << endl;

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(pattern)){
    if(find(begin(literals_), end(literals_), pattern) != end(literals_)){
      // literal identifier
      if(!identifierp(form)) return false;

      return identifier_eq(this->env_, pattern, form_env, form);
    }else{
      // non-literal identifier
      if(pattern != ignore_ident){
        check_duplicate(pattern);
        env->local_set(pattern, new SyntacticClosure(form_env, nullptr, form));
      }
      return true;
    }
  }else if(pattern.tag() == Ptr_tag::cons){
    if(form.tag() != Ptr_tag::cons)
      return false;

    if(nullp(pattern) && nullp(form)){
      return true;
    }

    auto p_i = begin(pattern), p_e = end(pattern);
    auto f_i = begin(form), f_e = end(form);

    for(; p_i != p_e; ++p_i, (f_i ? ++f_i : f_i)){
      auto p_n = next(p_i);

      // checks ellipsis
      if(identifierp(*p_i)
         && (p_n != p_e) && identifierp(*p_n)
         && identifier_symbol(*p_n) == ellipsis_sym){
        if(p_i == begin(pattern)){
          throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
        }

        if(!nullp(p_e.base())){
          throw zs_error("syntax-rules error: '...' is appeared in a inproper list pattern!\n");
        }

        if(!nullp(f_e.base())){
          throw zs_error("syntax-rules error: '...' is used for a inproper list form!\n");
        }

        check_duplicate(*p_i);
        env->local_set(*p_i, f_i.base());
        return true;
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(env, *p_i, *f_i, form_env, ignore_ident)){
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return try_match_1(env, p_i.base(), f_i.base(), form_env, ignore_ident);
    }else{
      return false;
    }
  }else if(pattern.tag() == Ptr_tag::vector){
    if(form.tag() != Ptr_tag::vector)
      return false;

    auto p_v = pattern.get<Vector*>();
    auto f_v = form.get<Vector*>();

    auto p_i = begin(*p_v), p_e = end(*p_v);
    auto f_i = begin(*f_v), f_e = end(*f_v);

    for(; p_i != p_e; ++p_i, ++f_i){
      auto p_n = next(p_i);

      // checks ellipsis
      if(identifierp(*p_i)
         && (p_n != p_e) && identifierp(*p_n)
         && identifier_symbol(*p_n) == ellipsis_sym){
        if(p_i == begin(*p_v)){
          throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
        }

        check_duplicate(*p_i);
        env->local_set(*p_i, new Vector(f_i, f_e));
        return true;
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(env, *p_i, *f_i, form_env, ignore_ident)){
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return true;
    }else{
      return false;
    }
  }else{
    return equal_internal(pattern, form);
  }
}

} // Procedure
<commit_msg>removed wrong check in syntax-rule<commit_after>#include <memory>
#include <algorithm>
#include <iterator>

#include "s_rules.hh"
#include "s_closure.hh"
#include "cons_util.hh"
#include "env.hh"
#include "zs_error.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_util.hh"
#include "printer.hh"

// #include <iostream>
// #include "env.hh"

using namespace std;

namespace {

Lisp_ptr pick_first(Lisp_ptr p){
  if(p.tag() == Ptr_tag::cons){
    auto c = p.get<Cons*>();
    if(!c) throw zs_error("syntax-rules: the pattern is empty list\n");

    return c->car();
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();
    assert(v);
    if(v->empty()) throw zs_error("syntax-rules: the pattern is empty vector\n");

    return (*v)[0];
  }else{
    throw zs_error("syntax-rules: informal pattern passed! (%s)\n", stringify(p.tag()));
  }
}

} // namespace

namespace Procedure{

constexpr ProcInfo SyntaxRules::sr_procinfo;

SyntaxRules::SyntaxRules(Env* e, Lisp_ptr lits, Lisp_ptr rules)
  : env_(e), literals_(), rules_(){
  for(auto i : lits){
    if(!identifierp(i))
      throw builtin_identifier_check_failed("syntax-rules", i);

    literals_.push_back(i);
  }
  literals_.shrink_to_fit();

  for(auto i : rules){
    bind_cons_list_strict
      (i,
       [&](Lisp_ptr pat, Lisp_ptr tmpl){
        // checks forms
        pick_first(pat);

        rules_.push_back({pat, tmpl});
      });
  }
  rules_.shrink_to_fit();
}

SyntaxRules::~SyntaxRules() = default;

std::pair<Env*, Lisp_ptr> SyntaxRules::match(Lisp_ptr form, Env* form_env) const{
  // check form
  pick_first(form);

  static constexpr auto env_cleaner = [](Env* e){
    e->visit_map([](Env::map_type& map){
        for(auto i : map){
          if(auto sc = i.second.get<SyntacticClosure*>()){
            delete sc;
          }
        }
        map.clear();
      });
  };

  static constexpr auto env_deleter = [&](Env* e){
    env_cleaner(e);
    delete e;
  };

  unique_ptr<Env, decltype(env_deleter)> env{env_->push(), env_deleter};

  for(auto i : rules_){
    auto ignore_ident = pick_first(i.first);
    if(try_match_1(env.get(), i.first, form, form_env, ignore_ident)){
      return {env.release(), i.second};
    }else{
      env_cleaner(env.get());
    }
  }

  throw zs_error("syntax-rules error: no matching pattern found!\n");
}

bool SyntaxRules::try_match_1(Env* env, Lisp_ptr pattern,
                              Lisp_ptr form, Env* form_env,
                              Lisp_ptr ignore_ident) const{
  static const auto check_duplicate = [env](Lisp_ptr ident){
    assert(identifierp(ident));

    env->visit_map([&](const Env::map_type& map){
        if(map.find(ident) != map.end()){
          // cout << "### env: " << env << endl;
          // cout << ident << " = " << map.find(ident)->second << endl;
          throw zs_error("syntax-rules error: duplicated pattern variable! (%s)\n",
                         identifier_symbol(ident)->name().c_str());
        }
      });
  };

  // cout << __func__ << endl;
  // cout << "pattern " << pattern << ", form " << form << endl;

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(pattern)){
    if(find(begin(literals_), end(literals_), pattern) != end(literals_)){
      // literal identifier
      if(!identifierp(form)) return false;

      return identifier_eq(this->env_, pattern, form_env, form);
    }else{
      // non-literal identifier
      if(pattern != ignore_ident){
        check_duplicate(pattern);
        env->local_set(pattern, new SyntacticClosure(form_env, nullptr, form));
      }
      return true;
    }
  }else if(pattern.tag() == Ptr_tag::cons){
    if(form.tag() != Ptr_tag::cons)
      return false;

    if(nullp(pattern) && nullp(form)){
      return true;
    }

    auto p_i = begin(pattern), p_e = end(pattern);
    auto f_i = begin(form), f_e = end(form);

    for(; p_i != p_e; ++p_i, (f_i ? ++f_i : f_i)){
      auto p_n = next(p_i);

      // checks ellipsis
      if(identifierp(*p_i)
         && (p_n != p_e) && identifierp(*p_n)
         && identifier_symbol(*p_n) == ellipsis_sym){
        if(p_i == begin(pattern)){
          throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
        }

        if(!nullp(p_e.base())){
          throw zs_error("syntax-rules error: '...' is appeared in a inproper list pattern!\n");
        }

        if(!nullp(f_e.base())){
          throw zs_error("syntax-rules error: '...' is used for a inproper list form!\n");
        }

        check_duplicate(*p_i);
        env->local_set(*p_i, f_i.base());
        return true;
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(env, *p_i, *f_i, form_env, ignore_ident)){
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return try_match_1(env, p_i.base(), f_i.base(), form_env, ignore_ident);
    }else{
      return false;
    }
  }else if(pattern.tag() == Ptr_tag::vector){
    if(form.tag() != Ptr_tag::vector)
      return false;

    auto p_v = pattern.get<Vector*>();
    auto f_v = form.get<Vector*>();

    auto p_i = begin(*p_v), p_e = end(*p_v);
    auto f_i = begin(*f_v), f_e = end(*f_v);

    for(; p_i != p_e; ++p_i, ++f_i){
      auto p_n = next(p_i);

      // checks ellipsis
      if(identifierp(*p_i)
         && (p_n != p_e) && identifierp(*p_n)
         && identifier_symbol(*p_n) == ellipsis_sym){
        if(p_i == begin(*p_v)){
          throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
        }

        check_duplicate(*p_i);
        env->local_set(*p_i, new Vector(f_i, f_e));
        return true;
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(env, *p_i, *f_i, form_env, ignore_ident)){
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return true;
    }else{
      return false;
    }
  }else{
    return equal_internal(pattern, form);
  }
}

} // Procedure
<|endoftext|>


<commit_before>#include <curses.h>
#include <panel.h>

int main(int argc, char** argv)
{
    WINDOW w;
    SCREEN s;
    PANEL p;
    return 0;
}

<commit_msg>fix warnings<commit_after>#include <curses.h>
#include <panel.h>

int main(int argc, char** argv)
{
    WINDOW w;
    PANEL p;
    (void)(w);
    (void)(p);
    (void)(argc);
    (void)(argv);
    return 0;
}

<|endoftext|>


<commit_before>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string>
#include <vector>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "sandbox.h"

using namespace std;

static const uint32_t STACK_SIZE = 64 * 1024;

bool loadRawData(machine& mach, const string& filename)
{
	// open and mmap input file
	mfile pf(filename);
	if (!pf.open(O_RDONLY))
		return false;

	static unsigned int dataCount = 0;
	char tmpstr[32];

	// alloc new data memory range
	sprintf(tmpstr, "data%u", dataCount++);
	size_t sz = pf.st.st_size;
	addressRange *rdr = new addressRange(tmpstr, sz);

	// copy mmap'd data into local buffer
	rdr->buf.assign((char *) pf.data, sz);
	rdr->updateRoot();

	// add to global memory map
	return mach.mapInsert(rdr);
}

static void usage(const char *progname)
{
	fprintf(stderr,
		"Usage: %s [options]\n"
		"\n"
		"options:\n"
		"-E <directory>\t\tAdd to executable hash search path list\n"
		"-e <hash|pathname>\tLoad specified Moxie executable into address space\n"
		"-D <directory>\t\tAdd to data hash search path list\n"
		"-d <file>\t\tLoad data into address space\n"
		"-o <file>\t\tOutput data to <file>.  \"-\" for stdout\n"
		"-t\t\t\tEnabling simulator tracing\n"
		,
		progname);
}

static void printMemMap(machine &mach)
{
	for (unsigned int i = 0; i < mach.memmap.size(); i++) {
		addressRange *ar = mach.memmap[i];
		fprintf(stderr, "%s %08x-%08x %s\n",
			ar->readOnly ? "ro" : "rw", ar->start, ar->end,
			ar->name.c_str());
	}
}

static void addStackMem(machine& mach)
{
	// alloc r/w memory range
	addressRange *rdr = new addressRange("stack", STACK_SIZE);

	rdr->buf.resize(STACK_SIZE);
	rdr->updateRoot();
	rdr->readOnly = false;

	// add memory range to global memory map
	mach.mapInsert(rdr);

	// set SR #7 to now-initialized stack vaddr
	mach.cpu.asregs.sregs[7] = rdr->end;
}

static void addMapDescriptor(machine& mach)
{
	// fill list from existing memory map
	vector<struct mach_memmap_ent> desc;
	mach.fillDescriptors(desc);

	// add entry for the mapdesc range to be added to memory map
	struct mach_memmap_ent mme_self;
	memset(&mme_self, 0, sizeof(mme_self));
	desc.push_back(mme_self);

	// add blank entry for list terminator
	struct mach_memmap_ent mme_end;
	memset(&mme_end, 0, sizeof(mme_end));
	desc.push_back(mme_end);

	// calc total region size
	size_t sz = sizeof(mme_end) * desc.size();

	// manually fill in mapdesc range descriptor
	mme_self.length = sz;
	strcpy(mme_self.tags, "ro,mapdesc,");

	// build entry for global memory map
	addressRange *ar = new addressRange("mapdesc", sz);

	// allocate space for descriptor array
	ar->buf.resize(sz);
	ar->updateRoot();

	// copy 'desc' array into allocated memory space
	unsigned int i = 0;
	for (vector<struct mach_memmap_ent>::iterator it = desc.begin();
	     it != desc.end(); it++, i++) {
		struct mach_memmap_ent& mme = (*it);
		memcpy(&ar->buf[i * sizeof(mme)], &mme, sizeof(mme));
	}

	// add memory range to global memory map
	mach.mapInsert(ar);

	// set SR #6 to now-initialized mapdesc start vaddr
	mach.cpu.asregs.sregs[6] = ar->start;
}

static void gatherOutput(machine& mach, const string& outFilename)
{
	if (!outFilename.size())
		return;

	uint32_t vaddr = mach.cpu.asregs.sregs[6];
	uint32_t length = mach.cpu.asregs.sregs[7];
	if (!vaddr || !length)
		return;

	char *p = (char *) mach.physaddr(vaddr, length);
	if (!p) {
		fprintf(stderr, "Sim exception %d (%s) upon output\n",
			SIGBUS,
			strsignal(SIGBUS));
		exit(EXIT_FAILURE);
	}

	int fd;
	if (outFilename == "-") {
		fd = STDOUT_FILENO;
	} else {
		fd = open(outFilename.c_str(),
			  O_WRONLY | O_CREAT | O_TRUNC, 0666);
		if (fd < 0) {
			perror(outFilename.c_str());
			exit(EXIT_FAILURE);
		}
	}

	while (length > 0) {
		ssize_t bytes = write(fd, p, length);
		if (bytes < 0) {
			perror(outFilename.c_str());
			exit(EXIT_FAILURE);
		}

		length -= bytes;
		p += bytes;
	}

	close(fd);
}

static bool isDir(const char *pathname)
{
	struct stat st;

	if (stat(pathname, &st) < 0)
		return false;

	return S_ISDIR(st.st_mode);
}

int main (int argc, char *argv[])
{
	machine mach;

	vector<string> pathExec;
	vector<string> pathData;

	bool progLoaded = false;
	string outFilename;
	int opt;
	while ((opt = getopt(argc, argv, "E:e:D:d:o:t")) != -1) {
		switch(opt) {
		case 'E':
			if (!isDir(optarg)) {
				fprintf(stderr, "%s not a directory\n", optarg);
				exit(EXIT_FAILURE);
			}
			pathExec.push_back(optarg);
			break;
		case 'e':
			bool rc;
			if (IsHex(optarg))
				rc = loadElfHash(mach, optarg, pathExec);
			else
				rc = loadElfProgram(mach, optarg);
			if (!rc) {
				fprintf(stderr, "ELF load failed for %s\n",
					optarg);
				exit(EXIT_FAILURE);
			}
			progLoaded = true;
			break;
		case 'D':
			if (!isDir(optarg)) {
				fprintf(stderr, "%s not a directory\n", optarg);
				exit(EXIT_FAILURE);
			}
			pathExec.push_back(optarg);
			break;
		case 'd':
			if (!loadRawData(mach, optarg)) {
				fprintf(stderr, "Data load failed for %s\n",
					optarg);
				exit(EXIT_FAILURE);
			}
			break;

		case 'o':
			outFilename = optarg;
			break;

		case 't':
			mach.tracing = true;
			break;

		default:
			usage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}

	if (!progLoaded) {
		fprintf(stderr, "No Moxie program loaded.\n");
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	addStackMem(mach);
	addMapDescriptor(mach);

	printMemMap(mach);

	mach.cpu.asregs.regs[PC_REGNO] = mach.startAddr;
	sim_resume(mach);

	if (mach.cpu.asregs.exception != SIGQUIT) {
		fprintf(stderr, "Sim exception %d (%s)\n",
			mach.cpu.asregs.exception,
			strsignal(mach.cpu.asregs.exception));
		exit(EXIT_FAILURE);
	}

	gatherOutput(mach, outFilename);

	// return $r0, the exit status passed to _exit()
	return mach.cpu.asregs.regs[2];
}

<commit_msg>sandbox: -D should fill pathData array<commit_after>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string>
#include <vector>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "sandbox.h"

using namespace std;

static const uint32_t STACK_SIZE = 64 * 1024;

bool loadRawData(machine& mach, const string& filename)
{
	// open and mmap input file
	mfile pf(filename);
	if (!pf.open(O_RDONLY))
		return false;

	static unsigned int dataCount = 0;
	char tmpstr[32];

	// alloc new data memory range
	sprintf(tmpstr, "data%u", dataCount++);
	size_t sz = pf.st.st_size;
	addressRange *rdr = new addressRange(tmpstr, sz);

	// copy mmap'd data into local buffer
	rdr->buf.assign((char *) pf.data, sz);
	rdr->updateRoot();

	// add to global memory map
	return mach.mapInsert(rdr);
}

static void usage(const char *progname)
{
	fprintf(stderr,
		"Usage: %s [options]\n"
		"\n"
		"options:\n"
		"-E <directory>\t\tAdd to executable hash search path list\n"
		"-e <hash|pathname>\tLoad specified Moxie executable into address space\n"
		"-D <directory>\t\tAdd to data hash search path list\n"
		"-d <file>\t\tLoad data into address space\n"
		"-o <file>\t\tOutput data to <file>.  \"-\" for stdout\n"
		"-t\t\t\tEnabling simulator tracing\n"
		,
		progname);
}

static void printMemMap(machine &mach)
{
	for (unsigned int i = 0; i < mach.memmap.size(); i++) {
		addressRange *ar = mach.memmap[i];
		fprintf(stderr, "%s %08x-%08x %s\n",
			ar->readOnly ? "ro" : "rw", ar->start, ar->end,
			ar->name.c_str());
	}
}

static void addStackMem(machine& mach)
{
	// alloc r/w memory range
	addressRange *rdr = new addressRange("stack", STACK_SIZE);

	rdr->buf.resize(STACK_SIZE);
	rdr->updateRoot();
	rdr->readOnly = false;

	// add memory range to global memory map
	mach.mapInsert(rdr);

	// set SR #7 to now-initialized stack vaddr
	mach.cpu.asregs.sregs[7] = rdr->end;
}

static void addMapDescriptor(machine& mach)
{
	// fill list from existing memory map
	vector<struct mach_memmap_ent> desc;
	mach.fillDescriptors(desc);

	// add entry for the mapdesc range to be added to memory map
	struct mach_memmap_ent mme_self;
	memset(&mme_self, 0, sizeof(mme_self));
	desc.push_back(mme_self);

	// add blank entry for list terminator
	struct mach_memmap_ent mme_end;
	memset(&mme_end, 0, sizeof(mme_end));
	desc.push_back(mme_end);

	// calc total region size
	size_t sz = sizeof(mme_end) * desc.size();

	// manually fill in mapdesc range descriptor
	mme_self.length = sz;
	strcpy(mme_self.tags, "ro,mapdesc,");

	// build entry for global memory map
	addressRange *ar = new addressRange("mapdesc", sz);

	// allocate space for descriptor array
	ar->buf.resize(sz);
	ar->updateRoot();

	// copy 'desc' array into allocated memory space
	unsigned int i = 0;
	for (vector<struct mach_memmap_ent>::iterator it = desc.begin();
	     it != desc.end(); it++, i++) {
		struct mach_memmap_ent& mme = (*it);
		memcpy(&ar->buf[i * sizeof(mme)], &mme, sizeof(mme));
	}

	// add memory range to global memory map
	mach.mapInsert(ar);

	// set SR #6 to now-initialized mapdesc start vaddr
	mach.cpu.asregs.sregs[6] = ar->start;
}

static void gatherOutput(machine& mach, const string& outFilename)
{
	if (!outFilename.size())
		return;

	uint32_t vaddr = mach.cpu.asregs.sregs[6];
	uint32_t length = mach.cpu.asregs.sregs[7];
	if (!vaddr || !length)
		return;

	char *p = (char *) mach.physaddr(vaddr, length);
	if (!p) {
		fprintf(stderr, "Sim exception %d (%s) upon output\n",
			SIGBUS,
			strsignal(SIGBUS));
		exit(EXIT_FAILURE);
	}

	int fd;
	if (outFilename == "-") {
		fd = STDOUT_FILENO;
	} else {
		fd = open(outFilename.c_str(),
			  O_WRONLY | O_CREAT | O_TRUNC, 0666);
		if (fd < 0) {
			perror(outFilename.c_str());
			exit(EXIT_FAILURE);
		}
	}

	while (length > 0) {
		ssize_t bytes = write(fd, p, length);
		if (bytes < 0) {
			perror(outFilename.c_str());
			exit(EXIT_FAILURE);
		}

		length -= bytes;
		p += bytes;
	}

	close(fd);
}

static bool isDir(const char *pathname)
{
	struct stat st;

	if (stat(pathname, &st) < 0)
		return false;

	return S_ISDIR(st.st_mode);
}

int main (int argc, char *argv[])
{
	machine mach;

	vector<string> pathExec;
	vector<string> pathData;

	bool progLoaded = false;
	string outFilename;
	int opt;
	while ((opt = getopt(argc, argv, "E:e:D:d:o:t")) != -1) {
		switch(opt) {
		case 'E':
			if (!isDir(optarg)) {
				fprintf(stderr, "%s not a directory\n", optarg);
				exit(EXIT_FAILURE);
			}
			pathExec.push_back(optarg);
			break;
		case 'e':
			bool rc;
			if (IsHex(optarg))
				rc = loadElfHash(mach, optarg, pathExec);
			else
				rc = loadElfProgram(mach, optarg);
			if (!rc) {
				fprintf(stderr, "ELF load failed for %s\n",
					optarg);
				exit(EXIT_FAILURE);
			}
			progLoaded = true;
			break;
		case 'D':
			if (!isDir(optarg)) {
				fprintf(stderr, "%s not a directory\n", optarg);
				exit(EXIT_FAILURE);
			}
			pathData.push_back(optarg);
			break;
		case 'd':
			if (!loadRawData(mach, optarg)) {
				fprintf(stderr, "Data load failed for %s\n",
					optarg);
				exit(EXIT_FAILURE);
			}
			break;

		case 'o':
			outFilename = optarg;
			break;

		case 't':
			mach.tracing = true;
			break;

		default:
			usage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}

	if (!progLoaded) {
		fprintf(stderr, "No Moxie program loaded.\n");
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	addStackMem(mach);
	addMapDescriptor(mach);

	printMemMap(mach);

	mach.cpu.asregs.regs[PC_REGNO] = mach.startAddr;
	sim_resume(mach);

	if (mach.cpu.asregs.exception != SIGQUIT) {
		fprintf(stderr, "Sim exception %d (%s)\n",
			mach.cpu.asregs.exception,
			strsignal(mach.cpu.asregs.exception));
		exit(EXIT_FAILURE);
	}

	gatherOutput(mach, outFilename);

	// return $r0, the exit status passed to _exit()
	return mach.cpu.asregs.regs[2];
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_SCHEMA_HPP
#define REALM_SCHEMA_HPP

#include <string>
#include <vector>

namespace realm {
class SchemaChange;
class ObjectSchema;
struct Property;

class Schema : private std::vector<ObjectSchema> {
private:
    using base = std::vector<ObjectSchema>;
public:
    Schema();
    ~Schema();
    // Create a schema from a vector of ObjectSchema
    Schema(base types);
    Schema(std::initializer_list<ObjectSchema> types);

    Schema(Schema const&);
    Schema(Schema &&);
    Schema& operator=(Schema const&);
    Schema& operator=(Schema&&);

    // find an ObjectSchema by name
    iterator find(std::string const& name);
    const_iterator find(std::string const& name) const;

    // find an ObjectSchema with the same name as the passed in one
    iterator find(ObjectSchema const& object) noexcept;
    const_iterator find(ObjectSchema const& object) const noexcept;

    // Verify that this schema is internally consistent (i.e. all properties are
    // valid, links link to types that actually exist, etc.)
    void validate() const;

    // Get the changes which must be applied to this schema to produce the passed-in schema
    std::vector<SchemaChange> compare(Schema const&) const;

    void copy_table_columns_from(Schema const&);

    friend bool operator==(Schema const&, Schema const&);

    using base::iterator;
    using base::const_iterator;
    using base::begin;
    using base::end;
    using base::empty;
    using base::size;
};

namespace schema_change {
    struct AddTable {
        const ObjectSchema* object;
    };

    struct AddProperty {
        const ObjectSchema* object;
        const Property* property;
    };

    struct RemoveProperty {
        const ObjectSchema* object;
        const Property* property;
    };

    struct ChangePropertyType {
        const ObjectSchema* object;
        const Property* old_property;
        const Property* new_property;
    };

    struct MakePropertyNullable {
        const ObjectSchema* object;
        const Property* property;
    };

    struct MakePropertyRequired {
        const ObjectSchema* object;
        const Property* property;
    };

    struct AddIndex {
        const ObjectSchema* object;
        const Property* property;
    };

    struct RemoveIndex {
        const ObjectSchema* object;
        const Property* property;
    };

    struct ChangePrimaryKey {
        const ObjectSchema* object;
        const Property* property;
    };
}

#define REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(macro) \
    macro(AddTable) \
    macro(AddProperty) \
    macro(RemoveProperty) \
    macro(ChangePropertyType) \
    macro(MakePropertyNullable) \
    macro(MakePropertyRequired) \
    macro(AddIndex) \
    macro(RemoveIndex) \
    macro(ChangePrimaryKey) \

class SchemaChange {
public:
#define REALM_SCHEMA_CHANGE_CONSTRUCTOR(name) \
    SchemaChange(schema_change::name value) : m_kind(Kind::name) { name = value; }
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SCHEMA_CHANGE_CONSTRUCTOR)
#undef REALM_SCHEMA_CHANGE_CONSTRUCTOR

    template<typename Visitor>
    auto visit(Visitor&& visitor) const {
        switch (m_kind) {
#define REALM_SWITCH_CASE(name) case Kind::name: return visitor(name);
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SWITCH_CASE)
#undef REALM_SWITCH_CASE
        }
    }

    friend bool operator==(SchemaChange const& lft, SchemaChange const& rgt);
private:
    enum class Kind {
#define REALM_SCHEMA_CHANGE_TYPE(name) name,
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SCHEMA_CHANGE_TYPE)
#undef REALM_SCHEMA_CHANGE_TYPE

    } m_kind;
    union {
#define REALM_DEFINE_FIELD(name) schema_change::name name;
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_DEFINE_FIELD)
#undef REALM_DEFINE_FIELD
    };
};

#undef REALM_FOR_EACH_SCHEMA_CHANGE_TYPE
}

#endif /* defined(REALM_SCHEMA_HPP) */
<commit_msg>Unindent the schema_change namespace<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_SCHEMA_HPP
#define REALM_SCHEMA_HPP

#include <string>
#include <vector>

namespace realm {
class SchemaChange;
class ObjectSchema;
struct Property;

class Schema : private std::vector<ObjectSchema> {
private:
    using base = std::vector<ObjectSchema>;
public:
    Schema();
    ~Schema();
    // Create a schema from a vector of ObjectSchema
    Schema(base types);
    Schema(std::initializer_list<ObjectSchema> types);

    Schema(Schema const&);
    Schema(Schema &&);
    Schema& operator=(Schema const&);
    Schema& operator=(Schema&&);

    // find an ObjectSchema by name
    iterator find(std::string const& name);
    const_iterator find(std::string const& name) const;

    // find an ObjectSchema with the same name as the passed in one
    iterator find(ObjectSchema const& object) noexcept;
    const_iterator find(ObjectSchema const& object) const noexcept;

    // Verify that this schema is internally consistent (i.e. all properties are
    // valid, links link to types that actually exist, etc.)
    void validate() const;

    // Get the changes which must be applied to this schema to produce the passed-in schema
    std::vector<SchemaChange> compare(Schema const&) const;

    void copy_table_columns_from(Schema const&);

    friend bool operator==(Schema const&, Schema const&);

    using base::iterator;
    using base::const_iterator;
    using base::begin;
    using base::end;
    using base::empty;
    using base::size;
};

namespace schema_change {
struct AddTable {
    const ObjectSchema* object;
};

struct AddProperty {
    const ObjectSchema* object;
    const Property* property;
};

struct RemoveProperty {
    const ObjectSchema* object;
    const Property* property;
};

struct ChangePropertyType {
    const ObjectSchema* object;
    const Property* old_property;
    const Property* new_property;
};

struct MakePropertyNullable {
    const ObjectSchema* object;
    const Property* property;
};

struct MakePropertyRequired {
    const ObjectSchema* object;
    const Property* property;
};

struct AddIndex {
    const ObjectSchema* object;
    const Property* property;
};

struct RemoveIndex {
    const ObjectSchema* object;
    const Property* property;
};

struct ChangePrimaryKey {
    const ObjectSchema* object;
    const Property* property;
};
}

#define REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(macro) \
    macro(AddTable) \
    macro(AddProperty) \
    macro(RemoveProperty) \
    macro(ChangePropertyType) \
    macro(MakePropertyNullable) \
    macro(MakePropertyRequired) \
    macro(AddIndex) \
    macro(RemoveIndex) \
    macro(ChangePrimaryKey) \

class SchemaChange {
public:
#define REALM_SCHEMA_CHANGE_CONSTRUCTOR(name) \
    SchemaChange(schema_change::name value) : m_kind(Kind::name) { name = value; }
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SCHEMA_CHANGE_CONSTRUCTOR)
#undef REALM_SCHEMA_CHANGE_CONSTRUCTOR

    template<typename Visitor>
    auto visit(Visitor&& visitor) const {
        switch (m_kind) {
#define REALM_SWITCH_CASE(name) case Kind::name: return visitor(name);
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SWITCH_CASE)
#undef REALM_SWITCH_CASE
        }
    }

    friend bool operator==(SchemaChange const& lft, SchemaChange const& rgt);
private:
    enum class Kind {
#define REALM_SCHEMA_CHANGE_TYPE(name) name,
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_SCHEMA_CHANGE_TYPE)
#undef REALM_SCHEMA_CHANGE_TYPE

    } m_kind;
    union {
#define REALM_DEFINE_FIELD(name) schema_change::name name;
        REALM_FOR_EACH_SCHEMA_CHANGE_TYPE(REALM_DEFINE_FIELD)
#undef REALM_DEFINE_FIELD
    };
};

#undef REALM_FOR_EACH_SCHEMA_CHANGE_TYPE
}

#endif /* defined(REALM_SCHEMA_HPP) */
<|endoftext|>