diff --git a/Main.c b/Main.c index b73490997bcc49f086a9b53f41efba71a790ff13..eb503c8aae6b94de64bfe76bfb5e6fa22f804df8 100644 --- a/Main.c +++ b/Main.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> #include <sys/wait.h> +#include <unistd.h> #include "apue.h" #include "HelperHeader.h" @@ -44,6 +45,8 @@ int makeargv(); // Creates argv using passed line. void parse_line(); // Parses provided line into commands. makeargv_struct* parse_command(); // Parses provided command into subsections. void execute_command(); // Executes provided command. +void recursive_execute(); // Continues executing command. +void redirect_fd(); // Redirects passed file descriptors. void make_arg_example(); @@ -54,10 +57,10 @@ void make_arg_example(); */ int main(int argc, char* argv[]) { - parse_line(""); - parse_line("ls"); + // parse_line(""); + // parse_line("ls"); parse_line("ls -l"); - // parse_line("ls -l | grep a"); + parse_line("ls -l | grep a"); // parse_line("ls -l | grep a | grep b"); // parse_line("ls -l | grep a | grep b | grep c"); @@ -71,9 +74,10 @@ int main(int argc, char* argv[]) { */ void parse_line(char* command_line) { int index; - int index2; makeargv_struct* line_argv; // Pointer to makeargv struct. - makeargv_struct* command_argv; // Pointer to makeargv struct. + makeargv_struct* command_argv; // Pointer to/array of makeargv structs. + makeargv_struct* orig_pointer; // Holds orig value (start) of command_argv. + makeargv_struct* temp_pointer; // Temporary pointer placeholder. printf("Beginning command line parse... "); @@ -89,103 +93,141 @@ void parse_line(char* command_line) { } printf("%d tokens found.\n", line_argv->argc); - command_argv = calloc(1, sizeof(makeargv_struct)); - command_argv->argv = calloc(1, sizeof(char***)); + command_argv = calloc(line_argv->argc, sizeof(makeargv_struct)); + orig_pointer = command_argv; // For each argument above, parse again. // This will separate the individual arguments of each given command. index = 0; while (index < line_argv->argc) { - printf("%s\n", (**(line_argv->argv + index))); - command_argv->argc = makeargv((**(line_argv->argv)), " ", command_argv->argv); + // Print line argv to prove it exists. + printf("line_argv arg: %s\n", (*(*line_argv->argv + index))); + + command_argv->argv = calloc(1, sizeof(char***)); + command_argv->argc = makeargv((*(*line_argv->argv + index)), " ", command_argv->argv); // Check for errors. if (command_argv->argc < 0) { err_sys("Unexpected error parsing command line."); } - index2 = 0; - while (index2 < command_argv->argc) { - printf("%s ", (*(*command_argv->argv + index2))); - index2++; - } + printf("command_argv arg: %s\n", (*(*command_argv->argv + index))); + ++command_argv; + printf("\n"); - execute_command(*command_argv->argv); index++; } + command_argv = orig_pointer; + + // If any args, run commands. + if (line_argv->argc > 0) { + printf("command_argv arg: %s\n", **command_argv->argv); + execute_command(line_argv->argc, command_argv, (line_argv->argc - 1)); + } + // Free memory. index = 0; - while (index < line_argv->argc) { - free(*(*(line_argv->argv + index))); - free(*(line_argv->argv + index)); - index2 = 0; - // // Not needed? - // while (index2 < command_argv->argc) { - // //printf("%s ", (*(*command_argv->argv + index2))); - // free(*(*command_argv->argv + index2)); - // index2++; - // } - free(*(*command_argv->argv + index2)); - free(*(command_argv->argv + index)); - index++; - } - if (line_argv->argc == 0) { - free(*line_argv->argv); + + // Free all of command_argv values. + while (line_argv->argc > 0) { + temp_pointer = command_argv; + ++temp_pointer; + free(*(*command_argv->argv)); + free(*(command_argv->argv)); + free(command_argv->argv); + command_argv = temp_pointer; + line_argv->argc--; } + free(orig_pointer); - free(command_argv->argv); + // Free line_argv values. + free(*(*(line_argv->argv + index))); + free(*(line_argv->argv)); free(line_argv->argv); - free(command_argv); free(line_argv); } /** - * Takes provided command and runs appropriately. + * Start initial child pipe, then hand off to recursive function. */ -void execute_command(char** command) { +void execute_command(int argc, makeargv_struct* args, int current_arg) { + pid_t pid; int status; - int fd[2]; + + // Check that there are any provided args. + if (argc > 0) { + switch(pid = fork()) { + case 0: // Child. + recursive_execute(argc, args, current_arg); + break; + + case -1: // Error. + err_sys("Fork Error."); + break; + + default: // Parent. + waitpid(pid, &status, 0); // Wait for child process to end. + break; + } + } +} + + +/** + * Recursive function to handle command input. + * Should handle both single commands and multi-pipe commands. + */ +void recursive_execute(int argc, makeargv_struct* args, int current_arg) { pid_t pid; + int index; + int status; + int fd[2]; + makeargv_struct* temp_pointer; + + // Check that there are still args to iterate through. + if (argc > 0) { + + // Check if there are still more child args to handle. + if (argc > 1) { + pipe(fd); + switch(pid = fork()) { + case 0: // Child Process. + dup2(fd[1], STDOUT_FILENO); + close(fd[0]); + close(fd[1]); + recursive_execute((argc - 1), args, (current_arg - 1)); + break; + + case -1: // Error. + err_sys("Fork Error."); + break; + + default: // Parent. + waitpid(pid, &status, 0); // Wait for child process to end. + break; + } + dup2(fd[0], 0); + close(fd[0]); + close(fd[1]); + } + + // Get desired arg to run. + temp_pointer = args; + index = 0; + while (index < current_arg) { + ++temp_pointer; + index++; + } + + printf("Process to Run: %s\n", **temp_pointer->argv); + - printf("Executing Commands...\n"); - // Fork process. - pipe(fd); - switch (pid = fork()) { - - case 0: // Child process. - dup2(fd[0], STDIN_FILENO); - close(fd[1]); // Child does not need this. - printf("IMA CHILD.\n\n"); - - // Basic ls example. - //execlp("ls", "ls", (char*) NULL); - // ls with one arg example. - //execlp("ls", "ls", "-l", (char*) NULL); - - // execlp example. - // if (*(command + 1) != NULL) { - // execlp(*command, *command, *(command + 1), (char*) NULL); - // } else { - // execlp(*command, *command, (char*) NULL); - // } - - execvp(*command, command); - - err_sys("Child execution did not work."); - break; - case -1: // Error. - err_sys("Fork Error."); - break; - default: // Parent Process. - close(fd[0]); // Parent does not need this. - printf("IMA PARENT.\n"); - wait(&status); // Wait for child process to end. - printf("\nOh, he ded. No longer a parent.\n\n"); - break; + execvp(**temp_pointer->argv, *temp_pointer->argv); + err_sys("Failed to exec."); } }