From f4cfae11074ee70b6639da94daea8e16193ecfd0 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 14 Feb 2026 02:01:10 +0100 Subject: [PATCH] feat: added internal variables --- include/builtins.h | 3 +- include/core.h | 15 +- include/errors.h | 3 +- include/minishell.h | 5 +- include/variables.h | 43 ++++ src/executor/command_exec.c | 8 +- src/executor/path_resolver.c | 3 +- src/minishell.c | 16 +- src/parser/parser_expand.c | 8 +- src/variables/{ => environment}/environment.c | 217 +++++++++--------- src/variables/environment_unset.c | 41 ---- src/variables/internal/internal.c | 120 ++++++++++ src/variables/variables.c | 50 ++++ 13 files changed, 352 insertions(+), 180 deletions(-) create mode 100644 include/variables.h rename src/variables/{ => environment}/environment.c (59%) delete mode 100644 src/variables/environment_unset.c create mode 100644 src/variables/internal/internal.c create mode 100644 src/variables/variables.c diff --git a/include/builtins.h b/include/builtins.h index 01ae629..94754c9 100644 --- a/include/builtins.h +++ b/include/builtins.h @@ -6,7 +6,7 @@ /* By: sede-san // tgetent(3), tgetflag(3), tgetnum(3), // tgetstr(3), tgoto(3), tputs(3) -void handle_sigint_status(t_minishell *minishell); -bool handle_eof(char *line, t_minishell *minishell); - #endif /* MINISHELL_H */ diff --git a/include/variables.h b/include/variables.h new file mode 100644 index 0000000..8b4b944 --- /dev/null +++ b/include/variables.h @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variables.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san path); exit(exit_status); } diff --git a/src/executor/path_resolver.c b/src/executor/path_resolver.c index 67cb80e..dc033cc 100644 --- a/src/executor/path_resolver.c +++ b/src/executor/path_resolver.c @@ -6,11 +6,12 @@ /* By: sede-san prompt.ps1 = DEFAULT_PS1; - minishell->prompt.ps2 = DEFAULT_PS2; -} - void minishell_init( t_minishell *minishell, char **envp ){ ft_bzero(minishell, sizeof(t_minishell)); + set_intp(minishell); set_envp(envp, minishell); set_builtins(minishell); - set_prompts(minishell); if (minishell->variables.environment == NULL || minishell->builtins == NULL) minishell_clear(minishell); } @@ -47,7 +39,7 @@ void minishell_run( while (!minishell->exit) { if (isatty(STDIN_FILENO)) - line = readline(minishell->prompt.ps1); + line = readline(DEFAULT_PS1); else line = get_next_line(STDIN_FILENO); handle_sigint_status(minishell); @@ -67,6 +59,8 @@ void minishell_clear( t_minishell *minishell ){ rl_clear_history(); + if (minishell->variables.internal != NULL) + ft_hashmap_clear(&minishell->variables.internal, free); if (minishell->variables.environment != NULL) ft_hashmap_clear(&minishell->variables.environment, free); if (minishell->builtins != NULL) diff --git a/src/parser/parser_expand.c b/src/parser/parser_expand.c index 1ef4782..1a4d752 100644 --- a/src/parser/parser_expand.c +++ b/src/parser/parser_expand.c @@ -6,12 +6,13 @@ /* By: sede-san exit = true, malloc_error()); - variable_value = get_env(variable_name, minishell); + variable_value = get_var(variable_name, minishell); free(variable_name); if (variable_value == NULL) variable_value = ""; diff --git a/src/variables/environment.c b/src/variables/environment/environment.c similarity index 59% rename from src/variables/environment.c rename to src/variables/environment/environment.c index 3461a4a..6b72f39 100644 --- a/src/variables/environment.c +++ b/src/variables/environment/environment.c @@ -6,65 +6,33 @@ /* By: sede-san variables.environment - = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp); - if (msh->variables.environment == NULL) - return ; - while (*envp != NULL) - { - equal_sign = ft_strchr(*envp, '='); - if (equal_sign == NULL) - { - key = ft_strdup(*envp); - value = ft_strdup(""); - } - else - { - key = ft_substr(*envp, 0, equal_sign - *envp); - value = ft_strdup(equal_sign + 1); - } - if (key == NULL || value == NULL) - { - free(key); - free(value); - ft_hashmap_clear(&msh->variables.environment, free); - return ; - } - ft_hashmap_put(msh->variables.environment, key, value); - envp++; - } +char *get_env( + const char *name, + t_minishell *minishell +) +{ + return (ft_hashmap_get(minishell->variables.environment, name)); } /** @@ -75,29 +43,72 @@ void set_envp( * the old value is freed to prevent memory leaks. If the variable is new, * a duplicate of the key name is created for storage. * - * @param env_name The name of the environment variable to set - * @param env_value The value to assign to the environment variable - * @param msh Pointer to the minishell structure containing the - * environment hashmap + * @param name The name of the environment variable to set + * @param value The value to assign to the environment variable + * @param minishell Pointer to the minishell object. */ void set_env( - const char *env_name, - char *env_value, - t_minishell *msh -) { - t_hashmap *environment; - const char *key; - char *old_value; + const char *name, + char *value, + t_minishell *minishell +) +{ + t_hashmap *environment; + char *key; + char *val; + char *old_value; - environment = msh->variables.environment; - key = env_name; - if (!ft_hashmap_contains_key(environment, key)) - key = ft_strdup(env_name); - old_value = ft_hashmap_put(environment, key, ft_strdup(env_value)); + environment = minishell->variables.environment; + key = (char *)name; + if (key != NULL && !ft_hashmap_contains_key(environment, key)) + { + key = ft_strdup(name); + if (key == NULL) + { + minishell->exit = true; + malloc_error(); + return ; + } + } + val = value; + if (val != NULL) + val = ft_strdup(value); + if (val == NULL) + { + if (key != name) + free(key); + minishell->exit = true; + malloc_error(); + return ; + } + old_value = ft_hashmap_put(environment, key, val); if (old_value != NULL) free(old_value); } +/** + * @brief Removes an environment variable by name. + * + * @param name The name of the environment variable to remove. + * @param minishell Pointer to the minishell structure. + * + * @note If the environment variable exists, it will be removed from the hashmap + * and its associated value will be freed. + */ +void unset_env( + const char *name, + t_minishell *minishell +) +{ + t_hashmap *environment; + char *val; + + environment = minishell->variables.environment; + val = ft_hashmap_remove(environment, (void *)name); + if (val != NULL) + free(val); +} + /** * @brief Converts the environment variables hashmap to an envp array format. * @@ -105,7 +116,7 @@ void set_env( * environment hashmap and converts them into a NULL-terminated array of * strings in the format "KEY=VALUE". * - * @param msh Pointer to the minishell structure containing the environment + * @param minishell Pointer to the minishell structure containing the environment * variables hashmap. * * @return A dynamically allocated array of strings representing environment @@ -120,17 +131,18 @@ void set_env( * the NULL terminator. */ char **get_envp( - t_minishell *msh -) { + t_minishell *minishell +) +{ char **envp; t_list *env_list; t_list *env; t_map_entry *entry; size_t i; - env_list = ft_hashmap_entries(msh->variables.environment); + env_list = ft_hashmap_entries(minishell->variables.environment); envp = (char **)malloc( - (msh->variables.environment->size + 1) * sizeof(char *) + (minishell->variables.environment->size + 1) * sizeof(char *) ); if (envp != NULL) { @@ -149,44 +161,39 @@ char **get_envp( } /** - * @brief Frees a dynamically allocated environment variables array + * @brief Parses and stores environment variables from envp array into a hashmap * - * This function deallocates memory for an array of strings that was previously - * allocated by `get_envp()`. It iterates through each string in the array, - * frees the memory for individual strings, and then frees the array itself. + * This function iterates through the environment variables array (envp) and + * splits each variable string on the '=' delimiter to separate the variable + * name from its value. Each name-value pair is then stored in the minishell's + * environment hashmap for later retrieval. * - * @param envp Pointer to the array of environment variable strings to be freed. - * Each string in the array should be dynamically allocated. - * The array must be NULL-terminated. + * @param envp Array of environment variable strings in "NAME=value" format + * @param minishell Pointer to the minishell structure containing the environment + * hashmap + * + * @note The function assumes envp strings are in the standard format + * "NAME=value" */ -void free_envp( - char **envp -) { - size_t i; +void set_envp( + char **envp, + t_minishell *minishell +) +{ + t_hashmap **environment; + char **key_value; - i = -1; - while (envp[++i] != NULL) - free(envp[i]); - free(envp); -} - -/** - * @brief Retrieves the value of an environment variable from the shell's - * environment hashmap. - * - * This function searches for the specified environment variable name in the - * minishell's environment variable hashmap and returns its associated value. - * - * @param env_name The name of the environment variable to retrieve (e.g., - * "PATH", "HOME") - * @param msh Pointer to the minishell structure containing the environment - * variables hashmap - * - * @return The value of the environment variable if found, NULL if not found - */ -char *get_env( - const char *env_name, - t_minishell *msh -) { - return (ft_hashmap_get(msh->variables.environment, env_name)); + if (minishell == NULL || envp == NULL) + return ; + environment = &minishell->variables.environment; + *environment = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp); + if (*environment == NULL) + return ; + while (*envp != NULL) + { + key_value = ft_split(*envp, '='); + set_env(key_value[0], key_value[1], minishell); + ft_free_split(key_value); + envp++; + } } diff --git a/src/variables/environment_unset.c b/src/variables/environment_unset.c deleted file mode 100644 index feae147..0000000 --- a/src/variables/environment_unset.c +++ /dev/null @@ -1,41 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* environment_unset.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: sede-san variables.environment); - current = entries; - while (current != NULL) - { - entry = current->content; - if (ft_strcmp(entry->key, env_name) != 0) - ft_hashmap_put(new_env, - ft_strdup(entry->key), ft_strdup(entry->value)); - current = current->next; - } - ft_lstclear_nodes(&entries); - ft_hashmap_clear(&msh->variables.environment, free); - msh->variables.environment = new_env; -} diff --git a/src/variables/internal/internal.c b/src/variables/internal/internal.c new file mode 100644 index 0000000..006a9d7 --- /dev/null +++ b/src/variables/internal/internal.c @@ -0,0 +1,120 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* internal.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san variables.internal, name)); +} + +/** + * @brief Stores a variable as internal. + * + * @param name The name of the internal variable to set. + * @param value The value to associate with the internal variable. + * @param minishell Pointer to the minishell structure. + * + * @note If the internal variable already exists, its value will be updated and + * the old value will be freed. If it does not exist, a new internal + * variable will be created. + */ +void set_int( + const char *name, + char *value, + t_minishell *minishell +) +{ + t_hashmap *internal; + char *key; + char *val; + char *old_val; + + internal = minishell->variables.internal; + key = (char *)name; + if (key != NULL && !ft_hashmap_contains_key(internal, key)) + { + key = ft_strdup(name); + if (key == NULL) + return (minishell->exit = true, malloc_error()); + } + val = value; + if (val != NULL) + val = ft_strdup(value); + if (val == NULL) + { + if (key != name) + free(key); + return (minishell->exit = true, malloc_error()); + } + old_val = ft_hashmap_put(internal, key, val); + if (old_val != NULL) + free(old_val); +} + +/** + * @brief Removes an internal variable by name. + * + * @param name The name of the internal variable to remove. + * @param minishell Pointer to the minishell structure. + * + * @note If the internal variable exists, it will be removed from the hashmap + * and its associated value will be freed. + */ +void unset_int( + const char *name, + t_minishell *minishell +) +{ + char *value; + + value = ft_hashmap_remove(minishell->variables.internal, (void *)name); + if (value != NULL) + free(value); +} + +/** + * @brief Initializes the internal variables hashmap with default values. + * + * @param minishell Pointer to the minishell structure to initialize. + * + * @warning This function must be called only once during the initialization of + * the minishell. + */ +void set_intp( + t_minishell *minishell +) +{ + if (minishell == NULL) + return ; + minishell->variables.internal + = ft_hashmap_new(16, ft_hashmap_hashstr, ft_hashmap_strcmp); + if (minishell->variables.internal == NULL) + return ; + set_int("?", "0", minishell); + set_int("_", "minishell", minishell); + set_int("PS1", DEFAULT_PS1, minishell); + set_int("PS2", DEFAULT_PS2, minishell); +} diff --git a/src/variables/variables.c b/src/variables/variables.c new file mode 100644 index 0000000..60f8e72 --- /dev/null +++ b/src/variables/variables.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variables.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san variables.internal, name)) + set_int(name, value, minishell); + set_env(name, value, minishell); +} + +void unset_var( + const char *name, + t_minishell *minishell +) +{ + unset_int(name, minishell); + unset_env(name, minishell); +}