diff --git a/src/array.c b/src/array.c index c09ab80..1cd8eb1 100644 --- a/src/array.c +++ b/src/array.c @@ -13,47 +13,90 @@ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include "array.h" +/** + * Create a String Array by initializing its structure. + * @param string_array The String Array to create. + */ void create_string_array(StringArray *string_array) { string_array->array = NULL; string_array->size = 0; } +/** + * Insert a string into the String Array. + * @param string_array The String Array to insert into. + * @param string The string to insert into the String Array. + */ void insert_string_array(StringArray *string_array, char *string) { if (string_array->size == 0) { string_array->array = malloc(sizeof(char *)); + if (string_array->array == NULL) { + fprintf(stderr, "malloc failed"); + exit(EXIT_FAILURE); + } } else { string_array->array = realloc(string_array->array, (string_array->size + 1) * sizeof(char *)); + if (string_array->array == NULL) { + fprintf(stderr, "realloc failed"); + exit(EXIT_FAILURE); + } } string_array->array[string_array->size] = malloc(sizeof(string)); + if (string_array->array == NULL) { + fprintf(stderr, "malloc failed"); + exit(EXIT_FAILURE); + } strcpy(string_array->array[string_array->size], string); string_array->size++; } +/** + * Delete a string from the String Array. + * @param string_array The String Array to delete from. + * @param index The index in the String Array to delete. + */ void delete_string_array(StringArray *string_array, int index) { if (string_array->size > 0 && string_array->size > index) { for (int i = index; i < string_array->size - 1; i++) { free(string_array->array[i]); string_array->array[i] = NULL; string_array->array[i] = malloc(sizeof(string_array->array[i + 1])); + if (string_array->array[i] == NULL) { + fprintf(stderr, "malloc failed"); + exit(EXIT_FAILURE); + } strcpy(string_array->array[i], string_array->array[i + 1]); } free(string_array->array[string_array->size - 1]); string_array->array[string_array->size - 1] = NULL; string_array->array = realloc(string_array->array, (string_array->size - 1) * sizeof(char *)); + if (string_array->array == NULL) { + fprintf(stderr, "realloc failed"); + exit(EXIT_FAILURE); + } string_array->size--; } } +/** + * Free the String Array and all of its strings. + * @param string_array The String Array to free. + */ void free_string_array(StringArray *string_array) { for (int i = 0; i < string_array->size; i++) { - free(string_array->array[i]); - string_array->array[i] = NULL; + if (string_array->array[i] != NULL) { + free(string_array->array[i]); + string_array->array[i] = NULL; + } + } + if (string_array->array != NULL) { + free(string_array->array); + string_array->array = NULL; } - free(string_array->array); - string_array->array = NULL; string_array->size = 0; } diff --git a/src/builtins.c b/src/builtins.c index 4648ad9..a677774 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -18,6 +18,11 @@ #include "array.h" #include "builtins.h" +/** + * Check if the command is a builtin or not. + * @param command String with the command name to check. + * @return Returns true if it's a builtin or false otherwise. + */ bool is_builtin(char *command) { if (strcmp(command, "exit") == 0) { return true; @@ -30,13 +35,21 @@ bool is_builtin(char *command) { return false; } -void run_builtin(StringArray *string_array) { - if (strcmp(string_array->array[0], "exit") == 0) { - exit_shell(string_array); +/** + * Run the builtin command. + * @param args An array of strings containing the arguments to run. + */ +void run_builtin(StringArray *args) { + if (strcmp(args->array[0], "exit") == 0) { + exit_shell(args); } } -void exit_shell(StringArray *string_array) { - free_string_array(string_array); +/** + * Exit the shell. + * @param args The arguments that were used to call exit. This is used to free the memory before exit. + */ +void exit_shell(StringArray *args) { + free_string_array(args); exit(EXIT_SUCCESS); } diff --git a/src/console_line.c b/src/console_line.c index 7ea5e34..3c1413c 100644 --- a/src/console_line.c +++ b/src/console_line.c @@ -18,20 +18,46 @@ #include #include #include +#include #include #include #include "color.h" +#include "console_line.h" + +/** + * Remove new line from the end of a string. + * @param line The string to remove the new line from. + */ +void remove_new_line(char* line) { + line[strcspn(line, "\n")] = 0; +} /** * Get the logged in user's username. * @return Returns the logged in user's username. */ -char *get_user() { +char *get_username() { struct passwd *pass; pass = getpwuid(getuid()); return pass->pw_name; } +/** + * Get the hostname of the machine. + * @return Returns the hostname. + */ +char *get_hostname() { + char hostname[HOST_NAME_MAX + 1]; + gethostname(hostname, HOST_NAME_MAX + 1); + char *result = malloc((HOST_NAME_MAX + 1) * sizeof(char)); + if (result == NULL) { + fprintf(stderr, "malloc failed"); + exit(EXIT_FAILURE); + } + strcpy(result, hostname); + return result; +} + /** * Get the current working directory of the shell. * @return Returns the current working directory. @@ -52,8 +78,41 @@ char *get_working_directory() { * Print the console line before the user input. */ void print_input_line() { - char *name = get_user(); + char *username = get_username(); + char *hostname = get_hostname(); char *cwd = get_working_directory(); - printf(BRIGHT_CYAN "%s" MAGENTA "@" RED "localhost" MAGENTA ":" BLUE "%s" MAGENTA "$ " RESET, name, cwd); + printf(BRIGHT_CYAN "%s" MAGENTA "@" RED "%s" MAGENTA ":" BLUE "%s" MAGENTA "$ " RESET, username, hostname, cwd); + free(hostname); free(cwd); } + +/** + * Get input from the console. + * @return Returns a string input by the user. + */ +char *get_console_input() { + size_t buffer_size = 0; + char *line = NULL; + + if (getline(&line, &buffer_size, stdin) == -1) { + if (feof(stdin)) { + // the stdin was closed, this usually happens for CTRL-D + printf("\n"); + if (line != NULL) { + free(line); + line = NULL; + } + exit(EXIT_SUCCESS); + } + else { + perror("getline() error: "); + if (line != NULL) { + free(line); + line = NULL; + } + exit(EXIT_FAILURE); + } + } + remove_new_line(line); + return line; +} diff --git a/src/include/array.h b/src/include/array.h index fef9b3a..cdf048a 100644 --- a/src/include/array.h +++ b/src/include/array.h @@ -29,5 +29,4 @@ void insert_string_array(StringArray *string_array, char *string); void delete_string_array(StringArray *string_array, int index); void free_string_array(StringArray *string_array); - #endif diff --git a/src/include/builtins.h b/src/include/builtins.h index ccaebbf..4ffa2d5 100644 --- a/src/include/builtins.h +++ b/src/include/builtins.h @@ -19,6 +19,8 @@ #ifndef _MYSHELLIN_BUILTINS #define _MYSHELLIN_BUILTINS bool is_builtin(char *command); + void run_builtin(StringArray *string_array); + void exit_shell(StringArray *string_array); #endif diff --git a/src/include/console_line.h b/src/include/console_line.h index 6b0803c..e1f85eb 100644 --- a/src/include/console_line.h +++ b/src/include/console_line.h @@ -15,7 +15,17 @@ #ifndef _MYSHELLIN_CONSOLE_LINE #define _MYSHELLIN_CONSOLE_LINE -char *get_user(); +#define CONSOLE_BUFFER_SIZE 1024 + +void remove_new_line(char *line); + +char *get_username(); + +char *get_hostname(); + char *get_working_directory(); + void print_input_line(); + +char *get_console_input(); #endif diff --git a/src/include/loop.h b/src/include/loop.h index adc2695..0586ad7 100644 --- a/src/include/loop.h +++ b/src/include/loop.h @@ -15,6 +15,5 @@ #ifndef _MYSHELLIN_LOOP #define _MYSHELLIN_LOOP -void remove_new_line(char *line); void loop(); #endif diff --git a/src/loop.c b/src/loop.c index cfaf81f..e7b6087 100644 --- a/src/loop.c +++ b/src/loop.c @@ -21,52 +21,22 @@ #include "builtins.h" #include "console_line.h" -/** - * Remove new line from the end of a string. - * @param line The string to remove the new line from. - */ -void remove_new_line(char* line) { - line[strcspn(line, "\n")] = 0; -} - /** * This is the loop that checks for user input and acts on it. */ void loop() { - size_t buffer_size = 0; - char *line = NULL; - while (1) { print_input_line(); - if (getline(&line, &buffer_size, stdin) == -1) { - if (feof(stdin)) { - // the stdin was closed, this usually happens for CTRL-D - printf("\n"); - if (line != NULL) { - free(line); - line = NULL; - } - exit(EXIT_SUCCESS); - } - else { - perror("getline() error: "); - if (line != NULL) { - free(line); - line = NULL; - } - exit(EXIT_FAILURE); - } - } - remove_new_line(line); + char *line = get_console_input(); - StringArray string_array; - create_string_array(&string_array); + StringArray args; + create_string_array(&args); char *saveptr = NULL; char *token = strtok_r(line, " ", &saveptr); while (token) { - insert_string_array(&string_array, token); + insert_string_array(&args, token); token = strtok_r(NULL, " ", &saveptr); } if (line != NULL) { @@ -75,14 +45,14 @@ void loop() { } // The user didn't type anything so restart the loop - if (string_array.size == 0) { + if (args.size == 0) { continue; } - if (is_builtin(string_array.array[0])) { - run_builtin(&string_array); + if (is_builtin(args.array[0])) { + run_builtin(&args); } - free_string_array(&string_array); + free_string_array(&args); } }