/** * Running the shell, cool stuff happens here */ void runShell(char ** argv) { //loop char *String = malloc(200); printf("Dat Bash $"); //run shell while (scanf(" %199[^\n]s", String)) { if (strcmp(String, "quit") == 0) { break; } int h; int g; char ** pipedCommands = parse(String, '|'); int pipes =0; for (int i =0; i < strlen(String); i++) { if(String[i] == '|') { pipes++; } } // printf("pipes = %i\n", pipes); char **st = malloc((sizeof(char *)) * (pipes +1)); char ***parameters = malloc(sizeof(char *) * (pipes +1)); for(int i= 0; pipedCommands[i] != NULL; i++) { h =0; g=0; while (pipedCommands[i][g] != '|' && pipedCommands[i][g] != 0) { g++; } char ** commands = malloc(g+1); //check command for parameter while (pipedCommands[i][h] != ' ' && pipedCommands[i][h] != 0) { h++; } commands[i] = malloc(h + 1); for (int l = 0; l < h; ++l) { commands[i][l] = pipedCommands[i][l]; } commands[i][h] = 0; //find the longest path variable int lv = 0; int envVariables =0; for (int j = 0; argv[j] != NULL; j++) { if (strlen(argv[j]) > lv) { lv = strlen(argv[j]); envVariables++; } } st[i] = malloc(strlen(commands[i]) + 2 + lv); bool f = false; for (int k = 0; argv[k] != NULL; k++) { char *a = malloc(strlen(argv[k]) * 10); for (int j = 0; j < strlen(argv[k]); j++) { a[j] = argv[k][j]; } //find the commands path char *s = strcat(a, "/"); st[i] = strcat(s, commands[i]); if (file_exist(st[i])) { printf("Found \'%s\'!\n", st[i]); f = true; break; } } if(!f) { printf("\'%s\' was not found.\n", st[i]); } //format the command's path parameters[i] = parse(pipedCommands[i], ' '); int count = 0; for (int k = 0; parameters[i][k]; k++) { count++; } } //check if the files_exist if (files_exist(st, pipes)) { int i; pid_t result; //create pipes int in, fd [2]; in =0; //begin executing commands result = fork(); if (result == 0) { //is a pipe needed? and how many for (i = 0; i < pipes; i++) { pipe(fd); //create more branches for children if ((result=fork()) ==0) { //child close input pipe if ((in != 0)) { dup2(in, 0); close(in); } //parents close write pipe if(fd[1] != 1) { dup2(fd[1], 1); close(fd[1]); } //execute piped commands execv(st[i], parameters[i]); }else { wait(&result); } //close write pipe close(fd [1]); //direct output to input for next child in = fd [0]; } //set stdin for final command if (in != 0) { dup2(in, 0); } //close pipe close(fd[0]); //execute final command execv(st[i], parameters[i]); } else { wait(&result); } } printf("Dat Bash $"); } }
/* Test the "semantics" (with respect to what the outputs should be, given certain input) of the test cases in ../test/*. This testing has the preconditions of having a text output file in test/files/testX/execution/output (for X = test0, test1, ...) and a executable binary in test/files/testX/execution/bin (for X = test0, test1, ...). */ void test_semantics_of_test_cases() { std::cout << std::endl << std::endl << "Checking semantics of every test case provided:" << std::endl; /* Test case index. */ unsigned int t_index = 0; /* (input, output) pair index. */ unsigned int f_index = 0; const std::string path_temp = ("../test/files/test"); /* Input file. */ std::string input_path; /* Output file of execution. */ std::string output_path; /* The expected output file. */ std::string exp_output_path; while(exists(path_temp + std::to_string(t_index) + std::string("/execution/bin"))) { /* The binary file to be checked on exists. */ f_index = 0; std::string binary = path_temp + std::to_string(t_index) + std::string("/execution/bin"); while(files_exist(path_temp, t_index, f_index)) { /* There is a new (input, output) pair to be checked. */ input_path = path_temp + std::to_string(t_index) + std::string("/input") + std::to_string(f_index); output_path = path_temp + std::to_string(t_index) + std::string("/execution/output"); exp_output_path = path_temp + std::to_string(t_index) + std::string("/output") + std::to_string(f_index); std::string execution = binary + (std::string(" < ") + input_path) + (std::string(" > ") + output_path); std::system(execution.c_str()); /* ------------------------------------------------------------ */ /* These instructions check that there was no difference between the output that resulted from execution, and the expected output. */ // First, build diff command. std::string diff = std::string("diff ") + output_path + std::string(" ") + exp_output_path + std::string(" > extra.diff"); // Execute diff command. std::system(diff.c_str()); // Open file that contains results of diff execution. std::fstream extra; extra.open("extra.diff", std::fstream::in); assert(!extra.fail()); // Check that the end of the file is at position 0 // (i.e., length is 0). extra.seekg(0, extra.end); if ((int)extra.tellg() != 0) { std::cout << "Differences have been found between "; std::cout << output_path << " and " << exp_output_path; std::cout << ":" << std::endl; std::system("cat extra.diff"); exit(1); } /* ------------------------------------------------------------ */ ++f_index; } ++t_index; } if (exists(std::string("extra.diff"))) std::system("rm extra.diff"); std::cout << "\tSemantics of the test cases has been proven correct." << std::endl; }