console_line #7

Merged
cromer merged 7 commits from getchar into master 2021-06-26 23:15:01 -04:00
8 changed files with 148 additions and 53 deletions

View File

@ -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. * 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 <stdio.h>
#include <string.h> #include <string.h>
#include "array.h" #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) { void create_string_array(StringArray *string_array) {
string_array->array = NULL; string_array->array = NULL;
string_array->size = 0; 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) { void insert_string_array(StringArray *string_array, char *string) {
if (string_array->size == 0) { if (string_array->size == 0) {
string_array->array = malloc(sizeof(char *)); string_array->array = malloc(sizeof(char *));
if (string_array->array == NULL) {
fprintf(stderr, "malloc failed");
exit(EXIT_FAILURE);
}
} }
else { else {
string_array->array = realloc(string_array->array, (string_array->size + 1) * sizeof(char *)); 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)); 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); strcpy(string_array->array[string_array->size], string);
string_array->size++; 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) { void delete_string_array(StringArray *string_array, int index) {
if (string_array->size > 0 && string_array->size > index) { if (string_array->size > 0 && string_array->size > index) {
for (int i = index; i < string_array->size - 1; i++) { for (int i = index; i < string_array->size - 1; i++) {
free(string_array->array[i]); free(string_array->array[i]);
string_array->array[i] = NULL; string_array->array[i] = NULL;
string_array->array[i] = malloc(sizeof(string_array->array[i + 1])); 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]); strcpy(string_array->array[i], string_array->array[i + 1]);
} }
free(string_array->array[string_array->size - 1]); free(string_array->array[string_array->size - 1]);
string_array->array[string_array->size - 1] = NULL; string_array->array[string_array->size - 1] = NULL;
string_array->array = realloc(string_array->array, (string_array->size - 1) * sizeof(char *)); 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--; 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) { void free_string_array(StringArray *string_array) {
for (int i = 0; i < string_array->size; i++) { for (int i = 0; i < string_array->size; i++) {
free(string_array->array[i]); if (string_array->array[i] != NULL) {
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; string_array->size = 0;
} }

View File

@ -18,6 +18,11 @@
#include "array.h" #include "array.h"
#include "builtins.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) { bool is_builtin(char *command) {
if (strcmp(command, "exit") == 0) { if (strcmp(command, "exit") == 0) {
return true; return true;
@ -30,13 +35,21 @@ bool is_builtin(char *command) {
return false; return false;
} }
void run_builtin(StringArray *string_array) { /**
if (strcmp(string_array->array[0], "exit") == 0) { * Run the builtin command.
exit_shell(string_array); * @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); exit(EXIT_SUCCESS);
} }

View File

@ -18,20 +18,46 @@
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "color.h" #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. * Get the logged in user's username.
* @return Returns the logged in user's username. * @return Returns the logged in user's username.
*/ */
char *get_user() { char *get_username() {
struct passwd *pass; struct passwd *pass;
pass = getpwuid(getuid()); pass = getpwuid(getuid());
return pass->pw_name; 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. * Get the current working directory of the shell.
* @return Returns the current working directory. * @return Returns the current working directory.
@ -52,8 +78,41 @@ char *get_working_directory() {
* Print the console line before the user input. * Print the console line before the user input.
*/ */
void print_input_line() { void print_input_line() {
char *name = get_user(); char *username = get_username();
char *hostname = get_hostname();
char *cwd = get_working_directory(); 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); 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;
}

View File

@ -29,5 +29,4 @@ void insert_string_array(StringArray *string_array, char *string);
void delete_string_array(StringArray *string_array, int index); void delete_string_array(StringArray *string_array, int index);
void free_string_array(StringArray *string_array); void free_string_array(StringArray *string_array);
#endif #endif

View File

@ -19,6 +19,8 @@
#ifndef _MYSHELLIN_BUILTINS #ifndef _MYSHELLIN_BUILTINS
#define _MYSHELLIN_BUILTINS #define _MYSHELLIN_BUILTINS
bool is_builtin(char *command); bool is_builtin(char *command);
void run_builtin(StringArray *string_array); void run_builtin(StringArray *string_array);
void exit_shell(StringArray *string_array); void exit_shell(StringArray *string_array);
#endif #endif

View File

@ -15,7 +15,17 @@
#ifndef _MYSHELLIN_CONSOLE_LINE #ifndef _MYSHELLIN_CONSOLE_LINE
#define _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(); char *get_working_directory();
void print_input_line(); void print_input_line();
char *get_console_input();
#endif #endif

View File

@ -15,6 +15,5 @@
#ifndef _MYSHELLIN_LOOP #ifndef _MYSHELLIN_LOOP
#define _MYSHELLIN_LOOP #define _MYSHELLIN_LOOP
void remove_new_line(char *line);
void loop(); void loop();
#endif #endif

View File

@ -21,52 +21,22 @@
#include "builtins.h" #include "builtins.h"
#include "console_line.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. * This is the loop that checks for user input and acts on it.
*/ */
void loop() { void loop() {
size_t buffer_size = 0;
char *line = NULL;
while (1) { while (1) {
print_input_line(); 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; StringArray args;
create_string_array(&string_array); create_string_array(&args);
char *saveptr = NULL; char *saveptr = NULL;
char *token = strtok_r(line, " ", &saveptr); char *token = strtok_r(line, " ", &saveptr);
while (token) { while (token) {
insert_string_array(&string_array, token); insert_string_array(&args, token);
token = strtok_r(NULL, " ", &saveptr); token = strtok_r(NULL, " ", &saveptr);
} }
if (line != NULL) { if (line != NULL) {
@ -75,14 +45,14 @@ void loop() {
} }
// The user didn't type anything so restart the loop // The user didn't type anything so restart the loop
if (string_array.size == 0) { if (args.size == 0) {
continue; continue;
} }
if (is_builtin(string_array.array[0])) { if (is_builtin(args.array[0])) {
run_builtin(&string_array); run_builtin(&args);
} }
free_string_array(&string_array); free_string_array(&args);
} }
} }