From 07ae95a5af0105666fdb77bbc6651bc8e5f05411 Mon Sep 17 00:00:00 2001 From: Brandon Rodriguez <brodriguez8774@gmail.com> Date: Thu, 2 Nov 2017 17:13:47 -0400 Subject: [PATCH] Add handling for redirection (< and > symbols) --- Main.c | 119 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 35 deletions(-) diff --git a/Main.c b/Main.c index f382d96..a5fa59a 100644 --- a/Main.c +++ b/Main.c @@ -20,18 +20,24 @@ * ls -l | grep a | grep b | grep c | grep v * appears to work with no issues or memory leaks. * - * Adding a single & (seperated by spaces) at the end of a command enables backgrounding. + * Adding a single & (seperated by spaces) at the end of a command enables backgrounding. * The parent will create a child that runs off to do provided command. * Parent will meanwhile forget about child and prompt for further input. + * + * Redirecting with < or > will temporarily change input/output accordingly. */ /** * Known Issues: - * Does not handle < or > symbols. - - * Backgrounding slightly messes up user interface display. + * Backgrounding may mess up user interface display. * Should correct after inputing another command. + * + * Combining backgrounding and redirection may cause a memory leak. + * The combination may also result in unexpected handling. + * To be perfectly blunt, I don't understand piping/duping nearly + * enough to troubleshoot this behavior. + * As it is, the standard piping/duping is still confusing. */ @@ -56,6 +62,7 @@ // Import headers. #include <ctype.h> +#include <fcntl.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -77,6 +84,10 @@ typedef struct{ char*** argv; } makeargv_struct; int run_program; // Holds if program should continue to run. +int in_redir_bool; // Holds if input redirection is denoted. +char* in_redir_char; // Input redirection variable. +int out_redir_bool; // Holds if output redirection is denoted. +char* out_redir_char; // Output redirection variable. char* user_input; // Holds user input value. makeargv_struct* line_argv; // Pointer to makeargv struct. makeargv_struct* command_argv; // Pointer to/array of makeargv structs. @@ -97,7 +108,7 @@ void set_umask(); // Sets umask value. void interupt_handler(); // Handler for ctrl+c signal. int check_for_backgrounding(); // Check for backgrounding (&) at end of input. void run_backgrounding(); // Runs child processes in background. -void free_memory(); // Frees memory of vars. +void check_for_redirection(); // Check for redirection (< or >) within input. void free_line_argv(); // Frees memory of line_argv. void free_command_argv(); // Frees memory of line_argv. @@ -162,8 +173,9 @@ int main(int argc, char* argv[]) { user_input = get_user_input_with_prompt(""); free(current_directory); - // Check for backgrounding. + // Check for backgrounding/redirection. backgrounding_bool = check_for_backgrounding(); + check_for_redirection(); // Run based on backgrounding bool. if (backgrounding_bool == 1) { @@ -234,9 +246,11 @@ void main_loop() { } else { execute_command(); } - //free_memory(); free_command_argv(); free_line_argv(); + } else { + free(in_redir_char); + free(out_redir_char); } } @@ -286,13 +300,30 @@ void parse_command() { * Start initial child pipe, then hand off to recursive function. */ void execute_command() { - pid_t pid; int status; + int fd; + pid_t pid; // Check that there are any provided args. if (line_argv->argc > 0) { + switch(pid = fork()) { - case 0: // Child. + case 0: // Child + + // Check for input redirect. + if (in_redir_bool == 1) { + fd = open(in_redir_char, O_RDONLY); + free(in_redir_char); + dup2(fd, STDIN_FILENO); + } + + // Check for output redirect. + if (out_redir_bool == 1) { + fd = open(out_redir_char, O_CREAT | O_APPEND | O_WRONLY, 0777); + free(out_redir_char); + dup2(fd, STDOUT_FILENO); + } + recursive_execute(line_argv->argc, command_argv, (line_argv->argc - 1)); break; @@ -302,6 +333,17 @@ void execute_command() { default: // Parent. waitpid(pid, &status, 0); // Wait for child process to end. + + // Check for input redirect. + if (in_redir_bool == 1) { + free(in_redir_char); + } + + // Check for output redirect. + if (out_redir_bool == 1) { + free(out_redir_char); + } + break; } } @@ -356,7 +398,6 @@ void recursive_execute(int argc, makeargv_struct* args, int current_arg) { if (execvp(**temp_pointer->argv, *temp_pointer->argv) == -1) { err_msg("Invalid exec arg(s)."); - //free_memory(); free_command_argv(); free_line_argv(); exit(-1); @@ -482,7 +523,6 @@ void interupt_handler() { int check_for_backgrounding() { int index = 0; int backgrounding_bool = 0; - char* token; char* temp_string; // Go to last index of string. @@ -506,7 +546,7 @@ int check_for_backgrounding() { // If background char was found, seperate out token. if (backgrounding_bool == 1) { - token = strtok_r(user_input, "&", &temp_string); + strtok_r(user_input, "&", &temp_string); } return backgrounding_bool; @@ -543,31 +583,40 @@ void run_backgrounding() { /** - * Frees memory of main program variables. + * Checks for redirection (< or >) chars within input. */ -void free_memory() { - int index; - makeargv_struct* temp_pointer; - makeargv_struct* orig_pointer = command_argv; - - 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); - command_argv = temp_pointer; - line_argv->argc--; +void check_for_redirection() { + char* token; + char* temp_string; + char* redir_string; + + // Check for input redirection. + temp_string = copy_string(user_input); + token = strtok_r(temp_string, "<", &redir_string); + if (strcmp(user_input, token) != 0) { + free(user_input); + user_input = copy_string(token); + in_redir_bool = 1; + in_redir_char = copy_string(redir_string); + } else { + in_redir_bool = 0; + //in_redir_char = calloc(1, sizeof(char)); + } + free(temp_string); + + // Check for output redirection. + temp_string = copy_string(user_input); + token = strtok_r(temp_string, ">", &redir_string); + if (strcmp(user_input, token) != 0) { + free(user_input); + user_input = copy_string(token); + out_redir_bool = 1; + out_redir_char = copy_string(redir_string); + } else { + out_redir_bool = 0; + //out_redir_char = calloc(1, sizeof(char)); } - free(orig_pointer); - - // Free line_argv values. - free(*(*(line_argv->argv + index))); - free(*(line_argv->argv)); - free(line_argv->argv); - free(line_argv); + free(temp_string); } -- GitLab