diff --git a/.gitmodules b/.gitmodules index 8bf60ae..b9e79fb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "libft"] path = libft - url = git@github.com:lithiumox-codam/libft.git + url = https://github.com/lithiumox-codam/libft.git branch = minishell diff --git a/Makefile b/Makefile index 69b4cc1..58559d7 100644 --- a/Makefile +++ b/Makefile @@ -31,10 +31,12 @@ SRC = main \ built_in/utils \ built_in/unset \ built_in/env \ + built_in/sort \ lexer/index \ expander/index \ expander/expand_env \ - expander/expand_quotes + expander/expand_quotes \ + signals/index SRCS = $(addsuffix .c, $(addprefix src/, $(SRC))) OBJS = $(patsubst src/%.c, build/%.o, $(SRCS)) diff --git a/includes/enum.h b/includes/enum.h index b4975e1..aaabfa8 100644 --- a/includes/enum.h +++ b/includes/enum.h @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/13 17:41:00 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/30 18:26:44 by julius ######## odam.nl */ +/* Updated: 2023/11/20 20:59:54 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -63,6 +63,18 @@ typedef enum e_exit OUT_OF_SCOPE } t_exit; +typedef enum e_error +{ + NO_ERROR = 0, + CATCH_ALL = 1, + MISUSE_OF_SHELL = 2, + PERMISSION_DENIED = 126, + COMMAND_NOT_FOUND = 127, + NOT_VALID = 128, + UNEXPECTED_EOF = 130, + SYNTAX_ERROR = 258, +} t_error; + /** * @brief defines which process is being executed */ diff --git a/includes/minishell.h b/includes/minishell.h index 3927b6c..38f49d6 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/09 21:25:59 by mdekker #+# #+# */ -/* Updated: 2023/11/16 23:17:36 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/22 14:20:29 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -18,6 +18,7 @@ # include # include # include +# include # include # include # include @@ -71,10 +72,10 @@ bool hdoc_expand(char **str, t_shell *data); /* executor */ bool executor(t_shell *data); bool create_processes(t_shell *data); -void exec_process(t_group *group, t_process type, t_vector *env_vec); +void exec_process(t_group *group, t_process type, t_shell *data); void dup_fd(t_group *group, t_process type); void check_cmd(t_group *group, t_process type, t_vector *env_vec); -void exec_built_in(t_group *group, t_process type, t_vector *env_vec); +void exec_built_in(t_group *group, t_process type, t_shell *data); void exec_absolute_path(t_group *group, t_process type, t_vector *env_vec); void handle_redirects(t_group *group); void validate_redirects(t_group *group); @@ -89,13 +90,25 @@ char **combine_env(t_vector *env_vec); /* built_in */ void ft_exit(t_group *group, t_shell *data); -void ft_cd(t_group *group, t_vector *env_vec); -void ft_export(t_group *group, t_vector *env_vec); -void ft_unset(t_group *group, t_vector *env_vec); +void ft_cd(t_group *group, t_shell *data); +void ft_export(t_group *group, t_shell *data); +void ft_unset(t_group *group, t_shell *data); void ft_echo(t_group *group); void ft_pwd(void); void ft_env(t_vector *env_vec); void print_env_dec(t_vector *env, char *arg_2); +void update_or_create_env(t_vector *env, char *key, char *value); +char **ft_export_split(char *src, char delimter); +size_t **return_sorted_arr(t_vector *env); +void ft_free_size_t(size_t **arr, size_t len); +char *string_handler(char *input); + +/* signals */ +void signal_main(int signal_num); +void setup_hdoc_signals(void); +void signal_hdoc(int signal_num); +void setup_child_signals(void); +void signal_child(int signal_num); /* structs */ t_token *create_token(char *value, t_types type); @@ -118,6 +131,7 @@ void exec_err(char *str, t_exit type); void write_err(t_shell *data); bool rm_quotes(t_token *token, bool set_string); bool type_compare(size_t num_args, t_types type, ...); +bool filter_operators(void *item); // bool out_of_scope(t_vector *found, t_shell *data); bool is_redirect(t_token *token); diff --git a/includes/structs.h b/includes/structs.h index d14c77e..54b37be 100644 --- a/includes/structs.h +++ b/includes/structs.h @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/10 11:15:16 by mdekker #+# #+# */ -/* Updated: 2023/10/12 18:19:49 by julius ######## odam.nl */ +/* Updated: 2023/11/18 23:06:40 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -83,6 +83,7 @@ typedef struct s_shell t_vector env; t_exec *exec; t_exit exit_type; + t_error error_type; char *exit_msg; } t_shell; diff --git a/libft b/libft index dadf2fd..a486a84 160000 --- a/libft +++ b/libft @@ -1 +1 @@ -Subproject commit dadf2fd54911b1c041938d9bed25edec9e76c2c7 +Subproject commit a486a849c74c989f7321d8d42b7fdc1535df76ad diff --git a/src/built_in/cd.c b/src/built_in/cd.c index 2355350..94671d0 100644 --- a/src/built_in/cd.c +++ b/src/built_in/cd.c @@ -6,30 +6,42 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/11/14 17:29:00 by mdekker #+# #+# */ -/* Updated: 2023/11/17 01:07:00 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/21 15:32:46 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** * @brief Updates the value of an environment variable when it already exists * @param env_var The env struct * @param key The key to compare to * @return void */ -static void update_env(t_vector *env, char *key, char *value) +static void update_env(t_shell *data, char *oldpwd) +{ + char *buff; + + buff = getcwd(NULL, 0); + update_or_create_env(&data->env, "OLDPWD", oldpwd); + update_or_create_env(&data->env, "PWD", buff); + free(buff); +} + +/** + * @brief Helper function to safely get an environment variable + * @param *env The environment vector + * @param *key The key to compare to + * @return char* The value of the environment variable or NULL + */ +static char *safe_env_get(t_vector *env, char *key) { t_env *env_var; env_var = vec_find_f(env, compare_env_key, key); if (env_var) - { - free(env_var->value); - env_var->value = ft_strdup(value); - } + return (env_var->value); + return (NULL); } /** @@ -37,26 +49,58 @@ static void update_env(t_vector *env, char *key, char *value) * @param path The path that caused the error * @return void */ -static void print_err_cd(char *path) +static bool error_check(t_shell *data, t_group *group) { - printf("cd: %s: %s\n", strerror(errno), path); - g_signal.exit_status = 1; + char *path; + + if (group->args[2]) + { + printf("cd: too many arguments\n"); + data->error_type = CATCH_ALL; + return (false); + } + if (!ft_strcmp(group->args[1], "-")) + { + path = safe_env_get(&data->env, "OLDPWD"); + if (!path) + { + printf("cd: OLDPWD not set\n"); + data->error_type = CATCH_ALL; + return (false); + } + printf("%s\n", path); + data->error_type = CATCH_ALL; + return (false); + } + return (true); } /** - * @brief Helper function for vec_find_f to safely get an environment variable - * @param *env The environment vector - * @param *key The key to compare to - * @return char* The value of the environment variable or NULL + * @brief Gets the path to change to + * + * @param group The group struct with the args + * @param data The shell struct + * @return char* The path to change to */ -static char *safe_env_get(t_vector *env, char *key) +static char *get_path(t_group *group, t_shell *data) { - t_env *env_var; + char *path; - env_var = vec_find_f(env, compare_env_key, key); - if (env_var) - return (env_var->value); - return (NULL); + if (!group->args[1] || !ft_strcmp(group->args[1], "~")) + { + path = ft_strdup(safe_env_get(&data->env, "HOME")); + if (!path) + { + printf("cd: HOME not set\n"); + data->error_type = CATCH_ALL; + return (NULL); + } + } + else if (ft_strncmp(group->args[1], "~/", 2) == 0) + path = ft_strjoin(safe_env_get(&data->env, "HOME"), group->args[1] + 1); + else + path = ft_strdup(group->args[1]); + return (path); } /** @@ -67,29 +111,31 @@ static char *safe_env_get(t_vector *env, char *key) * @param env The environment * @return void */ -void ft_cd(t_group *group, t_vector *env) +void ft_cd(t_group *group, t_shell *data) { char *path; char *oldpwd; + if (!error_check(data, group)) + return ; oldpwd = getcwd(NULL, 0); if (!oldpwd) - exit_mini("ft_cd", 1); - if (!group->args[1]) - path = safe_env_get(env, "HOME"); - else if (ft_strcmp(group->args[1], "-") == 0) - path = safe_env_get(env, "OLDPWD"); - else - path = group->args[1]; - if (!path) { - printf("cd: HOME not set\n"); - g_signal.exit_status = 1; + printf("cd: error retrieving current directory: %s\n", strerror(errno)); + data->error_type = CATCH_ALL; return ; } + path = get_path(group, data); + if (!path) + return ; if (chdir(path) == -1) - print_err_cd(path); + { + printf("cd: %s: %s\n", path, strerror(errno)); + data->error_type = CATCH_ALL; + } else - update_env(env, "OLDPWD", oldpwd); + update_env(data, oldpwd); + data->error_type = NO_ERROR; free(oldpwd); + free(path); } diff --git a/src/built_in/echo.c b/src/built_in/echo.c index 4a5ff3f..527a887 100644 --- a/src/built_in/echo.c +++ b/src/built_in/echo.c @@ -6,39 +6,37 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/23 10:10:23 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 15:39:14 by mdekker ######## odam.nl */ +/* Updated: 2023/11/21 16:08:07 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** - * @brief Checks if a flag only contains n's and if it does, it will return the - * index of the first non-flag argument or 1 if no flags. - * - * @param group The group struct with the args - * @return size_t The index of the first non-flag argument or 1 if no flags - */ -static size_t check_flags(t_group *group) + * @brief Checks if a flag only contains n's and if it does, + it will return the + * index of the first non-flag argument or 1 if no flags. + * + * @param group The group struct with the args + * @return size_t The index of the first non-flag argument or 1 if no flags + */ +static bool check_flag(char *arg, bool *flag) { size_t i; - size_t j; - i = 1; - while (group->args[i]) - { - j = 1; - if (group->args[i][0] != '-') - return (i); - while (group->args[i][j] == 'n') - j++; - if (group->args[i][j] != '\0' && group->args[i + 1] == NULL) - return (i); + i = 0; + if (arg[i] != '-') + return (false); + else + i++; + while (arg[i] == 'n') i++; + if (arg[i] == '\0') + { + *flag = true; + return (true); } - return (1); + return (false); } /** @@ -49,8 +47,12 @@ static size_t check_flags(t_group *group) void ft_echo(t_group *group) { size_t i; + bool flag; - i = check_flags(group); + i = 1; + flag = false; + while (group->args[i] && check_flag(group->args[i], &flag)) + i++; while (group->args[i]) { write(1, group->args[i], ft_strlen(group->args[i])); @@ -58,7 +60,7 @@ void ft_echo(t_group *group) write(1, " ", 1); i++; } - if (group->args[1] && ft_strcmp(group->args[1], "-n") != 0) + if (!flag) write(1, "\n", 1); exit(0); } diff --git a/src/built_in/env.c b/src/built_in/env.c index 7ebacee..2a4b09d 100644 --- a/src/built_in/env.c +++ b/src/built_in/env.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/11/16 23:12:07 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 15:26:31 by mdekker ######## odam.nl */ +/* Updated: 2023/11/21 18:15:44 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -15,13 +15,20 @@ void ft_env(t_vector *env_vec) { size_t i; + size_t **arr; + char *value; i = 0; - while (i < env_vec->length) + arr = return_sorted_arr(env_vec); + if (!arr) + return ; + while (arr[i] != NULL) { - printf("%s=%s\n", ((t_env *)vec_get(env_vec, i))->key, - ((t_env *)vec_get(env_vec, i))->value); + value = ((t_env *)vec_get(env_vec, *arr[i]))->value; + if (value) + printf("%s=%s\n", ((t_env *)vec_get(env_vec, *arr[i]))->key, value); i++; } + ft_free_size_t(arr, env_vec->length); exit(0); } diff --git a/src/built_in/exit.c b/src/built_in/exit.c index 3a95f14..0e96bc9 100644 --- a/src/built_in/exit.c +++ b/src/built_in/exit.c @@ -6,14 +6,12 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/04 15:01:59 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 15:25:17 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 20:56:32 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - int long long ft_exit_atoi(char *str) { size_t i; @@ -39,7 +37,7 @@ static bool check_args(t_group *group, t_shell *data) if (group->args[2] != NULL) { write(1, "minishell: exit: too many arguments\n", 37); - g_signal.exit_status = 1; + data->error_type = CATCH_ALL; return (false); } return (true); @@ -66,7 +64,7 @@ void ft_exit(t_group *group, t_shell *data) { printf("minishell: exit: %s: numeric argument required\n", group->args[1]); - g_signal.exit_status = 2; + data->error_type = CATCH_ALL; return ; } i++; diff --git a/src/built_in/export.c b/src/built_in/export.c index 91f85db..41abd2e 100644 --- a/src/built_in/export.c +++ b/src/built_in/export.c @@ -6,47 +6,25 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/31 22:20:10 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 16:08:44 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 21:49:48 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - -/** - * @brief Takes in a string and if it is a valid string, it will return a - * duplicate or if the input equals to NULL it - * will return a duplicate of an empty string - */ -static char *string_handler(char *input) -{ - char *str; - - if (!input) - str = ft_strdup(""); - else - str = ft_strdup(input); - if (!str) - exit_mini("string_handler", 1); - return (str); -} - -static bool validate_input(char *arg, size_t *i) +static bool validate_input(char *arg, size_t *i, t_shell *data) { size_t j; j = 0; if (!ft_isalpha(arg[0])) { - printf("export: `%s': not a valid identifier 1\n", arg); - g_signal.exit_status = 1; + printf("export: `%s': not a valid identifier\n", arg); + data->error_type = CATCH_ALL; return ((*i)++, false); } while (arg[j] && arg[j] != '=') j++; - if (arg[j] == '\0') - return ((*i)++, false); return (true); } @@ -73,7 +51,8 @@ bool compare_env_key(void *item, void *key) * * @param env_vec The vector to add the env token to * @param key The key of the env token - * @param value The value of the env token + * @param value The value of the env token (can be null so export + * and env can function properly) */ static void add_env(t_vector *env_vec, char *key, char *value) { @@ -82,8 +61,8 @@ static void add_env(t_vector *env_vec, char *key, char *value) char *value_dup; key_dup = string_handler(key); - value_dup = string_handler(value); - if (!key_dup || !value_dup) + value_dup = ft_strdup(value); + if (!key_dup) { if (key_dup) free(key_dup); @@ -93,11 +72,29 @@ static void add_env(t_vector *env_vec, char *key, char *value) } token = (t_env *)malloc(sizeof(t_env)); if (!token) + { + free(key_dup); + free(value_dup); return ; + } token->key = key_dup; token->value = value_dup; if (!vec_push(env_vec, token)) - return ; + clear_token(token); +} + +static void export_helper(t_env *token, t_shell *data, char **env) +{ + if (token) + { + if (env[1]) + { + free(token->value); + token->value = ft_strdup(env[1]); + } + } + else + add_env(&data->env, env[0], env[1]); } /** @@ -107,31 +104,25 @@ static void add_env(t_vector *env_vec, char *key, char *value) * @param env_vec The vector that contains the enviroment variables * @return void */ -void ft_export(t_group *group, t_vector *env_vec) +void ft_export(t_group *group, t_shell *data) { size_t i; char **env; t_env *token; i = 1; - print_env_dec(env_vec, group->args[1]); + print_env_dec(&data->env, group->args[1]); while (group->args[i]) { - if (!validate_input(group->args[i], &i)) + if (!validate_input(group->args[i], &i, data)) continue ; - env = ft_split(group->args[i], '='); + env = ft_export_split(group->args[i], '='); if (!env) return ; - token = (t_env *)vec_find_f(env_vec, compare_env_key, env[0]); - if (token) - { - free(token->value); - token->value = string_handler(env[1]); - } - else - add_env(env_vec, env[0], env[1]); + token = (t_env *)vec_find_f(&data->env, compare_env_key, env[0]); + export_helper(token, data, env); ft_free(env); i++; } - g_signal.exit_status = 0; + data->error_type = NO_ERROR; } diff --git a/src/built_in/sort.c b/src/built_in/sort.c new file mode 100644 index 0000000..4980bac --- /dev/null +++ b/src/built_in/sort.c @@ -0,0 +1,106 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* sort.c :+: :+: */ +/* +:+ */ +/* By: mdekker +#+ */ +/* +#+ */ +/* Created: 2023/11/21 17:43:05 by mdekker #+# #+# */ +/* Updated: 2023/11/21 18:22:54 by mdekker ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include + +/** + * @brief A function to compare two keys of the env vector + * + * @param index1 The index of the first key + * @param index2 The index of the second key + * @param enn The vector containing the keys + * @return int The result of the comparison + */ +static int compare_keys(size_t index1, size_t index2, t_vector *env) +{ + return (ft_strcmp(((t_env *)vec_get(env, index1))->key, + ((t_env *)vec_get(env, index2))->key)); +} + +/** + * @brief Quick and dirty bubble sort for size_t arrays + * + * @param arr The array to sort + * @param len The length of the array (same as the env vector) + * @param env The environment vector + */ +void bubble_sort(size_t **arr, size_t len, t_vector *env) +{ + size_t i; + size_t j; + size_t *temp; + + i = 0; + while (i < len) + { + j = 0; + while (j < len - i - 1) + { + if (compare_keys(*arr[j], *arr[j + 1], env) > 0) + { + temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + j++; + } + i++; + } +} + +/** + * @brief A function to free a size_t array + * + * @param arr The array to free + * @param len The length of the array + */ +void ft_free_size_t(size_t **arr, size_t len) +{ + size_t i; + + i = 0; + while (i < len) + { + free(arr[i]); + i++; + } + free(arr); +} + +/** + * @brief Return a sorted set of size_t indexes of the env vector + * + * @param env The vector to sort + * @return size_t** The sorted set of indexes + */ +size_t **return_sorted_arr(t_vector *env) +{ + size_t **sorted_arr; + size_t i; + + i = 0; + sorted_arr = malloc(sizeof(size_t *) * (env->length + 1)); + while (i < env->length) + { + sorted_arr[i] = malloc(sizeof(size_t)); + if (!sorted_arr[i]) + { + ft_free_size_t(sorted_arr, i); + return (NULL); + } + *sorted_arr[i] = i; + i++; + } + sorted_arr[i] = NULL; + bubble_sort(sorted_arr, env->length, env); + return (sorted_arr); +} diff --git a/src/built_in/unset.c b/src/built_in/unset.c index c26b907..bb524b9 100644 --- a/src/built_in/unset.c +++ b/src/built_in/unset.c @@ -6,49 +6,42 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/11/16 22:56:39 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 15:31:20 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 20:57:30 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** * @brief The main function of the unset built_in. It will loop through the * arguments and remove the corresponding environment variables from the - * environment vector. + * environment vector. (if they exist) * * @param group The group struct containing the arguments * @param env_vec The environment vector * @return void - * @note The exit status will be set to 1 if an error occurs */ -void ft_unset(t_group *group, t_vector *env_vec) +void ft_unset(t_group *group, t_shell *data) { - size_t i; - size_t index; - t_env *token; + size_t i; + size_t index; + t_env *token; i = 1; while (group->args[i]) { - token = (t_env *)vec_find_f(env_vec, compare_env_key, group->args[i]); + token = (t_env *)vec_find_f(&data->env, compare_env_key, + group->args[i]); if (token) { - index = (size_t)(token - (t_env *)env_vec->data); - if (!vec_remove(env_vec, index)) + index = (size_t)(token - (t_env *)(&data->env)->data); + if (!vec_remove(&data->env, index)) { - g_signal.exit_status = 1; + exit_mini("ft_unset", 1); return ; } } - else - { - g_signal.exit_status = 0; - return ; - } i++; } - g_signal.exit_status = 0; + data->error_type = NO_ERROR; } diff --git a/src/built_in/utils.c b/src/built_in/utils.c index bf39201..e194b19 100644 --- a/src/built_in/utils.c +++ b/src/built_in/utils.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/11/16 18:52:54 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/17 15:26:12 by mdekker ######## odam.nl */ +/* Updated: 2023/11/21 18:26:53 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -22,14 +22,118 @@ void print_env_dec(t_vector *env, char *arg_2) { size_t i; + size_t **arr; + char *value; i = 0; if (arg_2) return ; + arr = return_sorted_arr(env); while (i < env->length) { - printf("declare -x %s=%s\n", ((t_env *)vec_get(env, i))->key, - ((t_env *)vec_get(env, i))->value); + value = ((t_env *)vec_get(env, *arr[i]))->value; + if (value) + { + printf("declare -x %s=\"%s\"\n", ((t_env *)vec_get(env, + *arr[i]))->key, value); + } + else + printf("declare -x %s\n", ((t_env *)vec_get(env, *arr[i]))->key); i++; } + ft_free_size_t(arr, env->length); +} + +/** + * @brief Updates the value of an environment variable when it already exists or + * creates a new one if it doesn't (used in cd to update PWD and OLDPWD) + * @param env The environment vector + * @param key The key to compare to + * @param value The value to update or create + * @return void + */ +void update_or_create_env(t_vector *env, char *key, char *value) +{ + t_env *env_var; + + env_var = vec_find_f(env, compare_env_key, key); + if (env_var) + { + free(env_var->value); + env_var->value = ft_strdup(value); + } + else + { + if (!vec_push(env, create_env(ft_strdup(key), ft_strdup(value)))) + exit_mini("update_or_create_env", 1); + } +} + +static char **only_key_helper(char *src) +{ + char **ret; + + ret = malloc(sizeof(char *) * 2); + if (!ret) + exit_mini("ft_export_split", 1); + ret[0] = ft_strdup(src); + if (!ret[0]) + exit_mini("ft_export_split", 1); + ret[1] = NULL; + return (ret); +} + +/** + * @brief A version of split that only splits on the first occurence of the + * delimiter and treats the rest as one string + * + * @param src The string to split + * @param delimiter The delimiter to split on + * @return char** The splitted string + */ +char **ft_export_split(char *src, char delimter) +{ + char **ret; + size_t i; + + if (!ft_strchr(src, '=')) + return (only_key_helper(src)); + ret = malloc(sizeof(char *) * 3); + if (!ret) + exit_mini("ft_export_split", 1); + i = 0; + while (src[i] && src[i] != delimter) + i++; + ret[0] = ft_substr(src, 0, i); + if (!ret[0]) + exit_mini("ft_export_split", 1); + if (src[i] == delimter) + { + i++; + ret[1] = ft_strdup(src + i); + if (!ret[1]) + exit_mini("ft_export_split", 1); + } + else + ret[1] = NULL; + ret[2] = NULL; + return (ret); +} + +/** + * @brief Takes in a string and if it is a valid string, it will return a + * duplicate or if the input equals to NULL it + * will return a duplicate of an empty string + */ +char *string_handler(char *input) +{ + char *str; + + if (!input) + str = ft_strdup(""); + else + str = ft_strdup(input); + if (!str) + exit_mini("string_handler", 1); + return (str); } diff --git a/src/checker/helpers.c b/src/checker/helpers.c index 7c0470a..ad4e595 100644 --- a/src/checker/helpers.c +++ b/src/checker/helpers.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/09/11 21:12:42 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/26 13:04:49 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/21 14:48:24 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -18,6 +18,14 @@ void free_found(t_vector *found) free(found); } +bool filter_operators(void *item) +{ + t_token *token; + + token = (t_token *)item; + return (token->type >= 2 && token->type <= 7); +} + // /** // * @brief Checks if the tokens contain OR and AND operators because they // * are bonus and were not implementing that. diff --git a/src/checker/index.c b/src/checker/index.c index e3a4746..0a917af 100644 --- a/src/checker/index.c +++ b/src/checker/index.c @@ -6,20 +6,12 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/08/02 16:57:32 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/03 15:04:37 by mdekker ######## odam.nl */ +/* Updated: 2023/11/21 14:48:16 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ #include -bool filter_operators(void *item) -{ - t_token *token; - - token = (t_token *)item; - return (token->type >= 2 && token->type <= 7); -} - static bool check_double_ops(t_vector *found, t_shell *data) { t_found *c_found; diff --git a/src/debug/print_vector.c b/src/debug/print_vector.c index 6ebc961..8409103 100644 --- a/src/debug/print_vector.c +++ b/src/debug/print_vector.c @@ -6,28 +6,13 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/20 13:51:45 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/30 19:01:03 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/20 20:39:27 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include #include -void print_stack_trace(void) -{ - void *array[10]; - size_t size; - char **strings; - size_t i; - - size = backtrace(array, 10); - strings = backtrace_symbols(array, size); - printf("Obtained %zd stack frames.\n", size); - for (i = 0; i < size; i++) - printf("%s\n", strings[i]); - free(strings); -} - /** * @brief Prints data in a vector in a pretty way * @@ -39,8 +24,6 @@ void print_vector(t_vector *vec, void (*printer)(void *, size_t)) size_t i; i = 0; - if (!DEBUG) - return ; while (i < vec->length) { printer(vec_get(vec, i), i); diff --git a/src/exec/create_processes.c b/src/exec/create_processes.c index 847c221..e69c81e 100644 --- a/src/exec/create_processes.c +++ b/src/exec/create_processes.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/08/19 12:40:07 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/12 20:17:37 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/22 14:13:18 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -30,11 +30,11 @@ static bool set_pipe(t_group *group, size_t i, size_t count, t_shell *data) static void call_process(t_group *group, size_t i, size_t count, t_shell *data) { if (i == 0) - exec_process(group, LEFT, (&data->env)); + exec_process(group, LEFT, data); else if ((i == 1 && count == 2) || (count > 2 && i == count - 1)) - exec_process(group, RIGHT, (&data->env)); + exec_process(group, RIGHT, data); else - exec_process(group, MIDDLE, (&data->env)); + exec_process(group, MIDDLE, data); } static void set_group_and_close(t_group *group, pid_t pid, size_t i) @@ -83,6 +83,7 @@ bool create_processes(t_shell *data) t_vector *group_vec; t_group *group; + setup_child_signals(); group_vec = &data->exec->group_vec; if (group_vec->length == 1) { @@ -91,7 +92,7 @@ bool create_processes(t_shell *data) if (group->pd == -1) return (set_err(PERR, NULL, data)); if (group->pd == 0) - exec_process(group, SINGLE, (&data->env)); + exec_process(group, SINGLE, data); } else fork_and_pipe(data); diff --git a/src/exec/exec.c b/src/exec/exec.c index d3d6758..864f23d 100644 --- a/src/exec/exec.c +++ b/src/exec/exec.c @@ -6,14 +6,12 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/31 19:55:50 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/14 12:15:57 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/20 17:43:12 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** * @brief waits for processes to complete * @brief sets exit_status to the exit status of the last process to complete @@ -42,7 +40,7 @@ static int wait_processes(t_vector *group_vec, t_shell *data, { if (success == true) { - g_signal.exit_status = WEXITSTATUS(temp); + data->error_type = WEXITSTATUS(temp); return (true); } return (set_err(PERR, NULL, data)); @@ -52,9 +50,9 @@ static int wait_processes(t_vector *group_vec, t_shell *data, /** * @brief creates pipes and starts processes, - closes pipes and waits for child_processes + * closes pipes and waits for child_processes * @return return value is the EXITSTATUS of the last childprocess to complete - @note sets g_signal.exit_status + * @note sets the data error_type */ bool executor(t_shell *data) { diff --git a/src/exec/exec_builtin.c b/src/exec/exec_builtin.c index 21678b9..d5d73da 100644 --- a/src/exec/exec_builtin.c +++ b/src/exec/exec_builtin.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/09/11 14:04:28 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/16 23:19:34 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/20 17:54:00 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -15,7 +15,7 @@ /** * @note check if dup_fd or redirects should be done for the built_in */ -void exec_built_in(t_group *group, t_process type, t_vector *env_vec) +void exec_built_in(t_group *group, t_process type, t_shell *data) { dup_fd(group, type); if (is_special_builtin(group->cmd)) @@ -25,7 +25,7 @@ void exec_built_in(t_group *group, t_process type, t_vector *env_vec) else if (ft_strcmp(group->cmd, "pwd") == 0) ft_pwd(); else if (ft_strcmp(group->cmd, "env") == 0) - ft_env(env_vec); + ft_env(&data->env); } void exec_special_builtin(t_group *group, t_shell *data) @@ -33,9 +33,9 @@ void exec_special_builtin(t_group *group, t_shell *data) if (ft_strcmp(group->cmd, "exit") == 0) ft_exit(group, data); else if (ft_strcmp(group->cmd, "cd") == 0) - ft_cd(group, &data->env); + ft_cd(group, data); else if (ft_strcmp(group->cmd, "export") == 0) - ft_export(group, &data->env); + ft_export(group, data); else if (ft_strcmp(group->cmd, "unset") == 0) - ft_unset(group, &data->env); + ft_unset(group, data); } diff --git a/src/exec/exec_process.c b/src/exec/exec_process.c index 49a6d56..bab963f 100644 --- a/src/exec/exec_process.c +++ b/src/exec/exec_process.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/08/19 16:08:08 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/03 21:24:01 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/22 14:14:21 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -52,18 +52,19 @@ void dup_fd(t_group *group, t_process type) handle_redirects(group); } -void exec_process(t_group *group, t_process type, t_vector *env_vec) +void exec_process(t_group *group, t_process type, t_shell *data) { char **env; close_unused(type, group); validate_redirects(group); + dup_fd(group, type); if (group->cmd == NULL) - exit (0); + exit(0); if (is_builtin(group->cmd)) - exec_built_in(group, type, env_vec); - check_cmd(group, type, env_vec); - env = combine_env(env_vec); + exec_built_in(group, type, data); + check_cmd(group, type, &data->env); + env = combine_env(&data->env); dup_fd(group, type); if (!execve(group->cmd, group->args, env)) exec_err(NULL, PERR); diff --git a/src/exec/utils.c b/src/exec/utils.c index 3ae5683..f98f765 100644 --- a/src/exec/utils.c +++ b/src/exec/utils.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/09/01 19:44:05 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/14 16:21:13 by mdekker ######## odam.nl */ +/* Updated: 2023/11/22 14:15:03 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -34,11 +34,23 @@ bool is_special_builtin(char *str) return (false); } +static int protected_strlen(char *s) +{ + int i; + + i = 0; + if (!s) + return (0); + while (s[i]) + i++; + return (i); +} + char **combine_env(t_vector *env_vec) { - char **env; - t_env *env_token; - size_t i; + char **env; + t_env *env_token; + size_t i; i = 0; env = malloc(sizeof(char *) * (env_vec->length + 1)); @@ -48,7 +60,7 @@ char **combine_env(t_vector *env_vec) { env_token = vec_get(env_vec, i); env[i] = ft_calloc(ft_strlen(env_token->key) - + ft_strlen(env_token->value) + 2, sizeof(char)); + + protected_strlen(env_token->value) + 2, sizeof(char)); ft_strcpy(env[i], env_token->key); ft_strcat(env[i], "="); ft_strcat(env[i], env_token->value); diff --git a/src/expander/expand_env.c b/src/expander/expand_env.c index 0176196..2c6ed3e 100644 --- a/src/expander/expand_env.c +++ b/src/expander/expand_env.c @@ -6,21 +6,19 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/26 16:02:26 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/14 16:21:20 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 17:38:25 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - static bool push_status(size_t *i, t_vector *vec, t_shell *data) { char *exit_string; int j; (*i)++; - exit_string = ft_itoa(g_signal.exit_status); + exit_string = ft_itoa(data->error_type); if (!exit_string) return (set_err(MALLOC, "push_status", data)); j = 0; @@ -88,7 +86,7 @@ bool expand_env(char *str, size_t *i, t_vector *vec, t_shell *data) if (!env_token) return (true); j = 0; - while (env_token->value[j]) + while (env_token->value && env_token->value[j]) { if (!char_vec_push(vec, env_token->value[j])) return (set_err(MALLOC, "expand_env", data)); diff --git a/src/expander/index.c b/src/expander/index.c index 41a78e4..a0ea7ab 100644 --- a/src/expander/index.c +++ b/src/expander/index.c @@ -76,7 +76,7 @@ static bool expand(t_token *token, t_shell *data) t_vector expanded_string; size_t i; - if (!vec_init(&expanded_string, 10, sizeof(char), NULL)) + if (!vec_init(&expanded_string, 200, sizeof(char), NULL)) return (set_err(MALLOC, "expand", data)); i = 0; while (token->value[i]) diff --git a/src/expander/split.c b/src/expander/split.c deleted file mode 100644 index 0ed4001..0000000 --- a/src/expander/split.c +++ /dev/null @@ -1,53 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* split.c :+: :+: */ -/* +:+ */ -/* By: mdekker/jde-baai +#+ */ -/* +#+ */ -/* Created: 2023/10/14 22:07:22 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/14 22:21:52 by mdekker/jde ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include - -/** - * @brief Gets the amount of splits that will be made - * so the double pointer can be - * - * This assumes it should split on spaces and dollar signs - * and add one for the last split - * - * @param str The string to split - * @return size_t The amount of splits - */ -static size_t get_split_amount(char *str) -{ - size_t i; - size_t splits; - - i = 0; - splits = 0; - - while (str[i]) - { - if (str[i] == '$' || str[i] == ' ') - splits++; - // check if the next character is a dollar sign or space and if not skip over it - i++; - } - -} - -/** - * @brief Splits the string on spaces and dollar signs including the string - * between the dollar signs - * - * @param data The data struct - * @return char ** The split string - */ -char **split_env(char *str, t_shell *data) -{ - -} diff --git a/src/group/group.c b/src/group/group.c index 36d553e..a8121ed 100644 --- a/src/group/group.c +++ b/src/group/group.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/31 19:55:05 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/30 21:54:33 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/21 20:48:13 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -66,7 +66,7 @@ bool alloc_args(t_group *group, size_t i, t_shell *data) /** * @note check the else statement depending on how we will handle quotes - (ie. could be else if (token->type == STRING + (ie. could be else if (token->type == STRING || token->type == QUOTE_STRING) * */ @@ -141,13 +141,14 @@ bool group_token_vec(t_shell *data) if (!group) return (set_err(MALLOC, "group_token_v", data)); if (!set_cmd(group, i, data)) - return (false); + return (clear_group(group), free(group), false); if (!alloc_args(group, i, data)) - return (false); + return (clear_group(group), free(group), false); if (!group_tokens(group, &i, data)) - return (false); + return (clear_group(group), free(group), false); if (!vec_push(&data->exec->group_vec, group)) - return (set_err(MALLOC, "group_token_v", data)); + return (clear_group(group), free(group), set_err(MALLOC, + "group_token_v", data)); i++; } return (true); diff --git a/src/group/hdoc_expand.c b/src/group/hdoc_expand.c index 03d5a43..77d3f6a 100644 --- a/src/group/hdoc_expand.c +++ b/src/group/hdoc_expand.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/30 22:03:02 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/30 22:38:55 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/18 20:33:47 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -51,4 +51,4 @@ bool hdoc_expand(char **str, t_shell *data) } } return ((str_vec_to_string(&vec, str, data))); -} +} diff --git a/src/group/heredoc.c b/src/group/heredoc.c index 228d4f4..66244d6 100644 --- a/src/group/heredoc.c +++ b/src/group/heredoc.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/08/16 12:15:45 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/30 22:42:16 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/22 14:22:03 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -14,70 +14,81 @@ static bool push_hdoc(char *filename, t_group *group, t_shell *data) { - char *fname; - t_token *fname_token; + char **fname; t_token *red_token; - fname = ft_strdup(filename); + fname = malloc(sizeof(char *)); if (!fname) return (set_err(MALLOC, "push_hdoc", data)); red_token = create_token(filename, I_REDIRECT); if (!red_token) - return (set_err(MALLOC, "push_hdoc", data)); + return (free(fname), set_err(MALLOC, "push_hdoc", data)); if (!vec_push(&group->in_red, (void *)red_token)) - return (set_err(MALLOC, "push_hdoc", data)); - fname_token = create_token(fname, STRING); - if (!fname_token) - return (set_err(MALLOC, "push_hdoc", data)); - if (!vec_push(&data->exec->fname_vec, (void *)fname_token)) - return (set_err(MALLOC, "push_hdoc", data)); + return (free(fname), set_err(MALLOC, "push_hdoc", data)); + *fname = ft_strdup(filename); + if (!*fname) + return (free(fname), set_err(MALLOC, "push_hdoc", data)); + if (!vec_push(&data->exec->fname_vec, (void *)fname)) + return (free(*fname), free(fname), set_err(MALLOC, "push_hdoc", data)); return (true); } - - /** * @note if signal ctrl D break while loop and return true */ -static bool hdoc_read(size_t heredoc_fd, t_token *token, t_shell *data) +static void heredoc(char *filename, t_token *token, t_shell *data) { char *line; + int heredoc_fd; - // char *expanded_line; + setup_hdoc_signals(); + heredoc_fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644); + if (heredoc_fd == -1) + exec_err(NULL, PERR); while (1) { line = readline(">"); - if (!line || ft_strcmp(line, token->value) == 0) + if (line == NULL || ft_strcmp(line, token->value) == 0) break ; if (token->type != HDOC_LITERAL) { if (!hdoc_expand(&line, data)) - return (false); + exec_err("hdoc_expand", MALLOC); } write(heredoc_fd, line, ft_strlen(line)); write(heredoc_fd, "\n", 1); free(line); } free(line); - return (true); + if (close(heredoc_fd) != 0) + exec_err(NULL, PERR); + exit(0); } /** * @param filename the filename to be given to the new file * @param token the hdoc token - * @note depending on expansion DQ logic can be removed + * @note writes its own error messages. */ -bool heredoc(char *filename, t_token *token, t_shell *data) +bool hdoc_child(char *filename, t_token *token, t_shell *data) { - int heredoc_fd; + pid_t pid; + int status; - heredoc_fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644); - if (heredoc_fd == -1) - return (set_err(PERR, filename, data)); - if (!hdoc_read(heredoc_fd, token, data)) - return (close(heredoc_fd), false); - if (close(heredoc_fd) != 0) - return (set_err(PERR, filename, data)); + pid = fork(); + if (pid == -1) + return (set_err(PERR, NULL, data)); + if (pid == 0) + heredoc(filename, token, data); + else + { + waitpid(pid, &status, 0); + if (WEXITSTATUS(status) != 0) + { + data->error_type = WEXITSTATUS(status); + return (false); + } + } return (true); } @@ -92,12 +103,17 @@ bool hdoc_found(t_group *group, size_t i, t_shell *data) { t_token *token; char *filename; + char *nb; - filename = ft_strjoin("./src/hdoc_files/", ft_itoa((i))); + nb = ft_itoa(i); + filename = ft_strjoin("./src/hdoc_files/", nb); + free(nb); if (!filename) return (set_err(MALLOC, "hdoc_found", data)); + if (!push_hdoc(filename, group, data)) + return (false); token = vec_get(&data->token_vec, i); - if (!heredoc(filename, token, data)) + if (!hdoc_child(filename, token, data)) return (false); - return (push_hdoc(filename, group, data)); + return (true); } diff --git a/src/lexer/index.c b/src/lexer/index.c index 79bed1c..09468ae 100644 --- a/src/lexer/index.c +++ b/src/lexer/index.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/10/26 11:55:20 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/03 14:46:50 by mdekker ######## odam.nl */ +/* Updated: 2023/11/22 14:17:00 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -56,7 +56,7 @@ static bool check_quote_finish(char *input, size_t *i, t_shell *data) while (input[(*i)] && input[(*i)] != quote) (*i)++; if (input[(*i)] == '\0') - return (set_err(SYNTAX_MINI, (char[2]){quote, '\0'}, data)); + return (set_err(SYNTAX_MINI, NULL, data)); (*i)++; return (true); } @@ -107,7 +107,7 @@ bool lexer(char *input, t_shell *data) { if (checkchar(input[i], "();\\&")) { - return (set_err(OUT_OF_SCOPE, (char[2]){input[i], '\0'}, data)); + return (set_err(OUT_OF_SCOPE, NULL, data)); } if (checkchar(input[i], "<>")) if (!build_redir_token(input, &i, data)) diff --git a/src/main.c b/src/main.c index 1fd5fd0..962bd13 100644 --- a/src/main.c +++ b/src/main.c @@ -6,21 +6,22 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/12 14:11:01 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/14 16:21:52 by mdekker ######## odam.nl */ +/* Updated: 2023/11/22 14:27:56 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ #include -t_signal g_signal; - -static void debug(void) +/** + * @brief sets up signal handling and avoid readline catching sigs + * @note SIGINT = Ctrl-C + * @note SIGQUIT = Ctrl-\ + */ +static void setup_signals(void) { - printf("\033[1;32m●\n"); - printf("\033[1;34m│\n"); - printf("├── Debug mode enabled\n"); - printf("\033[1;34m│\n"); - printf("\033[0m"); + rl_catch_signals = 0; + signal(SIGINT, signal_main); + signal(SIGQUIT, SIG_IGN); } static void soft_exit(char *input, t_shell *data) @@ -33,8 +34,8 @@ static void soft_exit(char *input, t_shell *data) static bool function_map(char *input, t_shell *data) { - bool (*function[5])(t_shell *); - int i; + int i; + static bool (*function[5])(t_shell *); function[0] = parser; function[1] = check_tokens; @@ -42,7 +43,7 @@ static bool function_map(char *input, t_shell *data) function[3] = group_token_vec; function[4] = executor; if (!lexer(input, data)) - return (false); + return (soft_exit(input, data), false); i = -1; while (i++ < 4) { @@ -63,8 +64,15 @@ static void loop(t_shell *data) while (1) { - input = readline("\nminishell\n❯ "); - if (!input || input[0] == '\0') + setup_signals(); + input = readline(" ❯ "); + if (input == NULL) + { + free_shell(data, true); + printf("exit\n"); + exit(0); + } + if (input[0] == '\0') { free(input); continue ; @@ -83,11 +91,9 @@ int main(int ac, char **av, char **env) t_shell *data; (void)av; - if (DEBUG) - debug(); if (ac != 1) { - write(2, "Too many arguments\n", 20); + write(2, "Too maaaaaaaaaaany arguments\n", 20); return (1); } data = init_shell(env, true); diff --git a/src/parser/index.c b/src/parser/index.c index cc9b03d..742096a 100644 --- a/src/parser/index.c +++ b/src/parser/index.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/20 11:12:20 by mdekker #+# #+# */ -/* Updated: 2023/10/30 18:34:57 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/21 13:39:14 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -63,7 +63,6 @@ void parse_loop(t_vector *vec, t_func_map *func_map) break ; } token->type = func_map[j].type; - // print_token(token, j); } i++; } diff --git a/src/parser/tokens.c b/src/parser/tokens.c index 9f241e3..5a8f56e 100644 --- a/src/parser/tokens.c +++ b/src/parser/tokens.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* :::::::: */ -/* token_vec.c :+: :+: */ +/* tokens.c :+: :+: */ /* +:+ */ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/20 14:50:46 by mdekker/jde #+# #+# */ -/* Updated: 2023/08/04 04:14:11 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/21 17:14:11 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ diff --git a/src/signals/index.c b/src/signals/index.c new file mode 100644 index 0000000..898e28a --- /dev/null +++ b/src/signals/index.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* index.c :+: :+: */ +/* +:+ */ +/* By: mdekker/jde-baai +#+ */ +/* +#+ */ +/* Created: 2023/11/17 11:36:59 by mdekker/jde #+# #+# */ +/* Updated: 2023/11/22 00:16:17 by mdekker/jde ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include + +extern t_signal g_signal; + +void signal_main(int signal_num) +{ + if (signal_num == SIGINT) + { + write(1, "\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); + } +} + +/** + * @brief sets up signal handling and avoid readline catching sigs + * @note SIGINT = Ctrl-C + * @note SIGQUIT = Ctrl-\ + */ +void setup_hdoc_signals(void) +{ + rl_catch_signals = 1; + signal(SIGINT, signal_hdoc); + signal(SIGQUIT, SIG_IGN); +} + +void signal_hdoc(int signal_num) +{ + if (signal_num == SIGINT) + { + exit(130); + } +} + +void setup_child_signals(void) +{ + signal(SIGINT, signal_child); + signal(SIGQUIT, signal_child); +} + +void signal_child(int signal_num) +{ + if (signal_num == SIGINT) + { + write(1, "\n", 1); + } + else if (signal_num == SIGQUIT) + { + write(1, "Quit\n", 5); + } +} diff --git a/src/structs/env.c b/src/structs/env.c index de819ae..f83da82 100644 --- a/src/structs/env.c +++ b/src/structs/env.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/21 02:54:34 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/07 16:02:23 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 20:53:20 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ diff --git a/src/structs/group.c b/src/structs/group.c index c4674ff..7c8d13f 100644 --- a/src/structs/group.c +++ b/src/structs/group.c @@ -6,7 +6,7 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/08/02 20:42:59 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/12 21:25:36 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/19 13:54:50 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -39,14 +39,14 @@ void clear_group(void *data) void clear_fname(void *data) { - t_token *filename; + char **filename; if (!data) return ; - filename = (t_token *)data; - if (-1 == unlink(filename->value)) + filename = (char **)data; + if (-1 == unlink(*filename)) perror("minishell"); - free(filename->value); + free(*filename); filename = NULL; } @@ -102,7 +102,7 @@ t_exec *create_exec(void) free(exec); return (NULL); } - if (!vec_init(&exec->fname_vec, 1, sizeof(t_token), clear_fname)) + if (!vec_init(&exec->fname_vec, 1, sizeof(char **), clear_fname)) { vec_free(&exec->group_vec); free(exec); diff --git a/src/structs/shell.c b/src/structs/shell.c index a699baa..c7375c8 100644 --- a/src/structs/shell.c +++ b/src/structs/shell.c @@ -6,14 +6,12 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/09/03 18:11:09 by mdekker/jde #+# #+# */ -/* Updated: 2023/11/14 16:21:24 by mdekker ######## odam.nl */ +/* Updated: 2023/11/20 20:57:12 by mdekker/jde ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** * @brief frees the main data struct * @param data t_shell data @@ -36,16 +34,41 @@ void free_shell(t_shell *data, bool close_shell) } /** - * @brief Create a g_signal struct object - * - * @return t_signal The created g_signal struct + * @brief A helper function for init_shell for the first init + * @param env The enviroment char array + * @return t_shell* The created data struct */ -void create_signal_struct(void) +static t_shell *init_first_shell(char **env) { - g_signal.inte = false; - g_signal.quit = false; - g_signal.pipe = false; - g_signal.exit_status = 0; + t_shell *data; + + data = malloc(sizeof(t_shell)); + if (!data) + exit_mini("failed to init data", 1); + if (!vec_init(&data->token_vec, 3, sizeof(t_token), clear_token)) + exit_mini("failed to vec_init token_vec", 1); + if (!vec_init(&data->env, 50, sizeof(t_env), clear_env)) + exit_mini("failed to vec_init env", 1); + init_env(env, &data->env); + data->exec = NULL; + data->exit_type = GOOD; + data->error_type = NO_ERROR; + data->exit_msg = NULL; + return (data); +} + +/** + * @brief A helper function for init_shell for the subsequent inits + * @return t_shell* The created data struct + */ +static t_shell *init_subsequent_shell(t_shell *data) +{ + if (!vec_init(&data->token_vec, 3, sizeof(t_token), clear_token)) + exit_mini("failed to vec_init env", 1); + data->exec = NULL; + data->exit_type = GOOD; + data->exit_msg = NULL; + return (data); } /** @@ -62,27 +85,8 @@ t_shell *init_shell(char **env, bool first_init) data = NULL; if (first_init) - { - data = malloc(sizeof(t_shell)); - if (!data) - exit_mini("failed to init data", 1); - if (!vec_init(&data->token_vec, 3, sizeof(t_token), clear_token)) - exit_mini("failed to vec_init token_vec", 1); - if (!vec_init(&data->env, 50, sizeof(t_env), clear_env)) - exit_mini("failed to vec_init env", 1); - init_env(env, &data->env); - data->exec = NULL; - data->exit_type = GOOD; - data->exit_msg = NULL; - create_signal_struct(); - } + data = init_first_shell(env); else - { - if (!vec_init(&data->token_vec, 3, sizeof(t_token), clear_token)) - exit_mini("failed to vec_init env", 1); - data->exec = NULL; - data->exit_type = GOOD; - data->exit_msg = NULL; - } + init_subsequent_shell(data); return (data); } diff --git a/src/utils/error.c b/src/utils/error.c index b772118..6ef9e58 100644 --- a/src/utils/error.c +++ b/src/utils/error.c @@ -6,14 +6,12 @@ /* By: mdekker/jde-baai +#+ */ /* +#+ */ /* Created: 2023/07/19 21:42:24 by mdekker/jde #+# #+# */ -/* Updated: 2023/10/07 19:17:47 by mdekker/jde ######## odam.nl */ +/* Updated: 2023/11/22 14:18:28 by mdekker ######## odam.nl */ /* */ /* ************************************************************************** */ #include -extern t_signal g_signal; - /** * @brief called if there is an error in minihsell that should close the program * @@ -25,12 +23,12 @@ void exit_mini(char *str, int exit_code) { if (str) { - write(STDERR_FILENO, "minishell: ", 11); + write(STDERR_FILENO, "minishell: ", 12); write(STDERR_FILENO, str, ft_strlen(str)); write(STDERR_FILENO, "\n", 1); } else - write(STDERR_FILENO, "minishell: error\n", 16); + write(STDERR_FILENO, "minishell: error\n", 18); exit(exit_code); } @@ -57,43 +55,35 @@ void write_err(t_shell *data) if (data->exit_type == PERR) { perror("minishell"); - g_signal.exit_status = errno; + data->error_type = errno; } if (data->exit_type == MALLOC) { - write(STDERR_FILENO, "minishell: malloc error in : ", 28); + write(STDERR_FILENO, "minishell: malloc error in : ", 30); write(STDERR_FILENO, data->exit_msg, ft_strlen(data->exit_msg)); write(STDERR_FILENO, "\n", 1); - g_signal.exit_status = 1; + data->error_type = CATCH_ALL; } if (data->exit_type == SYNTAX) { write(STDERR_FILENO, "minishell: syntax error near unexpected token `", - 47); + 48); write(STDERR_FILENO, data->exit_msg, ft_strlen(data->exit_msg)); write(STDERR_FILENO, "'\n", 2); - g_signal.exit_status = 258; + data->error_type = SYNTAX_ERROR; } if (data->exit_type == SYNTAX_MINI) { - write(STDERR_FILENO, "minishell: unfinished operator : `", 34); - write(STDERR_FILENO, data->exit_msg, ft_strlen(data->exit_msg)); - write(STDERR_FILENO, "`\n", 2); - g_signal.exit_status = 2; + write(STDERR_FILENO, "minishell: syntax error: unfinished quote\n", 43); + data->error_type = 2; } if (data->exit_type == OUT_OF_SCOPE) { - write(STDERR_FILENO, "minishell: operator: `", 23); - write(STDERR_FILENO, data->exit_msg, ft_strlen(data->exit_msg)); - write(STDERR_FILENO, "`: out of project scope\n", 25); - g_signal.exit_status = 2; + write(2, "minishell: operators: () ; \\ & ||: out of scope\n", 49); + data->error_type = 2; } if (data->exit_type == SIGNAL_C) - { - write(STDERR_FILENO, "^C\n", 3); - g_signal.exit_status = 130; - } - free_shell(data, false); + data->error_type = 130; } /** @@ -108,30 +98,30 @@ void exec_err(char *str, t_exit type) } if (type == MALLOC) { - write(STDERR_FILENO, "minishell: malloc error in : ", 28); + write(STDERR_FILENO, "minishell: malloc error in : ", 30); write(STDERR_FILENO, str, ft_strlen(str)); write(STDERR_FILENO, "\n", 1); exit(1); } if (type == NOT_FOUND) { - write(STDERR_FILENO, "minishell: ", 11); + write(STDERR_FILENO, "minishell: ", 12); write(STDERR_FILENO, str, ft_strlen(str)); - write(STDERR_FILENO, ": command not found\n", 20); + write(STDERR_FILENO, ": command not found\n", 21); exit(127); } if (type == PERMISSION) { - write(STDERR_FILENO, "minishell: ", 11); + write(STDERR_FILENO, "minishell: ", 12); write(STDERR_FILENO, str, ft_strlen(str)); - write(STDERR_FILENO, ": Permission denied\n", 20); + write(STDERR_FILENO, ": Permission denied\n", 21); exit(126); } if (type == NO_SUCH) { - write(STDERR_FILENO, "minishell: ", 11); + write(STDERR_FILENO, "minishell: ", 12); write(STDERR_FILENO, str, ft_strlen(str)); - write(STDERR_FILENO, ": No such file or directory\n", 28); + write(STDERR_FILENO, ": No such file or directory\n", 29); exit(1); } } diff --git a/src/utils/miscellaneous.c b/src/utils/miscellaneous.c index 6bc7c8d..3ae2954 100644 --- a/src/utils/miscellaneous.c +++ b/src/utils/miscellaneous.c @@ -21,8 +21,8 @@ bool is_redirect(t_token *token) { if (token->type == O_REDIRECT || token->type == I_REDIRECT - || token->type == A_REDIRECT || token->type == HEREDOC || - token->type == HDOC_LITERAL) + || token->type == A_REDIRECT || token->type == HEREDOC + || token->type == HDOC_LITERAL) { return (true); }