Repository: aktyz/minishell
Pull request #42: Eval fixes
Author: login: marlenasn
Created: 2025-05-03T18:43:56Z | Merged: 2025-05-04T20:25:34Z

Summary of changes

* Fixing `export a=b`, `a` was showing `(null)` value before fix. It's because `is_valid_var_name` is doing something with the pointer passed under `var_name`. Added `ft_strdup` to the only call of this function
```
if (!is_valid_var_name(ft_strdup(cmd)))
```
* Fixing `export ABCD` without value. `env` should not print it (like in `bash`) but `export` command should
* Signals: only fix for Ctrl-C newline in blocking execution like `cat` or `grep "nothing"`.
* Ctrl-\ works ok in this case but doesn't show `Quit(Core dumped)` like `bash`



Diff:
diff --git a/Makefile b/Makefile
index 8629b20..0239d90 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
 #    By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+         #
 #                                                 +#+#+#+#+#+   +#+            #
 #    Created: 2024/12/04 15:20:00 by zslowian          #+#    #+#              #
-#    Updated: 2025/05/03 15:51:51 by zslowian         ###   ########.fr        #
+#    Updated: 2025/05/04 20:40:31 by zslowian         ###   ########.fr        #
 #                                                                              #
 # **************************************************************************** #
 
@@ -20,11 +20,13 @@ LIB = -L $(LIBFT_F) -lft
 RM = rm -f
 
 SRC = main.c \
-	builtins/builtins_helpers.c \
 	builtins/cd.c \
 	builtins/echo.c \
+	builtins/env_execve_arr.c \
+	builtins/env_helpers.c \
 	builtins/env.c \
 	builtins/exit.c \
+	builtins/export_sort.c \
 	builtins/export_utils.c \
 	builtins/export.c \
 	builtins/pwd.c \
diff --git a/builtins/builtins_helpers.c b/builtins/builtins_helpers.c
deleted file mode 100644
index 0f908cb..0000000
--- a/builtins/builtins_helpers.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ************************************************************************** */
-/*                                                                            */
-/*                                                        :::      ::::::::   */
-/*   builtins_helpers.c                                 :+:      :+:    :+:   */
-/*                                                    +:+ +:+         +:+     */
-/*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
-/*                                                +#+#+#+#+#+   +#+           */
-/*   Created: 2025/04/27 11:45:11 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/03 13:07:00 by zslowian         ###   ########.fr       */
-/*                                                                            */
-/* ************************************************************************** */
-
-#include "minishell.h"
-
-bool	is_valid_var_name(char *var_name);
-void	ft_update_value_or_add(char *cmd, t_global *global);
-void	ft_mini_export_wrapper(t_command *cmd, t_global *global);
-
-bool	is_valid_var_name(char *var_name)
-{
-	int		i;
-	bool	contains;
-	char	**name_value;
-
-	if (!var_name || !var_name[0] || var_name[0] == '=')
-		return (false);
-	i = 0;
-	contains = false;
-	if (ft_strchr(var_name, '='))
-	{
-		name_value = ft_split(var_name, '=');
-		free_ptr((void **) &var_name);
-		var_name = ft_strdup(name_value[0]);
-		ft_clear_char_array(&name_value, 2);
-	}
-	while (var_name[i])
-	{
-		if (!(ft_isalpha(var_name[i]) || ft_isdigit(var_name[i])
-				|| var_name[i] == '_'))
-			return (false);
-		if (!contains && (ft_isalpha(var_name[i]) || var_name[i] == '_'))
-			contains = true;
-		i++;
-	}
-	return (contains);
-}
-
-void	ft_update_value_or_add(char *cmd, t_global *global)
-{
-	t_minishell_env	*content;
-	t_list			*env;
-	char			*split_ptr;
-	int				split_index;
-
-	env = global->env;
-	while (env && env->content)
-	{
-		content = (t_minishell_env *)env->content;
-		split_ptr = ft_strchr(cmd, '=');
-		split_index = split_ptr - cmd;
-		if (ft_strncmp((const char *)cmd, content->name_value[0],
-				split_index) == 0)
-		{
-			ft_handle_existing_var(cmd, content);
-			return ;
-		}
-		env = env->next;
-	}
-	if (!env)
-		ft_add_new_env_var(cmd, global);
-}
-
-void	ft_mini_export_wrapper(t_command *cmd, t_global *global)
-{
-	t_io_fds	*io;
-
-	io = NULL;
-	if (cmd->final_io)
-		io = cmd->final_io;
-	if (cmd->pipe_output || (io && io->outfile))
-		return ;
-	if ((global->cmd->content != cmd) || (io && io->infile))
-	{
-		ft_clear_char_array(&cmd->args, cmd->args_size);
-		cmd->args = ft_calloc(sizeof(char *), 2);
-		cmd->args[0] = ft_strdup(EXPORT);
-	}
-	ft_export(cmd, global);
-}
diff --git a/builtins/cd.c b/builtins/cd.c
index 70e2d1e..256aa74 100644
--- a/builtins/cd.c
+++ b/builtins/cd.c
@@ -6,7 +6,7 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/11 09:22:35 by zslowian          #+#    #+#             */
-/*   Updated: 2025/04/29 22:02:30 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 17:59:35 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -40,13 +40,13 @@ static int	ft_cd_home(t_global *g, char *cmd)
 {
 	char	*path;
 
-	path = ft_get_env_var_value(ENV_HOME, g->env);
+	path = ft_get_env_var_value(g->env, "HOME");
 	if (!path)
 	{
 		handle_cd_err(cmd, g, 3);
 		return (1);
 	}
-	return (chdir(path));
+	return (free_ptr((void **) &path), chdir(path));
 }
 
 static void	handle_cd_err(char *cmd, t_global *g, int code)
diff --git a/builtins/env.c b/builtins/env.c
index 2ab720e..6dc42ce 100644
--- a/builtins/env.c
+++ b/builtins/env.c
@@ -22,7 +22,8 @@ int	ft_env(t_list *env)
 	while (ptr && ptr->content)
 	{
 		content = (t_minishell_env *)ptr->content;
-		ft_printf("%s=%s\n", content->name_value[0], content->name_value[1]);
+		if (content->name_value[1])
+			ft_printf("%s=%s\n", content->name_value[0], content->name_value[1]);
 		ptr = ptr->next;
 	}
 	return (0);
diff --git a/builtins/env_execve_arr.c b/builtins/env_execve_arr.c
new file mode 100644
index 0000000..edb8357
--- /dev/null
+++ b/builtins/env_execve_arr.c
@@ -0,0 +1,94 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   env_execve_arr.c                                   :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/05/04 20:20:30 by zslowian          #+#    #+#             */
+/*   Updated: 2025/05/04 20:49:30 by zslowian         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+char		**ft_execve_env(t_list *env);
+static void	ft_create_execve_array_entry(char **ptr,
+				t_minishell_env *content);
+bool		process_env_variable(char *env_var, t_list **list);
+
+/**
+ * Function translates our minishell t_list *env into an array required
+ * by execve(). As our execve is working perfectly fine - DO NOT TOUCH
+ *
+ */
+char	**ft_execve_env(t_list *env)
+{
+	char			**execve_env;
+	t_minishell_env	*content;
+	int				i;
+
+	execve_env = ft_calloc(sizeof(char *), env->lst_size + 1);
+	if (!execve_env)
+		return (NULL);
+	i = 0;
+	while (env && env->content)
+	{
+		content = (t_minishell_env *)env->content;
+		if (content->export && content->name_value)
+			ft_create_execve_array_entry(&execve_env[i], content);
+		if (execve_env[i])
+			i++;
+		env = env->next;
+	}
+	return (execve_env);
+}
+
+static void	ft_create_execve_array_entry(char **ptr, t_minishell_env *content)
+{
+	char	*env_var;
+	int		i;
+
+	env_var = ft_calloc(sizeof(char), ft_strlen(content->name_value[0])
+			+ ft_strlen(content->name_value[1]) + 2);
+	i = ft_strlcpy(env_var, content->name_value[0],
+			ft_strlen(content->name_value[0]));
+	env_var[i] = '=';
+	ft_strlcpy(env_var + i + 1, content->name_value[1],
+		ft_strlen(content->name_value[1]));
+	*ptr = env_var;
+}
+
+/**
+ * This is a special function handling env variables list creation
+ * in the initialization phase of the minishell start-up.
+ * aka: DO NOT TOUCH
+ */
+bool	process_env_variable(char *env_var, t_list **list)
+{
+	t_minishell_env	*content;
+
+	content = ft_calloc(sizeof(t_minishell_env), 1);
+	if (!content)
+	{
+		ft_lstclear(list, ft_clear_minishell_env);
+		return (false);
+	}
+	content->name_value = ft_calloc(sizeof(char *), 2);
+	if (!content->name_value)
+	{
+		ft_lstclear(list, ft_clear_minishell_env);
+		return (false);
+	}
+	ft_split_env_variable(env_var, &content->name_value[0],
+		&content->name_value[1]);
+	if (!content->name_value[0] || !content->name_value[1])
+	{
+		free(content);
+		ft_lstclear(list, ft_clear_minishell_env);
+		return (false);
+	}
+	if (ft_strcmp(content->name_value[0], "_"))
+		content->export = true;
+	return (ft_lstadd_back(list, ft_lstnew(content)), true);
+}
diff --git a/builtins/env_helpers.c b/builtins/env_helpers.c
new file mode 100644
index 0000000..ab00fba
--- /dev/null
+++ b/builtins/env_helpers.c
@@ -0,0 +1,182 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   env_helpers.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/05/04 16:31:59 by zslowian          #+#    #+#             */
+/*   Updated: 2025/05/04 21:30:02 by zslowian         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+char	*ft_get_env_var_value(t_list *env, char *var_name);
+bool	ft_update_env_var_value(t_list *node, char *new_value);
+bool	ft_add_env_var(t_global *g, char *name, char *value);
+void	ft_add_new_env_var(char *var_name, t_global *global);
+t_list	*ft_return_env_list_node_ptr(t_list *env, char *name);
+
+
+char	*ft_get_env_var_value(t_list *env, char *var_name)
+{
+	t_list			*lst;
+	t_minishell_env	*content;
+
+	lst = NULL;
+	content = NULL;
+	if (!var_name)
+		return (NULL);
+	lst = ft_return_env_list_node_ptr(env, var_name);
+	if (lst)
+		content = (t_minishell_env *) lst->content;
+	else
+		return (NULL);
+	if (lst->content && content->name_value[1])
+		return (ft_strdup(content->name_value[1]));
+	return (NULL);
+}
+
+/**
+ * Please use this function only when you are sure that the node
+ * is pointing to the node of the variable's value you want to update.
+ * Because of the overwriting new_value can be empty.
+ * Function returns:
+ * - true - if the value is successfully update
+ * - false - in case of error
+ *
+ * If new_value is passed as null, the environment variable you
+ * want to update will not hold any value (will have `NULL`)
+ * under `content->name_value[1]`, therefore we need to check for
+ * it in crucial places in the project.
+ *
+ */
+bool	ft_update_env_var_value(t_list *node, char *new_value)
+{
+	t_minishell_env	*content;
+	char			*prev_value;
+
+	prev_value = NULL;
+	if (!node)
+		return (false);
+	content = (t_minishell_env *) node->content;
+	if (content->name_value[1]) // The variable already has a value
+	{
+		prev_value = ft_strdup(content->name_value[1]);
+		free_ptr((void **) &content->name_value[1]);
+		if (new_value)
+		{
+			content->name_value[1] = ft_strdup(new_value);
+			if (!content->name_value[1])
+				return (free_ptr((void **) &prev_value), false);
+		}
+		else
+			content->name_value[1] = NULL;
+		content->export = true;
+		return (free_ptr((void **) &prev_value), true);
+	}
+	else // The variable previously had no value
+	{
+		if (new_value)
+		{
+			content->name_value[1] = ft_strdup(new_value);
+			if (!content->name_value[1])
+				return (false);
+		}
+		content->export = true;
+		return (true);
+	}
+}
+
+/**
+ * Function creates a new entry on the environment list.
+ *
+ * We assume that the env list is already there after the initialization
+ * process handled by special designation functions.
+ *
+ * Function takes parameters:
+ * - name - that should had been previously validated
+ * - value - that can be NULL
+ *
+ * Because we only create new env variables through `export` cmd,
+ * export flag set to true by default.
+ */
+bool	ft_add_env_var(t_global *g, char *name, char *value)
+{
+	t_minishell_env	*new_content;
+
+	if (!g->env)
+	{
+		ft_minishell_perror("ft_add_env_var", 1);
+		ft_exit(g, "env_list not initialized", EXIT_FAILURE);
+	}
+	new_content = ft_calloc(sizeof(t_minishell_env), 1);
+	if (!new_content)
+	{
+		ft_minishell_perror("ft_calloc", 1);
+		return (false);
+	}
+	new_content->name_value = ft_calloc(sizeof(char *), 2);
+	if (!new_content->name_value)
+	{
+		free_ptr((void **) &new_content);
+		ft_minishell_perror("ft_calloc", 1);
+		return (false);
+	}
+	new_content->name_value[0] = ft_strdup(name);
+	if (value)
+		new_content->name_value[1] = ft_strdup(value);
+	new_content->export = true;
+	ft_lstadd_back(&g->env, ft_lstnew(new_content));
+	return (true);
+}
+
+/**
+ * This function is very similar to the one above, however
+ * instead of two arguments env_var_name and env_var_value
+ * it takes a string var_name as argument consisting of:
+ * <var_name>=<var_value>
+ *
+ */
+void	ft_add_new_env_var(char *var_name, t_global *global)
+{
+	t_minishell_env	*content;
+
+	content = ft_calloc(sizeof(t_minishell_env), 1);
+	if (!content)
+		return ;
+	content->name_value = ft_calloc(sizeof(char *), 2);
+	ft_split_env_variable(var_name, &content->name_value[0],
+		&content->name_value[1]);
+	content->export = true;
+	ft_lstadd_back(&global->env, ft_lstnew(content));
+}
+
+/**
+ * Function returns a pointer to the env_list node that holds
+ * the information for name enviroment variable or NULL if the
+ * - list doesn't exist
+ * - name is NULL
+ * - name is Unfound
+ *
+ */
+t_list	*ft_return_env_list_node_ptr(t_list *env, char *name)
+{
+	t_list			*lst;
+	t_minishell_env	*content;
+
+	if (!env)
+		return (NULL);
+	if (!name)
+		return (NULL);
+	lst = env;
+	while (lst && lst->content)
+	{
+		content = (t_minishell_env *) lst->content;
+		if (ft_strcmp(name, content->name_value[0]) == 0)
+			return (lst);
+		lst = lst->next;
+	}
+	return (lst);
+}
diff --git a/builtins/export.c b/builtins/export.c
index 49f8c1d..b0156fd 100644
--- a/builtins/export.c
+++ b/builtins/export.c
@@ -6,109 +6,114 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/23 17:33:45 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/03 15:55:33 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 22:04:05 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
 
 void		ft_export(t_command *cmd, t_global *global);
-char		**ft_execve_env(t_list *env);
-static void	ft_sort_export_list(t_list **list);
-void		ft_handle_existing_var(char *cmd, t_minishell_env *content);
-static void	ft_swap_nodes(t_list **current, t_list **next, bool *swapped);
+static bool	ft_handle_export_arg(char *cmd, t_global *global);
+static void	ft_handle_export_no_arg(t_global *global);
+void		ft_mini_export_wrapper(t_command *cmd, t_global *global);
 
 void	ft_export(t_command *cmd, t_global *global)
 {
-	t_list			*env;
-	int				i;
+	t_list	*env;
+	bool	result;
+	int		i;
 
 	env = global->env;
 	i = 0;
 	if (cmd->args[1])
 	{
 		while (cmd->args[++i])
-			global->last_exit_code = ft_handle_export_arg(cmd->args[i], global);
+		{
+			result = ft_handle_export_arg(cmd->args[i], global);
+			if (!result)
+			global->last_exit_code = 1;
+		}
 	}
 	else
 	{
 		ft_sort_export_list(&env);
-		ft_handle_export(global);
+		ft_handle_export_no_arg(global);
 	}
 }
 
 /**
- * Function translates our minishell t_list *env into an array required
- * by execve()
+ * This function is running whenever user provides argument to
+ * export built-in command. It needs to:
+ * - validate var_name, if ok it:
+ *     - create variable if not there
+ *     - update variable value if variable is there
+ * -> in all cases flip env->export to true
  *
+ * It takes export_arg argument - passed from export of structure:
+ * <var_name>=<var_value> OR <var_name>
  */
-char	**ft_execve_env(t_list *env)
+static bool	ft_handle_export_arg(char *export_arg, t_global *global)
 {
-	char			**execve_env;
-	t_minishell_env	*content;
-	int				i;
+	char	*var_name;
+	char	*var_value;
+	t_list	*node;
+	bool	result;
 
-	execve_env = ft_calloc(sizeof(char *), env->lst_size + 1);
-	if (!execve_env)
-		return (NULL);
-	i = 0;
-	while (env && env->content)
+	var_value = NULL;
+	node = NULL;
+	result = false;
+	if (ft_strnchar(export_arg, '=')) // we have value but can be NULL (aka we have '=')
+		ft_split_env_variable(export_arg, &var_name, &var_value);
+	else //no value
+		var_name = ft_strdup(export_arg);
+	node = ft_return_env_list_node_ptr(global->env, var_name);
+	if (is_valid_var_name(var_name))
 	{
-		content = (t_minishell_env *)env->content;
-		if (content->export && content->name_value)
-			ft_create_execve_array_entry(&execve_env[i], content);
-		if (execve_env[i])
-			i++;
-		env = env->next;
+		if (node)
+			result = ft_update_env_var_value(node, var_value);
+		else
+			result = ft_add_env_var(global, var_name, var_value);
 	}
-	return (execve_env);
+	else
+		errmsg_cmd("export", NULL, "not a valid identifier", 1);
+	if (var_value)
+		free_ptr((void **) &var_value);
+	return (free_ptr((void **) &var_name), result);
 }
 
-static void	ft_sort_export_list(t_list **list)
+static void	ft_handle_export_no_arg(t_global *global)
 {
-	t_list			*current;
-	t_list			*next;
-	bool			swapped;
+	t_minishell_env	*content;
+	t_list			*env;
 
-	if (!list || !*list)
-		return ;
-	swapped = true;
-	while (swapped)
+	env = global->env;
+	while (env && env->content)
 	{
-		swapped = false;
-		current = *list;
-		while (current->next)
+		content = (t_minishell_env *)env->content;
+		if (content->export && content->name_value)
 		{
-			next = current->next;
-			if (ft_strcmp(((t_minishell_env *)current->content)->name_value[0],
-					((t_minishell_env *)next->content)->name_value[0]) > 0)
-				ft_swap_nodes(&current, &next, &swapped);
-			current = current->next;
+			if (!content->name_value[1])
+				ft_printf("declare -x %s\n", content->name_value[0]);
+			else
+				ft_printf("declare -x %s=\"%s\"\n", content->name_value[0],
+					content->name_value[1]);
 		}
+		env = env->next;
 	}
 }
 
-void	ft_handle_existing_var(char *cmd, t_minishell_env *content)
+void	ft_mini_export_wrapper(t_command *cmd, t_global *global)
 {
-	int	equal_pos;
+	t_io_fds	*io;
 
-	equal_pos = ft_strlen(content->name_value[0]);
-	if (equal_pos < (int) ft_strlen(cmd) && cmd[equal_pos] == '=')
+	io = NULL;
+	if (cmd->final_io)
+		io = cmd->final_io;
+	if ((global->cmd->content != cmd) || (io && io->infile))
 	{
-		free_ptr((void **)&content->name_value[0]);
-		free_ptr((void **)&content->name_value[1]);
-		ft_split_env_variable(cmd, &content->name_value[0],
-			&content->name_value[1]);
+		ft_clear_char_array(&cmd->args, cmd->args_size);
+		cmd->args = ft_calloc(sizeof(char *), 2);
+		cmd->args[0] = ft_strdup(EXPORT);
 	}
-	content->export = true;
-}
-
-static void	ft_swap_nodes(t_list **current, t_list **next, bool *swapped)
-{
-	t_minishell_env	*temp_content;
-
-	temp_content = (*current)->content;
-	(*current)->content = (*next)->content;
-	(*next)->content = temp_content;
-	*swapped = true;
+	ft_export(cmd, global);
 }
diff --git a/builtins/export_sort.c b/builtins/export_sort.c
new file mode 100644
index 0000000..2c72f16
--- /dev/null
+++ b/builtins/export_sort.c
@@ -0,0 +1,55 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   export_sort.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/05/04 20:14:57 by zslowian          #+#    #+#             */
+/*   Updated: 2025/05/04 20:50:26 by zslowian         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+void		ft_sort_export_list(t_list **list);
+static void	ft_swap_nodes(t_list **current, t_list **next, bool *swapped);
+
+/**
+ * Simple bubble sort function for our env list, used when printing
+ * export with no arguments. No issues with the sorting mechanizm.
+ *
+ */
+void	ft_sort_export_list(t_list **list)
+{
+	t_list			*current;
+	t_list			*next;
+	bool			swapped;
+
+	if (!list || !*list)
+		return ;
+	swapped = true;
+	while (swapped)
+	{
+		swapped = false;
+		current = *list;
+		while (current->next)
+		{
+			next = current->next;
+			if (ft_strcmp(((t_minishell_env *)current->content)->name_value[0],
+					((t_minishell_env *)next->content)->name_value[0]) > 0)
+				ft_swap_nodes(&current, &next, &swapped);
+			current = current->next;
+		}
+	}
+}
+
+static void	ft_swap_nodes(t_list **current, t_list **next, bool *swapped)
+{
+	t_minishell_env	*temp_content;
+
+	temp_content = (*current)->content;
+	(*current)->content = (*next)->content;
+	(*next)->content = temp_content;
+	*swapped = true;
+}
diff --git a/builtins/export_utils.c b/builtins/export_utils.c
index 77845cb..fe4d211 100644
--- a/builtins/export_utils.c
+++ b/builtins/export_utils.c
@@ -6,18 +6,32 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/27 12:15:55 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/03 15:54:07 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 21:59:20 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
 
-void		ft_split_env_variable(char *name_value, char **var_name,
-				char **var_value);
-void		ft_create_execve_array_entry(char **ptr, t_minishell_env *content);
-int			ft_handle_export_arg(char *cmd, t_global *global);
-void		ft_handle_export(t_global *global);
-void		ft_add_new_env_var(char *var_name, t_global *global);
+bool	is_valid_var_name(char *var_name);
+void	ft_split_env_variable(char *name_value, char **var_name,
+			char **var_value);
+
+bool	is_valid_var_name(char *var_name)
+{
+	int		i;
+
+	if (!var_name || !var_name[0] || var_name[0] == '=' || ft_isdigit(var_name[0]))
+		return (false);
+	i = 0;
+	while (var_name[i])
+	{
+		if (!(ft_isalpha(var_name[i]) || ft_isdigit(var_name[i])
+				|| var_name[i] == '_'))
+			return (false);
+		i++;
+	}
+	return (true);
+}
 
 void	ft_split_env_variable(char *name_value, char **var_name,
 			char **var_value)
@@ -39,72 +53,3 @@ void	ft_split_env_variable(char *name_value, char **var_name,
 	else
 		*var_name = ft_strdup(name_value);
 }
-
-void	ft_create_execve_array_entry(char **ptr, t_minishell_env *content)
-{
-	char	*env_var;
-	int		i;
-
-	env_var = ft_calloc(sizeof(char), ft_strlen(content->name_value[0])
-			+ ft_strlen(content->name_value[1]) + 2);
-	i = ft_strlcpy(env_var, content->name_value[0],
-			ft_strlen(content->name_value[0]));
-	env_var[i] = '=';
-	ft_strlcpy(env_var + i + 1, content->name_value[1],
-		ft_strlen(content->name_value[1]));
-	*ptr = env_var;
-}
-
-int	ft_handle_export_arg(char *cmd, t_global *global)
-{
-	char	*value;
-	char	*final;
-
-	value = ft_strjoin("minishell: ", cmd);
-	final = ft_strjoin(value, ": not a valid identifier\n");
-	if (!is_valid_var_name(cmd))
-	{
-		ft_putstr_fd(final, 2);
-		free_ptr((void **) &value);
-		free_ptr((void **) &final);
-		return (1);
-	}
-	ft_update_value_or_add(cmd, global);
-	free_ptr((void **) &final);
-	return (free_ptr((void **) &value), 0);
-}
-
-void	ft_handle_export(t_global *global)
-{
-	t_minishell_env	*content;
-	t_list			*env;
-
-	env = global->env;
-	while (env && env->content)
-	{
-		content = (t_minishell_env *)env->content;
-		if (content->export && content->name_value)
-		{
-			if (!content->name_value[1])
-				ft_printf("declare -x %s=\"\"\n", content->name_value[0]);
-			else
-				ft_printf("declare -x %s=\"%s\"\n", content->name_value[0],
-					content->name_value[1]);
-		}
-		env = env->next;
-	}
-}
-
-void	ft_add_new_env_var(char *var_name, t_global *global)
-{
-	t_minishell_env	*content;
-
-	content = ft_calloc(sizeof(t_minishell_env), 1);
-	if (!content)
-		return ;
-	content->name_value = ft_calloc(sizeof(char *), 2);
-	ft_split_env_variable(var_name, &content->name_value[0],
-		&content->name_value[1]);
-	content->export = true;
-	ft_lstadd_back(&global->env, ft_lstnew(content));
-}
diff --git a/builtins/unset.c b/builtins/unset.c
index a079c51..321bb8f 100644
--- a/builtins/unset.c
+++ b/builtins/unset.c
@@ -6,7 +6,7 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/23 17:36:57 by zslowian          #+#    #+#             */
-/*   Updated: 2025/04/27 13:32:46 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 18:25:50 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -19,26 +19,18 @@ static void	ft_remove_node(t_list *node, t_global *global, bool *is_removed);
 
 void	ft_unset(t_command *cmd, t_global *global)
 {
-	t_minishell_env	*content;
-	t_list			*ptr;
-	int				i;
+	t_list	*lst;
+	t_list	*node_to_delete;
+	int		i;
 
 	if (!cmd->args[1])
 		return ;
+	lst = global->env;
 	i = 0;
 	while (cmd->args[++i])
 	{
-		ptr = global->env;
-		while (ptr)
-		{
-			content = (t_minishell_env *)ptr->content;
-			if (content && !ft_strcmp(cmd->args[i], content->name_value[0]))
-			{
-				ft_delete_env_node(ptr, global);
-				break ;
-			}
-			ptr = ptr->next;
-		}
+		node_to_delete = ft_return_env_list_node_ptr(lst, cmd->args[i]);
+		ft_delete_env_node(node_to_delete, global);
 	}
 }
 
diff --git a/execution/ft_exec_utils.c b/execution/ft_exec_utils.c
index 4b0dc61..db99589 100644
--- a/execution/ft_exec_utils.c
+++ b/execution/ft_exec_utils.c
@@ -6,7 +6,7 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/05 19:08:40 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/04 08:52:49 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 18:25:57 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -50,6 +50,8 @@ char	*resolve_command_path(t_global *g, char *path, char *cmd)
 	res = NULL;
 	ex = NULL;
 	(void)g;
+	if (!path)
+		return (NULL);
 	candidates = ft_split(path, ':');
 	if (candidates)
 	{
@@ -121,8 +123,6 @@ void	ft_execute_child_proc(t_command *cmd, t_global *global,
 	else
 	{
 		ft_check_path(cmd->path, &error);
-		if (!error)
-			ft_command_not_found(cmd->path, &error);
 		if (!error)
 		{
 			execve(cmd->path, cmd->args, ft_execve_env(global->env));
diff --git a/execution/ft_input.c b/execution/ft_input.c
index ea998d1..b9590fd 100644
--- a/execution/ft_input.c
+++ b/execution/ft_input.c
@@ -72,18 +72,25 @@ void	ft_execute_cmd(t_global *g, t_command *cmd, pid_t prev_pid)
 void	ft_check_path(char *path, int *error)
 {
 	struct stat	info;
+	bool dir_or_cmd;
 
-	if (stat(path, &info) != 0)
-		*error = 128;
-	if (S_ISDIR(info.st_mode) && (path[0] == '/' || path[0] == '.'))
-	{
-		*error = 126;
-		ft_minishell_perror(path, EISDIR);
+	dir_or_cmd = (ft_strchr(path, '/') || path[0] == '.');
+
+	if (stat(path, &info) != 0) {
+		*error = 127;
 	}
-	else if (S_ISDIR(info.st_mode))
+	if (*error && dir_or_cmd) {
+		return ft_handle_minishell_err(path, ": No such file or directory\n");
+	}
+	if (*error)
 	{
-		*error = 127;
-		ft_handle_minishell_err(path, ": command not found\n");
+		if (dir_or_cmd) {
+			*error = 126;
+			return ft_handle_minishell_err(path, ": No such file or directory\n");
+		}
+		else
+			return ft_handle_minishell_err(path, ": command not found\n");
+		return ;
 	}
 	if (access(path, F_OK))
 	{
@@ -93,7 +100,20 @@ void	ft_check_path(char *path, int *error)
 	else if (access(path, X_OK))
 	{
 		*error = 126;
-		ft_minishell_perror(path, EACCES);
+		if (dir_or_cmd) 
+			ft_minishell_perror(path, EACCES);
+		else {
+			*error = 127;
+			return ft_handle_minishell_err(path, ": command not found\n");
+		}
+			
+	}
+	if (S_ISDIR(info.st_mode)) {
+		*error = 126;
+		if (dir_or_cmd) 
+			return ft_handle_minishell_err(path, ": Is a directory\n");
+		*error = 127;
+		return ft_handle_minishell_err(path, ": command not found\n");
 	}
 }
 
diff --git a/execution/ft_process.c b/execution/ft_process.c
index 518a134..0ef5a3d 100644
--- a/execution/ft_process.c
+++ b/execution/ft_process.c
@@ -6,14 +6,13 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/12/05 15:11:29 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/04 07:23:37 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 17:57:49 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
 
 void		ft_process(t_global *global);
-char		*ft_get_env_var_value(char *env_var_name, t_list *env);
 void		ft_run_parent_builtins(t_command *cmd, t_global *global);
 static void	ft_pipex(t_global *global);
 static void	ft_execute(t_global *global);
@@ -27,20 +26,6 @@ void	ft_process(t_global *global)
 	}
 }
 
-char	*ft_get_env_var_value(char *env_var_name, t_list *env)
-{
-	t_minishell_env	*content;
-
-	while (env)
-	{
-		content = (t_minishell_env *)env->content;
-		if (ft_strcmp(env_var_name, content->name_value[0]) == 0)
-			return (content->name_value[1]);
-		env = env->next;
-	}
-	return (NULL);
-}
-
 void	ft_run_parent_builtins(t_command *cmd, t_global *global)
 {
 	if (cmd->command && ft_strncmp(cmd->command, EXIT, ft_strlen(EXIT)) == 0)
diff --git a/execution/ft_run_builtin.c b/execution/ft_run_builtin.c
index c5416cf..4b2a294 100644
--- a/execution/ft_run_builtin.c
+++ b/execution/ft_run_builtin.c
@@ -6,7 +6,7 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/09 17:54:00 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/04 07:31:39 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 18:32:21 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -57,12 +57,17 @@ void	ft_is_status_request(t_token *token, t_command *cmd)
 void	ft_split_child_parent_run(t_global *g, t_command *cmd,
 			t_command *prev_cmd)
 {
+	char	*path_values;
+
+	path_values = ft_get_env_var_value(g->env, "PATH");
 	if (!is_parent_builtin(cmd))
 		ft_safe_fork(g, cmd);
 	if (cmd->cmd_pid == 0 && ft_strcmp(cmd->command, "\0") == 0)
 		ft_exit(g, cmd->command, EXIT_SUCCESS);
-	if (!cmd->is_builtin)
-		cmd->path = resolve_command_path(g,
-				ft_get_env_var_value(ENV_PATH, g->env), cmd->command);
+	if (!cmd->is_builtin && path_values)
+	{
+		cmd->path = resolve_command_path(g, path_values, cmd->command);
+		free_ptr((void **) &path_values);
+	}
 	ft_handle_redirections(cmd, g, prev_cmd);
 }
diff --git a/includes/minishell.h b/includes/minishell.h
index 03257d5..148b32e 100644
--- a/includes/minishell.h
+++ b/includes/minishell.h
@@ -6,7 +6,7 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/12/04 15:15:23 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/04 08:26:53 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 21:59:08 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -142,7 +142,6 @@ char		**ft_execve_env(t_list *env);
 
 void		ft_split_env_variable(char *name_value, char **var_name,
 				char **var_value);
-char		*ft_get_env_var_value(char *env_var_name, t_list *env);
 char		*resolve_command_path(t_global *g, char *path, char *cmd);
 void		ft_execute_child_proc(t_command *cmd, t_global *global,
 				pid_t prev_pid);
@@ -279,14 +278,14 @@ int			ft_cd(t_command *cmd, t_global *global);
 void		ft_exit(t_global *global, char *cmd, int status);
 int			ft_pwd(void);
 void		ft_export(t_command *cmd, t_global *global);
+void		ft_sort_export_list(t_list **list);
 void		ft_unset(t_command *cmd, t_global *global);
 int			ft_env(t_list *env);
-void		ft_create_execve_array_entry(char **ptr, t_minishell_env *content);
-int			ft_handle_export_arg(char *cmd, t_global *global);
-void		ft_handle_export(t_global *global);
-void		ft_handle_existing_var(char *cmd, t_minishell_env *content);
+char		*ft_get_env_var_value(t_list *env, char *var_name);
+bool		ft_update_env_var_value(t_list *node, char *new_value);
+bool		ft_add_env_var(t_global *g, char *name, char *value);
+t_list		*ft_return_env_list_node_ptr(t_list *env, char *name);
 bool		is_valid_var_name(char *var_name);
-void		ft_update_value_or_add(char *cmd, t_global *global);
 void		ft_add_new_env_var(char *var_name, t_global *global);
 void		ft_mini_exit_wrapper(t_command *cmd, t_global *g);
 void		ft_mini_export_wrapper(t_command *cmd, t_global *global);
diff --git a/parser/clean_unnecessary_fds.c b/parser/clean_unnecessary_fds.c
index bf8ee9b..9ad4a5c 100644
--- a/parser/clean_unnecessary_fds.c
+++ b/parser/clean_unnecessary_fds.c
@@ -6,46 +6,16 @@
 /*   By: zslowian <zslowian@student.42.fr>          +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2025/04/27 20:21:20 by zslowian          #+#    #+#             */
-/*   Updated: 2025/05/03 16:44:34 by zslowian         ###   ########.fr       */
+/*   Updated: 2025/05/04 20:45:11 by zslowian         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
 
-bool		process_env_variable(char *env_var, t_list **list);
 void		add_io_heredoc_data(t_global *g, t_command *cmd, char *delimiter);
 static void	ft_check_preceedent_heredocs(t_list *cmd_io);
 char		*get_heredoc_name(void);
 
-bool	process_env_variable(char *env_var, t_list **list)
-{
-	t_minishell_env	*content;
-
-	content = ft_calloc(sizeof(t_minishell_env), 1);
-	if (!content)
-	{
-		ft_lstclear(list, ft_clear_minishell_env);
-		return (false);
-	}
-	content->name_value = ft_calloc(sizeof(char *), 2);
-	if (!content->name_value)
-	{
-		ft_lstclear(list, ft_clear_minishell_env);
-		return (false);
-	}
-	ft_split_env_variable(env_var, &content->name_value[0],
-		&content->name_value[1]);
-	if (!content->name_value[0] || !content->name_value[1])
-	{
-		free(content);
-		ft_lstclear(list, ft_clear_minishell_env);
-		return (false);
-	}
-	if (ft_strcmp(content->name_value[0], "_"))
-		content->export = true;
-	return (ft_lstadd_back(list, ft_lstnew(content)), true);
-}
-
 void	add_io_heredoc_data(t_global *g, t_command *cmd, char *delimiter)
 {
 	t_io_fds	*new;
diff --git a/parser/signals.c b/parser/signals.c
index bc4edec..c09f02b 100644
--- a/parser/signals.c
+++ b/parser/signals.c
@@ -47,6 +47,7 @@ void	set_signals_interactive(void)
 void	signal_print_newline(int signal)
 {
 	(void)signal;
+	write(1, "\n", 1);
 	rl_on_new_line();
 }
 
diff --git a/parser/var_expander_env.c b/parser/var_expander_env.c
index a827de4..cee2fd3 100644
--- a/parser/var_expander_env.c
+++ b/parser/var_expander_env.c
@@ -34,9 +34,11 @@ static int	var_exists(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
+		env = env->next;
+		if (ft_strlen(var) != ft_strlen(content->name_value[0]))
+			continue ; 
 		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
 			return (0);
-		env = env->next;
 	}
 	return (1);
 }
@@ -51,10 +53,15 @@ static char	*search_env_var(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
-		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
-			break ;
+		
 		env = env->next;
+		if (ft_strlen(var) != ft_strlen(content->name_value[0])) 
+			continue ;
+		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
+			break ;		
 	}
+	if (!content->name_value[1])
+		return (NULL);
 	str = ft_strdup(content->name_value[1]);
 	return (str);
 }


Reviews:
user: login: marlenasn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-03T18:52:57Z
user: login: aktyz
body: `export` built-in is tricky in our `minishell` because it should offer a feature otherwise not available (as per requirements):
`export TEST` - should switch `bool export` in our 't_minishell_env' if `TEST` exists, if not do nothing
`export TEST="something_new"` - should create a new env variable with `bool export` as true
`export TEST=""` - should overwrite previously set env variable value
bash run:
![obraz](https://github.com/user-attachments/assets/13c421c3-9423-4433-b897-5bf3c9ee639e)


state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-05-04T04:07:22Z
user: login: marlenasn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-04T07:26:50Z
user: login: marlenasn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-04T07:29:07Z
user: login: marlenasn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-04T07:40:39Z
user: login: marlenasn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-04T07:41:31Z
user: login: aktyz
state: APPROVED
author_association: OWNER
submitted_at: 2025-05-04T20:25:07Z

Review comments:
diff_hunk: @@ -51,10 +51,12 @@ static char	*search_env_var(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
-		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
+		if (ft_strncmp(content->name_value[0], var, ft_strlen(content->name_value[0])) == 0)
path: parser/var_expander_env.c
user: login: marlenasn
body: the issue here was that variable `A` was matched with `ABC` variable
created_at: 2025-05-03T18:52:56Z
author_association: COLLABORATOR
diff_hunk: @@ -22,7 +22,8 @@ int	ft_env(t_list *env)
 	while (ptr && ptr->content)
 	{
 		content = (t_minishell_env *)ptr->content;
-		ft_printf("%s=%s\n", content->name_value[0], content->name_value[1]);
+		if (content->name_value[1])
path: builtins/env.c
user: login: aktyz
body: That's a good catch, however we need to move it to the variable creation somewhere in `export` built-in:
![obraz](https://github.com/user-attachments/assets/2f352eaf-7ca9-4c4c-81b0-0e09552f4263)
so that we create an env variable only if `=` is present? (Pay attention to TEST2 not created)
`env` built-in should print an env variable without the value
created_at: 2025-05-04T03:54:32Z
author_association: OWNER
diff_hunk: @@ -61,8 +61,9 @@ int	ft_handle_export_arg(char *cmd, t_global *global)
 	char	*final;
 
 	value = ft_strjoin("minishell: ", cmd);
-	final = ft_strjoin(value, ": not a valid identifier\n");
-	if (!is_valid_var_name(cmd))
+	final = ft_strjoin(*ft_split(value, '='), ": not a valid identifier\n");
+
+	if (!is_valid_var_name(ft_strdup(cmd)))
path: builtins/export_utils.c
user: login: aktyz
body: such a call unfortunately will cause leak on Valgrind - we need to create a duplicate in the right place and then free it when no longer needed (unless you find a way a different way to free memory allocated in a function call)
created_at: 2025-05-04T03:54:38Z
author_association: OWNER
diff_hunk: @@ -86,7 +87,7 @@ void	ft_handle_export(t_global *global)
 		if (content->export && content->name_value)
 		{
 			if (!content->name_value[1])
-				ft_printf("declare -x %s=\"\"\n", content->name_value[0]);
+				ft_printf("declare -x %s\n", content->name_value[0]);
path: builtins/export_utils.c
user: login: aktyz
body: this one is still needed - similar to `env` built-in (visible at the upper bash test)
created_at: 2025-05-04T03:55:41Z
author_association: OWNER
diff_hunk: @@ -51,10 +51,12 @@ static char	*search_env_var(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
-		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
+		if (ft_strncmp(content->name_value[0], var, ft_strlen(content->name_value[0])) == 0)
 			break ;
 		env = env->next;
 	}
+	if (!content->name_value[1])
path: parser/var_expander_env.c
user: login: aktyz
body: same as previous comments - empty (or just empty strings) value `env` variables are allowed in `bash`
created_at: 2025-05-04T03:57:55Z
author_association: OWNER
diff_hunk: @@ -86,7 +87,7 @@ void	ft_handle_export(t_global *global)
 		if (content->export && content->name_value)
 		{
 			if (!content->name_value[1])
-				ft_printf("declare -x %s=\"\"\n", content->name_value[0]);
+				ft_printf("declare -x %s\n", content->name_value[0]);
path: builtins/export_utils.c
user: login: marlenasn
body: This is not testing empty string (that would be `!content->name_value[1][0]`), it's testing `NULL` under `name_value[1]`

`NULL` can be set like this, see this example in `bash`
```bash
$ export ABC123
$ env | grep ABC123
$ export | grep ABC123
declare -x ABC123
```

note that `bash` doesn't show `=""` in this case

Now, let's compare it with assigning empty string
```bash
$ export DEF456=""
$ env | grep DEF456
DEF456=
$ export | grep DEF456
declare -x DEF456=""
```
created_at: 2025-05-04T07:26:50Z
author_association: COLLABORATOR
diff_hunk: @@ -22,7 +22,8 @@ int	ft_env(t_list *env)
 	while (ptr && ptr->content)
 	{
 		content = (t_minishell_env *)ptr->content;
-		ft_printf("%s=%s\n", content->name_value[0], content->name_value[1]);
+		if (content->name_value[1])
path: builtins/env.c
user: login: marlenasn
body: See another comment below, without `=` env variable still needs to be created on the list because there is a difference in how `env` and `export` commands without arguments show the variables that have NULL
Without creating the variable with NULL value the `export` command wouldn't know how to show it.
created_at: 2025-05-04T07:29:07Z
author_association: COLLABORATOR
diff_hunk: @@ -51,10 +51,12 @@ static char	*search_env_var(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
-		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
+		if (ft_strncmp(content->name_value[0], var, ft_strlen(content->name_value[0])) == 0)
 			break ;
 		env = env->next;
 	}
+	if (!content->name_value[1])
path: parser/var_expander_env.c
user: login: marlenasn
body: as mentioned before have to check this here just for NULL
otherwise this is a segfault when trying to work with `NULL`
```
str = ft_strdup(content->name_value[1]);
```
created_at: 2025-05-04T07:40:39Z
author_association: COLLABORATOR
diff_hunk: @@ -51,10 +51,12 @@ static char	*search_env_var(t_global *global, char *var)
 	while (env && env->content)
 	{
 		content = (t_minishell_env *) env->content;
-		if (ft_strncmp(content->name_value[0], var, ft_strlen(var)) == 0)
+		if (ft_strncmp(content->name_value[0], var, ft_strlen(content->name_value[0])) == 0)
path: parser/var_expander_env.c
user: login: marlenasn
body: Updated to check strings length first and skipping comparison, otherwise there was issue other way round as well :see_no_evil: 
`ABCD` matching `ABC`
created_at: 2025-05-04T07:41:31Z
author_association: COLLABORATOR

PR comments:
user: login: marlenasn
created_at: 2025-05-04T07:39:11Z
body: > `export` built-in is tricky in our `minishell` because it should offer a feature otherwise not available (as per requirements): `export TEST` - should switch `bool export` in our 't_minishell_env' if `TEST` exists, if not do nothing `export TEST="something_new"` - should create a new env variable with `bool export` as true `export TEST=""` - should overwrite previously set env variable value bash run: ![obraz](https://private-user-images.githubusercontent.com/37752214/440159651-13c421c3-9423-4433-b897-5bf3c9ee639e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDYzNDQ1OTAsIm5iZiI6MTc0NjM0NDI5MCwicGF0aCI6Ii8zNzc1MjIxNC80NDAxNTk2NTEtMTNjNDIxYzMtOTQyMy00NDMzLWI4OTctNWJmM2M5ZWU2MzllLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA0VDA3MzgxMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJhMzg1Y2JhZTRkYzZiYzFmMWZjOThlYjBlMDNmMDVlNzgwZGExYTIwZmEyOWQ3ZDY0ZjRhZmI0ZjM3Y2YxZTEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.WzQibilSQiEQg7fX1NcMGbh-yHG0ELrQbah4aHi3Akc)

Fixed that in the last commit it seems, see the output:
```
marlena@marlena-DELL:~/42/minishell$ ./minishell
minishell$ env  | grep TEST
minishell$ export TEST
minishell$ env | grep TEST
minishell$ export TEST="something else"
minishell$ env | grep TEST
TEST=something else
minishell$ export TEST
minishell$ env | grep TEST
TEST=something else
minishell$ export TEST=123
minishell$ env | grep TEST
TEST=123
```
author_association: COLLABORATOR
user: login: marlenasn
created_at: 2025-05-04T08:40:58Z
body: TODO memory leak fix
author_association: COLLABORATOR
user: login: aktyz
created_at: 2025-05-04T16:07:42Z
body: I think we had an error in `ft_get_env_var_value` returning a pointer to the content of the env list instead of a duplicated string. If it was freed and then we were trying to clear the list - it was throwing double free error.
Reworked because with the free you deleted in the last commit the program was duplicating "TEST" env variable instead of updating it's value
author_association: OWNER