diff --git a/Documents/Program Logic b/Documents/Program Logic deleted file mode 100644 index 6439eeb908f025923d92d50381fa9e39b4e49185..0000000000000000000000000000000000000000 --- a/Documents/Program Logic +++ /dev/null @@ -1,30 +0,0 @@ - -Program Logic - - -Pipe - | - Takes stdout of item on left and uses as stdin of item on right. - - -Three cases: - Pipe on right side: - First command in line. Should be handled by original shell. - - Pipe on left side: - Last command in line. Original shell should fork this. - - Pipe on both sides: - Middle elements. - "Base Case" if no more middle items are present after this one. - - -How to handle by recursion: - First read command line. Regardless, fork to run at least once process. - If multiple piped items, recursion starts: - Handle "rightmost" item by sending remaining line, minus item on right. - Base Case: - If no more values to remove, then done. - Next, copy standard out of each "child" into the standard in of each "parent". - End recursion. Should handle all values back to initial fork. - Copy output of fork to original terminal. Originally forked to ensure that original terminal should never close. - diff --git a/HelperFunctions.c b/HelperFunctions.c index 53790efb60791ff081ff99a30d417a0146d82c9d..1b9d4dfe964274dedc24fd53a6eaa07da4c124c1 100644 --- a/HelperFunctions.c +++ b/HelperFunctions.c @@ -262,3 +262,66 @@ char* remove_newline(char* input_string) { return input_string; } + + +/** + * Gets user input from stdin. + */ +char* get_user_input() { + int get_input = 1; + char* user_input_buffer; + char* user_input; + + // Loop until input is given. + while (get_input == 1) { + user_input_buffer = calloc(4096, sizeof(char)); + printf("Enter input: "); + fgets(user_input_buffer, 4096, stdin); + + // Use copy_string function to remove extra buffer. + user_input = copy_string(user_input_buffer); + free(user_input_buffer); + + // Check that any input was given. + // Check that any input was given. + user_input = remove_newline(user_input); + if (strcmp(user_input, "") == 0) { + free(user_input); + } else { + get_input = 0; + } + } + + return user_input; +} + + +/** + * Gets user input from stdin and displays variable prompt. + */ +char* get_user_input_with_prompt(char* prompt) { + int get_input = 1; + char* user_input_buffer; + char* user_input; + + // Loop until input is given. + while (get_input == 1) { + user_input_buffer = calloc(4096, sizeof(char)); + printf("%s", prompt); + fgets(user_input_buffer, 4096, stdin); + + // Use copy_string function to remove extra buffer. + user_input = copy_string(user_input_buffer); + free(user_input_buffer); + + // Check that any input was given. + user_input = remove_newline(user_input); + if (strcmp(user_input, "") == 0) { + free(user_input); + } else { + get_input = 0; + } + } + + return user_input; +} diff --git a/HelperHeader.h b/HelperHeader.h index 7634698661cab1428a40ef2fdd585023c9f9ba75..402053e9a857def67ee3af0057bb14fec21e3a24 100644 --- a/HelperHeader.h +++ b/HelperHeader.h @@ -32,3 +32,6 @@ char* to_upper_case(char* input_string); char* first_letter_upper(char* input_string); char* remove_quotes(char* input_string); char* remove_newline(char* input_string); + +char* get_user_input(); +char* get_user_input_with_prompt(); diff --git a/Main.c b/Main.c index b73490997bcc49f086a9b53f41efba71a790ff13..7abcbb42e6b7bccc2626501874de924cbaa8adaa 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" @@ -37,13 +38,20 @@ typedef struct{ int argc; char*** argv; } makeargv_struct; +makeargv_struct* line_argv; // Pointer to makeargv struct. +makeargv_struct* command_argv; // Pointer to/array of makeargv structs. + // Method Declaration. 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 parse_command(); // Further parses line into smaller subsections. void execute_command(); // Executes provided command. +void recursive_execute(); // Continues executing command. +void redirect_fd(); // Redirects passed file descriptors. +void free_memory(); // Frees memory of vars. void make_arg_example(); @@ -53,30 +61,54 @@ void make_arg_example(); * Initializes and runs program. */ int main(int argc, char* argv[]) { + int run_program = 1; + char* user_input; - parse_line(""); - parse_line("ls"); - parse_line("ls -l"); + // parse_line(""); + // parse_line("ls"); + // parse_line("ls -l"); // parse_line("ls -l | grep a"); // parse_line("ls -l | grep a | grep b"); // parse_line("ls -l | grep a | grep b | grep c"); + // Run until user willingly quits. + while (run_program == 1) { + user_input = get_user_input_with_prompt("$ "); + + parse_line(user_input); + + printf("Tokens: %d\n", line_argv->argc); + printf("line_argv->argv: %s\n", **line_argv->argv); + + if (line_argv->argc > 0) { + parse_command(); + + // Check if exit program. + if (strcmp(**command_argv->argv, "exit") == 0) { + run_program = 0; + + // Check for cd command. + } else if (strcmp(**command_argv->argv, "cd") == 0) { + + + // Attempt to exec command. + } else { + execute_command(); + } + + free(user_input); + free_memory(); + } + } + return 0; } /** - * Parses given command into subsections, separated by spaces. - * Generally speaking, this will fall into either "command" or "argument". + * Parses given line into subsections, separated by pipes. */ 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. - - printf("Beginning command line parse... "); - // Parse line into struct. Seperates by each found "|" in argument. // Each seperated value should be an individual commmand. line_argv = calloc(1, sizeof(makeargv_struct)); @@ -87,109 +119,156 @@ void parse_line(char* command_line) { if (line_argv->argc < 0) { err_sys("Unexpected error parsing command line."); } +} + + +/** + * Further parse a given line into smaller subsections, separated by spaces. + */ +void parse_command() { + int index; + makeargv_struct* temp_pointer; - 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)); + temp_pointer = command_argv; - // For each argument above, parse again. + // For each argument in line_argv, 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("%d | line_argv arg: %s\n", index, (*(*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++; - } + // Print same value as above, but in command_argv to prove it exists. + printf("%d | command_argv arg: %s\n", index, (*(*command_argv->argv + index))); + ++command_argv; + printf("\n"); - execute_command(*command_argv->argv); index++; } + command_argv = temp_pointer; +} - // 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(command_argv->argv); - free(line_argv->argv); - free(command_argv); - free(line_argv); +/** + * Start initial child pipe, then hand off to recursive function. + */ +void execute_command() { + pid_t pid; + int status; + + // Check that there are any provided args. + if (line_argv->argc > 0) { + switch(pid = fork()) { + case 0: // Child. + recursive_execute(line_argv->argc, command_argv, (line_argv->argc - 1)); + break; + + case -1: // Error. + err_sys("Fork Error."); + break; + + default: // Parent. + waitpid(pid, &status, 0); // Wait for child process to end. + break; + } + } } /** - * Takes provided command and runs appropriately. + * Recursive function to handle command input. + * Should handle both single commands and multi-pipe commands. */ -void execute_command(char** command) { +void recursive_execute(int argc, makeargv_struct* args, int current_arg) { + pid_t pid; + int index; int status; int fd[2]; - pid_t pid; + 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]); + } - 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; + // 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); + + execvp(**temp_pointer->argv, *temp_pointer->argv); + err_sys("Failed to exec."); } } +/** + * Frees memory of main program variables. + */ +void free_memory() { + int index; + makeargv_struct* temp_pointer; + + index = 0; + + // 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); + free(command_argv); + command_argv = temp_pointer; + line_argv->argc--; + } + + // Free line_argv values. + free(*(*(line_argv->argv + index))); + free(*(line_argv->argv)); + free(line_argv->argv); + free(line_argv); +} + + /** * Example of using makeargv. */