From aac1d762760147a71445db54ae97b25116ddd1c2 Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Fri, 23 Aug 2024 18:46:21 +0200 Subject: [PATCH] Implement the export function, change tokenization The tokenization had to be changed because "export te=te" was refused by the parser. The "te=te" part was tokenized as ASSIGNMENT_WORD which can only occur before command. So any ASSIGNMENT_WORD after command name is now recognized as WORD. --- Makefile | 1 + inc/execution.h | 10 +++++- src/builtins/export.c | 75 +++++++++++++++++++++++++++++++++++++++++++ src/execution.c | 6 +++- src/tokenization.c | 49 ++++++++++++++++++++++++++-- 5 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 src/builtins/export.c diff --git a/Makefile b/Makefile index f56c1b4..dc168cd 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ SOURCES := main.c \ builtins/echo.c \ builtins/pwd.c \ builtins/env.c \ + builtins/export.c \ SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES)) diff --git a/inc/execution.h b/inc/execution.h index 6fc5f3d..9e6a39a 100644 --- a/inc/execution.h +++ b/inc/execution.h @@ -6,20 +6,28 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/02 17:40:19 by ljiriste #+# #+# */ -/* Updated: 2024/08/22 13:35:41 by lnikolov ### ########.fr */ +/* Updated: 2024/08/23 18:01:03 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef EXECUTION_H # define EXECUTION_H +#include "minishell.h" + const char *get_env_var_value(const t_execution_env *env, const char *var_name); int set_env_var_value(t_execution_env *env, const char *var_name, const char *new_value); +char *get_var_name(const char *line); +ssize_t get_var_index(const t_vec *vars, const char *var_name); +const char *get_var_value(const t_vec *vars, const char *var_name); +int set_var_value(t_vec *vars, const char *name, const char *value); + int cd(int argc, char **argv, t_execution_env *env); int echo(int argc, char **argv); int pwd(void); int ft_env(int argc, t_execution_env *env); +int export(int argc, char **argv, t_execution_env *env); #endif // EXECUTION_H diff --git a/src/builtins/export.c b/src/builtins/export.c new file mode 100644 index 0000000..de808e2 --- /dev/null +++ b/src/builtins/export.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/23 09:40:38 by ljiriste #+# #+# */ +/* Updated: 2024/08/23 18:06:00 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execution.h" +#include "minishell.h" +#include + +static void unset_single(const char *name, t_execution_env *env) +{ + ssize_t index; + + index = get_var_index(&env->vars->other, name); + if (index >= 0) + ft_vec_erase(&env->vars->other, index, free_str); + index = get_var_index(&env->vars->exported, name); + if (index >= 0) + ft_vec_erase(&env->vars->exported, index, free_str); + return ; +} + +static int export_single(const char *var, t_execution_env *env) +{ + char *name; + char *value; + const char *const_value; + int res; + + name = get_var_name(var); + if (!name || !name[0] || (var[ft_strlen(name)] != '=' && var[ft_strlen(name)] != '\0')) + { + free(name); + return (1); + } + if (var[ft_strlen(name)] == '=') + const_value = var + ft_strlen(name) + 1; + else + { + const_value = get_env_var_value(env, name); + if (!const_value) + const_value = ""; + } + value = ft_strdup(const_value); + if (!value) + { + free(name); + return (1); + } + unset_single(name, env); + res = set_var_value(&env->vars->exported, name, value); + free(name); + free(value); + return (res); +} + +int export(__attribute__((unused)) int argc, char **argv, t_execution_env *env) +{ + size_t i; + + i = 1; + while (argv[i]) + { + export_single(argv[i], env); + ++i; + } + return (0); +} diff --git a/src/execution.c b/src/execution.c index b8dd626..a433096 100644 --- a/src/execution.c +++ b/src/execution.c @@ -6,7 +6,7 @@ /* By: lnikolov ret_val = pwd(); else if (!ft_strcmp(fields[0], "env")) env->ret_val = ft_env(count_fields(fields), env); + else if (!ft_strcmp(fields[0], "export")) + env->ret_val = export(count_fields(fields), fields, env); else return (-1); return (0); diff --git a/src/tokenization.c b/src/tokenization.c index 923c8e1..2c38392 100644 --- a/src/tokenization.c +++ b/src/tokenization.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/21 16:34:43 by ljiriste #+# #+# */ -/* Updated: 2024/08/08 10:34:41 by ljiriste ### ########.fr */ +/* Updated: 2024/08/23 18:43:53 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -66,7 +66,7 @@ static int can_expand_operator(t_vec *current_token, char c) return (res); } -static const char *g_tokens[] = { +static const char *g_tokens[12] = { "WORD", "ASSIGNMENT_WORD", "IO_NUMBER", @@ -217,6 +217,50 @@ int finish_token(t_vec *tokens, t_vec *current_token, char next) return (ft_vec_init(current_token, sizeof(char)) != success); } +int is_redirection_operator(const t_token *token) +{ + return (token->type == g_tokens[LESS] + || token->type == g_tokens[DLESS] + || token->type == g_tokens[GREAT] + || token->type == g_tokens[DGREAT]); +} + +void filter_assignment_word(t_vec *tokens) +{ + size_t i; + t_token *token; + const t_token *prev_token; + + i = 0; + while (i < tokens->size) + { + token = ft_vec_access(tokens, i); + if (i == 0) + { + ++i; + continue ; + } + prev_token = ft_vec_caccess(tokens, i - 1); + if (prev_token->type == g_tokens[ASSIGNMENT_WORD] + || prev_token->type == g_tokens[AND_IF] + || prev_token->type == g_tokens[OR_IF]) + { + ++i; + continue ; + } + if (i == 1 || prev_token->type != g_tokens[WORD]) + { + ++i; + token->type = (char *)g_tokens[WORD]; + continue ; + } + prev_token = ft_vec_caccess(tokens, i - 2); + if (!is_redirection_operator(prev_token)) + token->type = (char *)g_tokens[WORD]; + ++i; + } +} + int tokenize(char **line, t_vec *tokens) { t_vec current_token; @@ -262,5 +306,6 @@ int tokenize(char **line, t_vec *tokens) if (res) ft_vec_free(tokens, free_token); ft_vec_free(¤t_token, NULL); + filter_assignment_word(tokens); return (res); } -- 2.30.2