//Kai Kuebler and Caleb Collar #include #include #include #include #include #include #include #include #include #include #include using namespace std; int main(int argc, char * argv[]) { bool HandleOptions(int argc, char ** argv, string &, string &, string &, string &, string &, string &); string d_arg; string i_arg; string o_arg; string a_arg; string arg_one; string arg_two; if (!HandleOptions(argc, argv, d_arg, i_arg, o_arg, a_arg, arg_one, arg_two)) { cout << "Missing required command line option -1" << endl; return 1; } if(d_arg.length() > 0){ if(chdir(d_arg.c_str()) == 0); else{ cerr << "Path does not exist, or is not a directory" << endl; return 1; } } int pipefds[2]; if(arg_two.length() > 0){ if(pipe(pipefds) < 0){ cerr << "Pipe failed." << endl; return 1; } } int PID = fork(); if (PID < 0) { cerr << "Fork failure." << endl; } else if (PID == 0) { //child if (i_arg.length() > 0){ if (fopen(i_arg.c_str(), "r")) { //fclose(file); if (arg_two.length() > 0){ //if -2 is on the command line, then the pipe will be on the open file table, so this file's index will be two greater (i.e. 5) on said table close(STDIN_FILENO); dup(5); close(5); } else{ //no pipe on the open file table, so this file will be after the default calues in the open file table close(STDIN_FILENO); dup(3); close(3); } } else { cerr << "Could not open redirected input file: no such file or directory" << endl; return 1; } } if(o_arg.length() > 0 && arg_two.length() <= 0){ if(fopen(o_arg.c_str(), "w")) { close(STDOUT_FILENO); dup(3); close(3); } else{ cerr << "Path is invalid or file could not be opened" << endl; return 1; } } if(a_arg.length() > 0 && arg_two.length() <= 0){ if(fopen(a_arg.c_str(), "a")) { close(STDOUT_FILENO); dup(3); close(3); } else{ cerr << "Path is invalid or file could not be opened" << endl; return 1; } } if(arg_two.length() > 0){ close(3); //or pipefds[0] close(STDOUT_FILENO); dup(4); close(4); } char* args[2]; args[0] = strdup(arg_one.c_str()); args[1] = NULL; if(execvp(args[0], args) == -1){ cerr << "Prog 1 exec failed." << endl; return 1; } } else { //parent int c2PID; if(arg_two.length() > 0){ c2PID = fork(); if (c2PID < 0) { cerr << "Fork failure." << endl; } else if (c2PID == 0){ //child 2 close(4); close(STDIN_FILENO); dup(3); close(3); if(o_arg.length() > 0){ if(fopen(o_arg.c_str(), "w")) { close(STDOUT_FILENO); dup(3); close(3); } else{ cerr << "Path is invalid or file could not be opened" << endl; return 1; } } if(a_arg.length() > 0){ if(fopen(a_arg.c_str(), "a")) { close(STDOUT_FILENO); dup(3); close(3); } else{ cerr << "Path is invalid or file could not be opened" << endl; return 1; } } char* args[2]; args[0] = strdup(arg_two.c_str()); args[1] = NULL; if(execvp(args[0], args) == -1){ cerr << "Prog 2 exec failed." << endl; return 1; } } else{ //parent } } int status2; int childTwoPID; int status; //wait on child return needs to properly reflect exit status (currently only 0) close(3); close(4); int childOnePID = waitpid(PID, &status, 0); if (arg_two.length() > 0){ //waitr for child 2 childTwoPID = waitpid(c2PID, &status2, 0); } if (arg_two.length() > 0){ cout << "Child 2: " << childTwoPID << " Returns: " << WEXITSTATUS(status2) << endl; } cout << "Child 1: " << childOnePID << " Returns: " << WEXITSTATUS(status) << endl; } return 0; } bool HandleOptions(int argc, char ** argv, string & d_arg, string & i_arg, string & o_arg, string & a_arg, string & arg_one, string & arg_two) { int c; while ((c = getopt(argc, argv, "d:i:o:a:1:2:pv")) != -1) { switch (c) { default: case 'd': d_arg = string(optarg); break; case 'i': i_arg = string(optarg); break; case 'o': o_arg = string(optarg); if(a_arg.length() > 0){ a_arg = ""; } break; case 'a': a_arg = string(optarg); if(o_arg.length() > 0){ o_arg = ""; } break; case '1': arg_one = string(optarg); break; case '2': arg_two = string(optarg); break; case 'p': char cwd [PATH_MAX]; cout << getcwd(cwd, sizeof(cwd)) << endl; break; case 'v': break; } } return arg_one.size() > 0; }