--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* execution.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: lnikolov <lnikolov@student.42prague.com +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/07/21 08:57:54 by ljiriste #+# #+# */
+<<<<<<< HEAD
+/* Updated: 2024/08/29 18:21:04 by ljiriste ### ########.fr */
+=======
+/* Updated: 2024/08/29 11:19:20 by lnikolov ### ########.fr */
+>>>>>>> 42/trunk
+/* */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "builtins.h"
+#include "minishell_structs.h"
+#include "minishell.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/wait.h>
+
+int is_token_type(const t_parse_tree_node *node, const char *type)
+{
+ return (!ft_strcmp(node->token.type, type));
+}
+
+void clear_old(t_vec *assignments, const char *new)
+{
+ size_t i;
+ char **assignment;
+
+ i = assignments->size;
+ while (i > 0)
+ {
+ --i;
+ assignment = ft_vec_access(assignments, i);
+ if (cmp_var_name(*assignment, new))
+ continue ;
+ ft_vec_erase(assignments, i, free);
+ }
+ return ;
+}
+
+int add_word(t_vec *exp_str, const char *word, const t_execution_env *env, int quote);
+
+int add_assignment(t_vec *assignments, const char *assignment, const t_execution_env *env)
+{
+ t_vec advanced_copy;
+ char *copy;
+
+ if (ft_vec_init(&advanced_copy, sizeof(char)) != success)
+ return (1);
+ if (add_word(&advanced_copy, assignment, env, 0))
+ return (1);
+ *(char *)ft_vec_access(&advanced_copy, advanced_copy.size - 1) = '\0';
+ copy = advanced_copy.vec;
+ unquote_field(copy);
+ clear_old(assignments, copy);
+ if (ft_vec_append(assignments, ©) == success)
+ return (0);
+ free(copy);
+ return (1);
+}
+
+int save_assignments_prefix(t_vec *assignments, t_parse_tree_node *prefix, const t_execution_env *env)
+{
+ size_t i;
+ t_parse_tree_node *subnode;
+
+ i = 0;
+ while (i < prefix->children.size)
+ {
+ subnode = ft_vec_access(&prefix->children, i);
+ if (is_token_type(subnode, "ASSIGNMENT_WORD"))
+ {
+ if (add_assignment(assignments, subnode->token.str, env))
+ return (1);
+ }
+ else if (is_token_type(subnode, "cmd_prefix"))
+ if (save_assignments_prefix(assignments, subnode, env))
+ return (1);
+ ++i;
+ }
+ return (0);
+}
+
+int save_assignments(t_vec *assignments, t_parse_tree_node *simple_command, const t_execution_env *env)
+{
+ t_parse_tree_node *subnode;
+
+ if (ft_vec_init(assignments, sizeof(char *)) != success)
+ return (1);
+ subnode = ft_vec_access(&simple_command->children, 0);
+ if (is_token_type(subnode, "cmd_prefix"))
+ return (save_assignments_prefix(assignments, subnode, env));
+ return (0);
+}
+
+char *get_word(const t_parse_tree_node *parent)
+{
+ char *res;
+ const t_parse_tree_node *word = ft_vec_caccess(&parent->children, 0);
+
+ res = ft_strdup(word->token.str);
+ return (res);
+}
+
+int expand_filename(char **filename, const t_execution_env *env)
+{
+ t_vec advanced_copy;
+
+ if (ft_vec_init(&advanced_copy, sizeof(char)) != success)
+ return (1);
+ if (add_word(&advanced_copy, *filename, env, 0))
+ {
+ ft_vec_free(&advanced_copy, NULL);
+ return (1);
+ }
+ free(*filename);
+ *filename = advanced_copy.vec;
+ filename[0][advanced_copy.size - 1] = '\0';
+ unquote_field(*filename);
+ return (0);
+}
+
+int add_redirection_file(t_vec *redirections, t_parse_tree_node *io_file, int fd, const t_execution_env *env)
+{
+ t_redirection redir;
+ const t_parse_tree_node *operator;
+ char *filename;
+ int sec_fd;
+
+ filename = get_word(ft_vec_caccess(&io_file->children, 1));
+ if (!filename)
+ return (1);
+ expand_filename(&filename, env);
+ operator = ft_vec_caccess(&io_file->children, 0);
+ if (is_token_type(operator, "LESS"))
+ {
+ if (fd == -1)
+ fd = STDIN_FILENO;
+ sec_fd = open(filename, O_RDONLY);
+ if (sec_fd < 0)
+ {
+ free(filename);
+ return (1);
+ }
+ redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd};
+ }
+ else
+ {
+ if (fd < 0)
+ fd = STDOUT_FILENO;
+ if (is_token_type(operator, "GREAT"))
+ sec_fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ else
+ sec_fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ if (sec_fd == -1)
+ {
+ free(filename);
+ return (1);
+ }
+ redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd};
+ }
+ free(filename);
+ return (ft_vec_append(redirections, &redir) != success);
+}
+
+int write_line_to_pipe(int pipe_fd, const char *line, const t_execution_env *env, int expand)
+{
+ size_t i;
+ char *var;
+ const char *value;
+
+ i = 0;
+ while (line[i])
+ {
+ if (line[i] != '$' || !expand)
+ {
+ ft_dprintf(pipe_fd, "%c", line[i]);
+ ++i;
+ continue ;
+ }
+ ++i;
+ var = get_var_name(line + i);
+ if (!var)
+ return (1);
+ value = get_env_var_value(env, var);
+ if (value)
+ ft_dprintf(pipe_fd, "%s", value);
+ i += ft_strlen(var);
+ free(var);
+ }
+ return (0);
+}
+
+char *unquote_delimiter(const char *str)
+{
+ size_t i;
+ char *res;
+ char quote_char;
+
+ res = ft_strdup(str);
+ if (!res)
+ return (NULL);
+ i = 0;
+ quote_char = '\0';
+ while (res[i])
+ {
+ if ((res[i] == '"' || res[i] == '\''))
+ {
+ if (!quote_char)
+ {
+ quote_char = res[i];
+ ft_memmove(res + i, res + i + 1, ft_strlen(res + i + 1) + 1);
+ continue ;
+ }
+ else if (res[i] == quote_char)
+ {
+ quote_char = '\0';
+ ft_memmove(res + i, res + i + 1, ft_strlen(res + i + 1) + 1);
+ continue ;
+ }
+ }
+ ++i;
+ }
+ return (res);
+}
+
+int here_file_to_pipe(int pipe_fd, const char *delimiter, const t_execution_env *env)
+{
+ int expand;
+ char *line;
+ char *unquoted_delimiter;
+
+ unquoted_delimiter = unquote_delimiter(delimiter);
+ if (!unquoted_delimiter)
+ return (1);
+ expand = !ft_strcmp(unquoted_delimiter, delimiter);
+ ft_printf("> ");
+ line = get_next_line(STDIN_FILENO);
+ while (line && ft_strncmp(line, unquoted_delimiter, ft_strlen(line) - 1))
+ {
+ if (write_line_to_pipe(pipe_fd, line, env, expand))
+ {
+ get_next_line(-1);
+ free(line);
+ free(unquoted_delimiter);
+ return (1);
+ }
+ free(line);
+ ft_printf("> ");
+ line = get_next_line(STDIN_FILENO);
+ }
+ if (!line)
+ ft_printf("minishell: warning: here-document delimited by EOF instead of %s!\n", unquoted_delimiter);
+ get_next_line(-1);
+ free(line);
+ free(unquoted_delimiter);
+ return (0);
+}
+
+int add_redirection_here(t_vec *redirections, t_parse_tree_node *io_here, int fd, const t_execution_env *env)
+{
+ char *delimiter;
+ int pipe_fds[2];
+ int err;
+ t_redirection redir;
+
+ delimiter = get_word(ft_vec_caccess(&io_here->children, 1));
+ if (!delimiter)
+ return (1);
+ if (fd == -1)
+ fd = STDIN_FILENO;
+ if (pipe(pipe_fds))
+ {
+ free(delimiter);
+ return (1);
+ }
+ err = here_file_to_pipe(pipe_fds[1], delimiter, env);
+ close(pipe_fds[1]);
+ free(delimiter);
+ if (err)
+ return (1);
+ redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = pipe_fds[0]};
+ return (ft_vec_append(redirections, &redir) != success);
+}
+
+int add_redirection(t_vec *redirections, t_parse_tree_node *redirect, const t_execution_env *env)
+{
+ int fd;
+ t_parse_tree_node *subnode;
+
+ fd = -1;
+ subnode = ft_vec_access(&redirect->children, 0);
+ if (redirect->children.size == 2)
+ {
+ fd = ft_atoi(subnode->token.str);
+ if (fd < 0)
+ fd = -2;
+ subnode = ft_vec_access(&redirect->children, 1);
+ }
+ if (is_token_type(subnode, "io_file"))
+ return (add_redirection_file(redirections, subnode, fd, env));
+ else
+ return (add_redirection_here(redirections, subnode, fd, env));
+}
+
+int save_redirections_psfix(t_vec *redirections, t_parse_tree_node *node, const t_execution_env *env)
+{
+ size_t i;
+ t_parse_tree_node *subnode;
+
+ i = 0;
+ while (i < node->children.size)
+ {
+ subnode = ft_vec_access(&node->children, i);
+ if (is_token_type(subnode, "io_redirect"))
+ {
+ if (add_redirection(redirections, subnode, env))
+ return (1);
+ }
+ else if (is_token_type(subnode, "cmd_suffix") || is_token_type(subnode, "cmd_prefix"))
+ if (save_redirections_psfix(redirections, subnode, env))
+ return (1);
+ ++i;
+ }
+ return (0);
+}
+
+int save_redirections(t_vec *redirections, t_parse_tree_node *simple_command, const t_execution_env *env)
+{
+ t_parse_tree_node *subnode;
+
+ if (ft_vec_init(redirections, sizeof(t_redirection)) != success)
+ return (1);
+ subnode = ft_vec_access(&simple_command->children, 0);
+ if (is_token_type(subnode, "cmd_prefix"))
+ if (save_redirections_psfix(redirections, subnode, env))
+ return (1);
+ subnode = ft_vec_access(&simple_command->children, simple_command->children.size - 1);
+ if (is_token_type(subnode, "cmd_suffix"))
+ if (save_redirections_psfix(redirections, subnode, env))
+ return (1);
+ return (0);
+}
+
+static const char space = ' ';
+
+int add_word(t_vec *exp_str, const char *word, const t_execution_env *env, int quote)
+{
+ size_t i;
+ char *var;
+ char *value;
+ const char *const_val;
+ int single_quoted;
+ int error;
+
+ error = 0;
+ single_quoted = 0;
+ i = 0;
+ while (word[i])
+ {
+ if (word[i] == '\'')
+ single_quoted = !single_quoted;
+ if (word[i] == '$' && !single_quoted && (ft_isalnum(word[i + 1]) || word[i + 1] == '_' || word[i + 1] == '?'))
+ {
+ ++i;
+ if (word[i] == '?')
+ {
+ ++i;
+ value = ft_itoa(env->ret_val);
+ }
+ else
+ {
+ var = get_var_name(word + i);
+ if (!var)
+ return (1);
+ i += ft_strlen(var);
+ const_val = get_env_var_value(env, var);
+ free(var);
+ if (!const_val)
+ continue;
+ value = ft_strdup(const_val);
+ }
+ if (!value)
+ return (1);
+ if (quote)
+ error = error || ft_vec_append(exp_str, "'") != success;
+ error = error || ft_vec_append_range(exp_str, value, ft_strlen(value)) != success;
+ if (quote)
+ error = error || ft_vec_append(exp_str, "'") != success;
+ free(value);
+ if (error)
+ return (1);
+ }
+ else
+ if (ft_vec_append(exp_str, word + (i++)) != success)
+ return (1);
+ }
+ if (ft_vec_append(exp_str, &space) != success)
+ return (1);
+ return (0);
+}
+
+int expand_cmd(t_vec *exp_str, const t_parse_tree_node *node, const t_execution_env *env)
+{
+ size_t i;
+ const t_parse_tree_node *subnode;
+
+ i = 0;
+ while (i < node->children.size)
+ {
+ subnode = ft_vec_caccess(&node->children, i);
+ if (is_token_type(subnode, "cmd_suffix"))
+ {
+ if (expand_cmd(exp_str, subnode, env))
+ return (1);
+ }
+ else if (is_token_type(subnode, "WORD"))
+ if (add_word(exp_str, subnode->token.str, env, 0))
+ return (1);
+ ++i;
+ }
+ return (0);
+}
+
+size_t get_next_word_size(const char *str)
+{
+ size_t n;
+ char quote;
+
+ quote = 0;
+ n = 0;
+ while (str[n])
+ {
+ if (str[n] == ' ' && !quote)
+ break ;
+ if ((str[n] == '"' || str[n] == '\''))
+ {
+ if (!quote)
+ quote = str[n];
+ else if (quote == str[n])
+ quote = 0;
+ }
+ ++n;
+ }
+ return (n);
+}
+
+void unquote_field(char *field)
+{
+ size_t i;
+ char quote;
+
+ quote = 0;
+ i = 0;
+ while (field && field[i])
+ {
+ if (field[i] == '"' || field[i] == '\'')
+ {
+ if (!quote)
+ quote = field[i];
+ else if (quote == field[i])
+ quote = 0;
+ else
+ {
+ ++i;
+ continue ;
+ }
+ ft_memmove(field + i, field + i + 1, ft_strlen(field + i + 1) + 1);
+ }
+ else
+ ++i;
+ }
+ return ;
+}
+
+void unquote(char **fields)
+{
+ size_t i;
+
+ i = 0;
+ while (fields[i])
+ {
+ unquote_field(fields[i]);
+ ++i;
+ }
+ return ;
+}
+
+static const void *nullptr = NULL;
+
+char **quoted_split(const char *str)
+{
+ size_t i;
+ size_t n;
+ t_vec fields;
+ char *new_str;
+
+ if (ft_vec_init(&fields, sizeof(char *)) != success)
+ return (NULL);
+ i = 0;
+ while (str[i])
+ {
+ while (str[i] == ' ')
+ ++i;
+ n = get_next_word_size(str + i);
+ if (n == 0)
+ break ;
+ new_str = ft_strndup(str + i, n);
+ if (!new_str)
+ {
+ ft_vec_free(&fields, free);
+ return (NULL);
+ }
+ if (ft_vec_append(&fields, &new_str) != success)
+ {
+ ft_vec_free(&fields, free);
+ free(new_str);
+ return (NULL);
+ }
+ i += n;
+ }
+ if (ft_vec_append(&fields, &nullptr) != success)
+ {
+ ft_vec_free(&fields, free);
+ return (NULL);
+ }
+ return (fields.vec);
+}
+
+static const char null_char = '\0';
+
+char **expand(t_parse_tree_node *simple_command, const t_execution_env *env)
+{
+ size_t i;
+ char **fields;
+ t_vec expanded_str;
+ t_parse_tree_node *subnode;
+
+ ft_vec_init(&expanded_str, sizeof(char));
+ ft_vec_reserve(&expanded_str, 64);
+ i = 0;
+ while (i < simple_command->children.size)
+ {
+ subnode = ft_vec_access(&simple_command->children, i);
+ if (is_token_type(subnode, "cmd_name")
+ || is_token_type(subnode, "cmd_word")
+ || is_token_type(subnode, "cmd_suffix"))
+ if (expand_cmd(&expanded_str, subnode, env))
+ {
+ ft_vec_free(&expanded_str, NULL);
+ return (NULL);
+ }
+ ++i;
+ }
+ if (ft_vec_append(&expanded_str, &null_char) != success)
+ {
+ ft_vec_free(&expanded_str, NULL);
+ return (NULL);
+ }
+ fields = quoted_split(expanded_str.vec);
+ ft_vec_free(&expanded_str, NULL);
+ unquote(fields);
+ return (fields);
+}
+
+int assignments_to_env(const t_vec *assignments, t_execution_env *env)
+{
+ size_t i;
+ const char *var_line;
+ char *var_name;
+
+ i = 0;
+ while (i < assignments->size)
+ {
+ var_line = *(char **)ft_vec_caccess(assignments, i);
+ var_name = get_var_name(var_line);
+ if (!var_name)
+ return (1);
+ if (set_env_var_value(env, var_name, var_line + ft_strlen(var_name) + 1))
+ {
+ free(var_name);
+ return (1);
+ }
+ free(var_name);
+ ++i;
+ }
+ return (0);
+}
+
+void free_split(char **fields)
+{
+ size_t i;
+
+ i = 0;
+ while (fields[i])
+ {
+ free(fields[i]);
+ ++i;
+ }
+ free(fields);
+ return ;
+}
+
+int contains_path(const char *str)
+{
+ return (ft_strchr(str, '/') != NULL);
+}
+
+int file_exists(const char *path)
+{
+ return (!access(path, F_OK));
+}
+
+int is_contained_in_dir(const char *exe_name, const char *dir_name)
+{
+ DIR *dir;
+ struct dirent *dir_entry;
+
+ dir = opendir(dir_name);
+ if (!dir)
+ return (0);
+ dir_entry = readdir(dir);
+ while (dir_entry)
+ {
+ if (!ft_strcmp(dir_entry->d_name, exe_name))
+ {
+ closedir(dir);
+ return (1);
+ }
+ dir_entry = readdir(dir);
+ }
+ closedir(dir);
+ return (0);
+}
+
+char *find_exe(const char *exe_name, const t_execution_env *env)
+{
+ const char *path;
+ char **paths;
+ size_t i;
+ char *res;
+
+ path = get_env_var_value(env, "PATH");
+ if (!path)
+ return (NULL);
+ paths = ft_split(path, ":");
+ if (!paths)
+ return (NULL);
+ res = NULL;
+ i = 0;
+ while (paths[i] && !res)
+ {
+ if (is_contained_in_dir(exe_name, paths[i]))
+ if (ft_strcat_alloc(&res, paths[i]))
+ if (ft_strcat_alloc(&res, "/"))
+ ft_strcat_alloc(&res, exe_name);
+ ++i;
+ }
+ free_split(paths);
+ return (res);
+}
+
+int dup_pipes(const t_execution_env *env)
+{
+ if (dup2(env->stdin_fd, STDIN_FILENO) == -1)
+ return (1);
+ if (dup2(env->stdout_fd, STDOUT_FILENO) == -1)
+ return (1);
+ return (0);
+}
+
+void close_pipes(const t_execution_env *env)
+{
+ close(env->stdin_fd);
+ close(env->stdout_fd);
+ return ;
+}
+
+int dup_redirections(__attribute__((unused)) const t_vec *redirections)
+{
+ size_t i;
+ const t_redirection *redir;
+
+ i = 0;
+ while (i < redirections->size)
+ {
+ redir = ft_vec_caccess(redirections, i);
+ dup2(redir->from_to_fds[1], redir->from_to_fds[0]);
+ close(redir->from_to_fds[1]);
+ ++i;
+ }
+ return (0);
+}
+
+void close_redirections(const t_vec *redirections)
+{
+ size_t i;
+ const t_redirection *redir;
+
+ i = 0;
+ while (i < redirections->size)
+ {
+ redir = ft_vec_caccess(redirections, i);
+ close(redir->from_to_fds[0]);
+ ++i;
+ }
+ return ;
+}
+
+int add_exported(__attribute__((unused)) t_vec *assignments, __attribute__((unused)) const t_execution_env *env)
+{
+ size_t i;
+ char *var;
+ const t_vec *exported;
+
+ exported = &env->vars->exported;
+ i = 0;
+ while (i < exported->size)
+ {
+ var = ft_strdup(*(char *const *)ft_vec_caccess(exported, i));
+ if (ft_vec_append(assignments, &var) != success) // Should exported be overwritten?
+ return (1);
+ ++i;
+ }
+ return (0);
+}
+
+int is_builtin(const char *str)
+{
+ if (!ft_strcmp(str, "cd"))
+ return (1);
+ if (!ft_strcmp(str, "echo"))
+ return (1);
+ if (!ft_strcmp(str, "pwd"))
+ return (1);
+ if (!ft_strcmp(str, "env"))
+ return (1);
+ if (!ft_strcmp(str, "export"))
+ return (1);
+ if (!ft_strcmp(str, "unset"))
+ return (1);
+ if (!ft_strcmp(str, "exit"))
+ return (1);
+ return (0);
+}
+
+size_t count_fields(char **fields)
+{
+ size_t i;
+
+ i = 0;
+ while (fields[i])
+ ++i;
+ return (i);
+}
+
+int save_std_filenos(int fds[3])
+{
+ fds[0] = dup(STDIN_FILENO);
+ if (fds[0] < 0)
+ return (1);
+ fds[1] = dup(STDOUT_FILENO);
+ if (fds[1] < 0)
+ {
+ close(fds[0]);
+ return (1);
+ }
+ fds[2] = dup(STDERR_FILENO);
+ if (fds[2] < 0)
+ {
+ close(fds[0]);
+ close(fds[1]);
+ return (1);
+ }
+ return (0);
+}
+
+int restore_std_filenos(int fds[3])
+{
+ if (dup2(fds[0], STDIN_FILENO) == -1)
+ return (1);
+ if (dup2(fds[1], STDOUT_FILENO) == -1)
+ return (1);
+ if (dup2(fds[2], STDERR_FILENO) == -1)
+ return (1);
+ close(fds[0]);
+ close(fds[1]);
+ close(fds[2]);
+ return (0);
+}
+
+int ex_builtin(char **fields, __attribute__((unused)) t_vec *assignments, __attribute__((unused)) const t_vec *redirections, t_execution_env *env)
+{
+ int fds[3];
+
+ save_std_filenos(fds);
+ dup_pipes(env);
+ dup_redirections(redirections);
+ if (!ft_strcmp(fields[0], "cd"))
+ env->last_builtin_ret_val = cd(count_fields(fields), fields, env);
+ else if (!ft_strcmp(fields[0], "echo"))
+ env->last_builtin_ret_val = echo(count_fields(fields), fields);
+ else if (!ft_strcmp(fields[0], "pwd"))
+ env->last_builtin_ret_val = pwd();
+ else if (!ft_strcmp(fields[0], "env"))
+ env->last_builtin_ret_val = ft_env(count_fields(fields), env);
+ else if (!ft_strcmp(fields[0], "export"))
+ env->last_builtin_ret_val = export(count_fields(fields), fields, env);
+ else if (!ft_strcmp(fields[0], "unset"))
+ env->last_builtin_ret_val = unset(count_fields(fields), fields, env);
+ else if (!ft_strcmp(fields[0], "exit"))
+ env->last_builtin_ret_val = execute_exit(count_fields(fields), fields, env);
+ else
+ return (1);
+ env->last_was_builtin = 1;
+ close_redirections(redirections);
+ close_pipes(env);
+ restore_std_filenos(fds);
+ return (0);
+}
+
+int ex_fields(char **fields, t_vec *assignments, const t_vec *redirections, t_execution_env *env)
+{
+ pid_t pid;
+ char *path;
+
+ if (is_builtin(fields[0]))
+ return (ex_builtin(fields, assignments, redirections, env));
+ env->last_was_builtin = 0;
+ path = NULL;
+ if (contains_path(fields[0]) && file_exists(fields[0]))
+ path = ft_strdup(fields[0]);
+ else if (!contains_path(fields[0]))
+ path = find_exe(fields[0], env);
+ if (!path)
+ return (1);
+ pid = fork();
+ if (pid == 0)
+ {
+ dup_pipes(env);
+ dup_redirections(redirections);
+ add_exported(assignments, env);
+ ft_vec_append(assignments, nullptr);
+ execve(path, fields, assignments->vec);
+ exit(-1);
+ }
+ free(path);
+ if (pid > 0)
+ {
+ if (ft_vec_append(&env->child_pids, &pid) != success)
+ return (1);
+ }
+ else
+ return (1);
+ return (0);
+}
+
+void close_redirection(void *v_redir)
+{
+ t_redirection *redir;
+
+ redir = v_redir;
+ close(redir->from_to_fds[1]);
+ return ;
+}
+
+int ex_simple_command(t_parse_tree_node *simple_command, t_execution_env *env)
+{
+ t_vec redirections;
+ t_vec assignments;
+ char **fields;
+ int res;
+
+ res = save_redirections(&redirections, simple_command, env);
+ res = save_assignments(&assignments, simple_command, env) || res;
+ fields = NULL;
+ if (!res)
+ fields = expand(simple_command, env);
+ if (!fields || res)
+ {
+ ft_vec_free(&redirections, close_redirection);
+ ft_vec_free(&assignments, free);
+ return (1);
+ }
+ if (!*fields)
+ {
+ assignments_to_env(&assignments, env);
+ ft_vec_free(&redirections, close_redirection);
+ ft_vec_free(&assignments, free_str);
+ free_split(fields);
+ return (0);
+ }
+ res = ex_fields(fields, &assignments, &redirections, env);
+ ft_vec_free(&redirections, close_redirection);
+ ft_vec_free(&assignments, free_str);
+ free_split(fields);
+ return (res);
+}
+
+t_ft_stat v_strcopy(void *v_dest, const void *v_src)
+{
+ char **dest;
+ const char *const *src;
+
+ dest = v_dest;
+ src = v_src;
+ if (!*src)
+ {
+ *dest = NULL;
+ return (success);
+ }
+ *dest = ft_strdup(*src);
+ if (!*dest)
+ return (alloc_fail);
+ return (success);
+}
+
+t_ft_stat v_copy_redir(void *v_dest, const void *v_src)
+{
+ t_redirection *dest;
+ const t_redirection *src;
+
+ dest = v_dest;
+ src = v_src;
+ *dest = *src;
+ return (success);
+}
+
+int ex_program(t_parse_tree_node *program, t_execution_env *env);
+
+int subshell(t_parse_tree_node *program, t_execution_env *env)
+{
+ int res;
+ int status;
+ pid_t pid;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ env->subshell = 1;
+ res = ex_program(program, env);
+ env->exit = 1;
+ return (res);
+ }
+ else if (pid < 0)
+ return (1);
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status))
+ return (1);
+ env->ret_val = WEXITSTATUS(status);
+ return (0);
+}
+
+int ex_command(t_parse_tree_node *command, t_execution_env *env)
+{
+ t_parse_tree_node *comp_command;
+
+ if (env->exit)
+ return (0);
+ if (is_token_type(ft_vec_caccess(&command->children, 0), "simple_command"))
+ return (ex_simple_command(ft_vec_access(&command->children, 0), env));
+ else
+ {
+ comp_command = ft_vec_access(&command->children, 0);
+ return (subshell(ft_vec_access(&comp_command->children, 1), env));
+ }
+}
+
+void killall(t_vec *child_pids, int sig_num)
+{
+ pid_t child_pid;
+ size_t i;
+
+ i = 0;
+ while (i < child_pids->size)
+ {
+ child_pid = *(pid_t *)ft_vec_access(child_pids, i);
+ kill(child_pid, sig_num);
+ ++i;
+ }
+ return ;
+}
+
+void wait_for_return(t_execution_env *env)
+{
+ pid_t last_pid;
+ int status;
+
+ if (env->last_was_builtin)
+ env->ret_val = env->last_builtin_ret_val;
+ else
+ {
+ if (env->child_pids.size == 0)
+ return ;
+ last_pid = *(pid_t *)ft_vec_access(&env->child_pids, env->child_pids.size - 1);
+ waitpid(last_pid, &status, 0);
+ if (g_last_signal != 0)
+ killall(&env->child_pids, g_last_signal);
+ if (g_last_signal == 0)
+ if (WIFEXITED(status))
+ env->ret_val = WEXITSTATUS(status);
+ }
+ ft_vec_free(&env->child_pids, NULL);
+ return ;
+}
+
+int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth)
+{
+ int pipe_fds[2];
+
+ if (g_last_signal != 0)
+ return (0);
+ if (pipeline->children.size == 1)
+ {
+ if (ex_command(ft_vec_access(&pipeline->children, 0), env))
+ return (1);
+ }
+ else
+ {
+ if (pipe(pipe_fds))
+ return (1);
+ ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+ ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1);
+ ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+ close(pipe_fds[1]);
+ ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+ ex_command(ft_vec_access(&pipeline->children, 2), env);
+ ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+ close(pipe_fds[0]);
+ }
+ if (depth == 0)
+ wait_for_return(env);
+ return (0);
+}
+
+int ex_program(t_parse_tree_node *program, t_execution_env *env)
+{
+ if (program->children.size == 1)
+ return (ex_pipeline(ft_vec_access(&program->children, 0), env, 0));
+ if (ex_program(ft_vec_access(&program->children, 0), env))
+ return (1);
+ if (is_token_type(ft_vec_caccess(&program->children, 1), "AND_IF"))
+ {
+ if (env->ret_val == 0)
+ return (ex_pipeline(ft_vec_access(&program->children, 2), env, 0));
+ }
+ else
+ {
+ if (env->ret_val != 0)
+ return (ex_pipeline(ft_vec_access(&program->children, 2), env, 0));
+ }
+ return (0);
+}
+
+int execute(t_tree *parse_tree, t_execution_env *env)
+{
+ int res;
+
+ res = ex_program(parse_tree, env);
+ if (g_last_signal != 0)
+ {
+ env->ret_val = 128 + g_last_signal;
+ g_last_signal = 0;
+ }
+ return (res);
+}