Refactor execution.c to files of max 5 functions
authorLilia-42 <nikolovalilianenkova@gmail.com>
Sun, 1 Sep 2024 12:07:07 +0000 (14:07 +0200)
committerLilia-42 <nikolovalilianenkova@gmail.com>
Sun, 1 Sep 2024 12:07:07 +0000 (14:07 +0200)
18 files changed:
Makefile
inc/execution.h
src/add_word.c [new file with mode: 0644]
src/assignments.c [new file with mode: 0644]
src/exe_find.c [new file with mode: 0644]
src/exe_helpers.c [new file with mode: 0644]
src/exe_pipeline.c [new file with mode: 0644]
src/exe_prepare.c [new file with mode: 0644]
src/execute.c [new file with mode: 0644]
src/execute_builtin.c [new file with mode: 0644]
src/execute_cmd.c [new file with mode: 0644]
src/execute_raw.c [new file with mode: 0644]
src/execution.c [deleted file]
src/expand.c [new file with mode: 0644]
src/expand_split.c [new file with mode: 0644]
src/redir_file.c [new file with mode: 0644]
src/redir_here.c [new file with mode: 0644]
src/redirection.c [new file with mode: 0644]

index 26c0c027ae2562c58008cc61e328b1748b9968a7..62925dcab0211857207a06a62e4338dedc697991 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,10 +35,25 @@ SOURCES :=  main.c                          \
                        token_categorize.c      \
                        token_finish.c          \
                        parsing.c                       \
-                       execution.c                     \
+                                                               \
+                       execute.c                       \
+                       add_word.c                      \
+                       assignments.c           \
+                       exe_find.c                      \
+                       exe_helpers.c           \
+                       exe_pipeline.c          \
+                       exe_prepare.c           \
+                       execute_builtin.c       \
+                       execute_cmd.c           \
+                       execute_raw.c           \
+                       expand.c                        \
+                       expand_split.c          \
+                       redirection.c           \
+                       redir_file.c            \
+                       redir_here.c            \
+                                                               \
                        helpers.c                       \
                        vars_helpers.c          \
-                                                               \
                        builtins/cd.c           \
                        builtins/echo.c         \
                        builtins/pwd.c          \
index 9aa5207f32ed23f778d36b5d18b061c6c436ac27..bc27ae12199dc0f41a8bf57063e0efb23fbd6e6a 100644 (file)
@@ -6,11 +6,52 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/08/02 17:40:19 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/26 11:42:37 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/09/01 14:03:42 by lnikolov         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #ifndef EXECUTION_H
 # define EXECUTION_H
 
+# include "minishell_structs.h"
+# include <signal.h>
+
+extern volatile sig_atomic_t   g_last_signal;
+
+void   free_split(char **fields);
+int    set_quote(char *quote, char c);
+int    is_token_type(const t_parse_tree_node *node, const char *type);
+
+int    dup_pipes(const t_execution_env *env);
+int    dup_redirections(const t_vec *redirections);
+
+char   **quoted_split(const char *str);
+int    unquote_field(char *field);
+int    add_word(t_vec *exp_str, const char *word,
+       const t_execution_env *env, int enquote_result);
+char   **expand(t_parse_tree_node *simple_command, const t_execution_env *env);
+
+char   *find_exe(const char *exe_name, const t_execution_env *env);
+int    prepare_env(t_execution_env *env,
+               const t_vec *redirections, t_vec *assignments);
+
+int    ex_builtin(char **fields, __attribute__((unused))
+       t_vec *assignments, const t_vec *redirections, t_execution_env *env);
+int    ex_fields(char **fields, t_vec *assignments,
+       const t_vec *redirections, t_execution_env *env);
+int    ex_command(t_parse_tree_node *command, t_execution_env *env);
+int    ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth);
+int    ex_program(t_parse_tree_node *program, t_execution_env *env);
+
+char   *get_word(const t_parse_tree_node *parent);
+int    add_redirection_here(t_vec *redirections,
+       t_parse_tree_node *io_here, int fd, const t_execution_env *env);
+int    add_redirection_file(t_vec *redirections,
+       t_parse_tree_node *io_file, int fd, t_execution_env *env);
+
+int    save_redirections(t_vec *redirections,
+       t_parse_tree_node *simple_command, t_execution_env *env);
+int    save_assignments(t_vec *assignments, t_parse_tree_node *simple_command,
+       const t_execution_env *env);
+
 #endif // EXECUTION_H
diff --git a/src/add_word.c b/src/add_word.c
new file mode 100644 (file)
index 0000000..6db9d3d
--- /dev/null
@@ -0,0 +1,98 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   add_word.c                                         :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:51:31 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:24:55 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <sys/wait.h>
+
+static int     is_expandable(const char *str)
+{
+       return (str[0] == '$'
+               && (ft_isalpha(str[1])
+                       || str[1] == '_'
+                       || str[1] == '?'));
+}
+
+static char    *get_value(const char *word, size_t *i, const t_execution_env *env)
+{
+       char            *var;
+       char            *value;
+       const char      *const_val;
+
+       if (word[*i] == '?')
+       {
+               ++*i;
+               value = ft_itoa(env->ret_val);
+       }
+       else
+       {
+               var = get_var_name(word + *i);
+               if (!var)
+                       return (NULL);
+               *i += ft_strlen(var);
+               const_val = get_env_var_value(env, var);
+               free(var);
+               if (!const_val)
+                       return (ft_strdup(""));
+               value = ft_strdup(const_val);
+       }
+       return (value);
+}
+
+static int     append_value(t_vec *exp_str, const char *value, int enquote_result)
+{
+       int     error;
+
+       if (!value)
+               return (1);
+       if (enquote_result)
+       {
+               error = ft_vec_append(exp_str, "'") != success;
+               error = error
+                       || ft_vec_append_range(exp_str, value, ft_strlen(value)) != success;
+               error = error || ft_vec_append(exp_str, "'") != success;
+               return (error);
+       }
+       return (ft_vec_append_range(exp_str, value, ft_strlen(value)) != success);
+}
+
+int    add_word(t_vec *exp_str, const char *word,
+       const t_execution_env *env, int enquote_result)
+{
+       size_t          i;
+       char            quote;
+       const char      space = ' ';
+       char            *value;
+
+       quote = '\0';
+       i = 0;
+       while (word[i])
+       {
+               set_quote(&quote, word[i]);
+               if (is_expandable(word + (i++)) && quote != '\'')
+               {
+                       value = get_value(word, &i, env);
+                       if (append_value(exp_str, value, enquote_result))
+                       {
+                               free(value);
+                               return (1);
+                       }
+                       free(value);
+               }
+               else
+                       if (ft_vec_append(exp_str, word + i - 1) != success)
+                               return (1);
+       }
+       return (ft_vec_append(exp_str, &space) != success);
+}
\ No newline at end of file
diff --git a/src/assignments.c b/src/assignments.c
new file mode 100644 (file)
index 0000000..8042f94
--- /dev/null
@@ -0,0 +1,89 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   assignments.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:19:00 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 14:00:36 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+
+static 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 ;
+}
+
+static 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, &copy) == success)
+               return (0);
+       free(copy);
+       return (1);
+}
+
+static 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);
+}
diff --git a/src/exe_find.c b/src/exe_find.c
new file mode 100644 (file)
index 0000000..694e112
--- /dev/null
@@ -0,0 +1,65 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   exe_find.c                                         :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:28 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:23:51 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <dirent.h>
+
+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);
+}
diff --git a/src/exe_helpers.c b/src/exe_helpers.c
new file mode 100644 (file)
index 0000000..9e3e0d0
--- /dev/null
@@ -0,0 +1,81 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   exe_helpers.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/07/21 08:57:54 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/09/01 13:22:49 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "libft.h"
+#include <stdlib.h>
+
+// Returns 1 when quote is set (or unset)
+// and 0 when quote is left in current state
+int    set_quote(char *quote, char c)
+{
+       if (c == '"' || c == '\'')
+       {
+               if (*quote == '\0')
+                       *quote = c;
+               else if (*quote == c)
+                       *quote = '\0';
+               else
+                       return (0);
+               return (1);
+       }
+       return (0);
+}
+
+int    is_token_type(const t_parse_tree_node *node, const char *type)
+{
+       return (!ft_strcmp(node->token.type, type));
+}
+
+// Returns 1 if any unquoting happened else returns 0
+int    unquote_field(char *field)
+{
+       int             res;
+       size_t  i;
+       char    quote;
+
+       res = 0;
+       quote = 0;
+       i = 0;
+       while (field && field[i])
+       {
+               if (field[i] == '"' || field[i] == '\'')
+               {
+                       if (!set_quote(&quote, field[i]))
+                       {
+                               ++i;
+                               continue ;
+                       }
+                       res = 1;
+                       ft_memmove(field + i, field + i + 1, ft_strlen(field + i + 1) + 1);
+               }
+               else
+                       ++i;
+       }
+       return (res);
+}
+
+void   free_split(char **fields)
+{
+       size_t  i;
+
+       if (!fields)
+               return ;
+       i = 0;
+       while (fields[i])
+       {
+               free(fields[i]);
+               ++i;
+       }
+       free(fields);
+       return ;
+}
\ No newline at end of file
diff --git a/src/exe_pipeline.c b/src/exe_pipeline.c
new file mode 100644 (file)
index 0000000..bf8e0bb
--- /dev/null
@@ -0,0 +1,133 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   exe_pipeline.c                                     :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:52:56 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:43:51 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+static 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 ;
+}
+
+static void    wait_for_all_to_end(t_vec *child_pids)
+{
+       size_t  i;
+       pid_t   pid;
+       int             sig_num;
+
+       sig_num = 0;
+       i = child_pids->size;
+       while (i > 0)
+       {
+               --i;
+               pid = *(pid_t *)ft_vec_access(child_pids, i);
+               if (g_last_signal == 0)
+                       waitpid(pid, NULL, 0);
+               if (g_last_signal)
+               {
+                       sig_num = g_last_signal;
+                       g_last_signal = 0;
+                       killall(child_pids, g_last_signal);
+                       i = child_pids->size;
+               }
+               ft_vec_forget(child_pids, i);
+       }
+       ft_vec_free(child_pids, NULL);
+       if (g_last_signal == 0)
+               g_last_signal = sig_num;
+       return ;
+}
+
+static void    wait_for_return(t_execution_env *env)
+{
+       pid_t   last_pid;
+       int             status;
+
+       if (env->last_was_builtin)
+               env->ret_val = env->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)
+                       if (WIFEXITED(status))
+                               env->ret_val = WEXITSTATUS(status);
+       }
+       wait_for_all_to_end(&env->child_pids);
+       return ;
+}
+
+static int     advance_pipeline(t_parse_tree_node *pipeline,
+               t_execution_env *env, int depth)
+{
+       int     pipe_fds[2];
+       int     res;
+
+       if (pipe(pipe_fds))
+               return (1);
+       res = ft_vec_append(&env->fds_to_close, &pipe_fds[0]);
+       res = res || ft_vec_append(&env->fds_to_close, &env->stdout_fd);
+       ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+       res = res
+               || ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1);
+       ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+       close(pipe_fds[1]);
+       if (res == 0)
+       {
+               ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
+               ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
+       }
+       ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+       res = res || ex_command(ft_vec_access(&pipeline->children, 2), env);
+       ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+       close(pipe_fds[0]);
+       return (res);
+}
+
+int    ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth)
+{
+       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 (advance_pipeline(pipeline, env, depth))
+               {
+                       killall(&env->child_pids, SIGTERM);
+                       return (1);
+               }
+       }
+       if (depth == 0)
+               wait_for_return(env);
+       return (0);
+}
diff --git a/src/exe_prepare.c b/src/exe_prepare.c
new file mode 100644 (file)
index 0000000..8c6abfd
--- /dev/null
@@ -0,0 +1,91 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   exe_prepare.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:23 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:25:40 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+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);
+       if (env->stdin_fd != STDIN_FILENO)
+               close(env->stdin_fd);
+       if (env->stdout_fd != STDOUT_FILENO)
+               close(env->stdout_fd);
+       return (0);
+}
+
+int    dup_redirections(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);
+}
+
+static int     add_exported(t_vec *assignments, 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)
+                       return (1);
+               ++i;
+       }
+       return (0);
+}
+
+static void    close_fds(t_vec *fds_to_close)
+{
+       int             fd;
+       size_t  i;
+
+       i = 0;
+       while (i < fds_to_close->size)
+       {
+               fd = *(int *)ft_vec_access(fds_to_close, i);
+               close(fd);
+               ++i;
+       }
+       return ;
+}
+
+int    prepare_env(t_execution_env *env,
+               const t_vec *redirections, t_vec *assignments)
+{
+       int     res;
+
+       close_fds(&env->fds_to_close);
+       res = dup_pipes(env);
+       res = dup_redirections(redirections) || res;
+       res = add_exported(assignments, env) || res;
+       return (res);
+}
\ No newline at end of file
diff --git a/src/execute.c b/src/execute.c
new file mode 100644 (file)
index 0000000..09e482f
--- /dev/null
@@ -0,0 +1,47 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   execute.c                                          :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:52:49 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:29:51 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+
+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);
+}
diff --git a/src/execute_builtin.c b/src/execute_builtin.c
new file mode 100644 (file)
index 0000000..e3dbab9
--- /dev/null
@@ -0,0 +1,115 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   execute_builtin.c                                  :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:07 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:26:33 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "builtins.h"
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+static 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);
+}
+
+static 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);
+}
+
+static void    close_pipes(const t_execution_env *env)
+{
+       close(env->stdin_fd);
+       close(env->stdout_fd);
+       return ;
+}
+
+static size_t  count_fields(char **fields)
+{
+       size_t  i;
+
+       i = 0;
+       while (fields[i])
+               ++i;
+       return (i);
+}
+
+static 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    ex_builtin(char **fields, __attribute__((unused))
+       t_vec *assignments, 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->builtin_ret_val = cd(count_fields(fields), fields, env);
+       else if (!ft_strcmp(fields[0], "echo"))
+               env->builtin_ret_val = echo(count_fields(fields), fields);
+       else if (!ft_strcmp(fields[0], "pwd"))
+               env->builtin_ret_val = pwd();
+       else if (!ft_strcmp(fields[0], "env"))
+               env->builtin_ret_val = ft_env(count_fields(fields), env);
+       else if (!ft_strcmp(fields[0], "export"))
+               env->builtin_ret_val = export(count_fields(fields), fields, env);
+       else if (!ft_strcmp(fields[0], "unset"))
+               env->builtin_ret_val = unset(count_fields(fields), fields, env);
+       else if (!ft_strcmp(fields[0], "exit"))
+               env->builtin_ret_val = execute_exit(count_fields(fields), fields, env);
+       else
+               return (1);
+       close_redirections(redirections);
+       close_pipes(env);
+       restore_std_filenos(fds);
+       return (0);
+}
\ No newline at end of file
diff --git a/src/execute_cmd.c b/src/execute_cmd.c
new file mode 100644 (file)
index 0000000..9256724
--- /dev/null
@@ -0,0 +1,114 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   execute_cmd.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:01 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 14:01:19 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+static void    close_redirection(void *v_redir)
+{
+       t_redirection   *redir;
+
+       redir = v_redir;
+       close(redir->from_to_fds[1]);
+       return ;
+}
+
+static 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);
+}
+
+static 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)
+               res = 1;
+       else if (!*fields)
+               res = assignments_to_env(&assignments, env);
+       else
+               res = ex_fields(fields, &assignments, &redirections, env);
+       free_split(fields);
+       ft_vec_free(&redirections, close_redirection);
+       ft_vec_free(&assignments, free_str);
+       return (res);
+}
+
+static 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));
+       }
+}
diff --git a/src/execute_raw.c b/src/execute_raw.c
new file mode 100644 (file)
index 0000000..6b01f1e
--- /dev/null
@@ -0,0 +1,93 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   execute_raw.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:16 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:29:27 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "builtins.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+static 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);
+}
+
+static int     contains_path(const char *str)
+{
+       return (ft_strchr(str, '/') != NULL);
+}
+
+static int     file_exists(const char *path)
+{
+       return (!access(path, F_OK));
+}
+
+static char    *get_path(const char *cmd, t_execution_env *env)
+{
+       char    *path;
+
+       path = NULL;
+       if (contains_path(cmd) && file_exists(cmd))
+               path = ft_strdup(cmd);
+       else if (!contains_path(cmd))
+               path = find_exe(cmd, env);
+       if (!path)
+               env->ret_val = 127;
+       return (path);
+}
+
+int    ex_fields(char **fields, t_vec *assignments,
+       const t_vec *redirections, t_execution_env *env)
+{
+       pid_t   pid;
+       char    *path;
+
+       env->last_was_builtin = is_builtin(fields[0]);
+       if (env->last_was_builtin)
+               return (ex_builtin(fields, assignments, redirections, env));
+       path = get_path(fields[0], env);
+       if (!path)
+               return (1);
+       pid = fork();
+       if (pid == 0)
+       {
+               if (prepare_env(env, redirections, assignments) == 0)
+                       execve(path, fields, assignments->vec);
+               exit(-1);
+       }
+       free(path);
+       if (pid < 0)
+               return (1);
+       if (ft_vec_append(&env->child_pids, &pid) != success)
+       {
+               kill(pid, SIGTERM);
+               return (1);
+       }
+       return (0);
+}
diff --git a/src/execution.c b/src/execution.c
deleted file mode 100644 (file)
index 8ee7e80..0000000
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* ************************************************************************** */
-/*                                                                            */
-/*                                                        :::      ::::::::   */
-/*   execution.c                                        :+:      :+:    :+:   */
-/*                                                    +:+ +:+         +:+     */
-/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
-/*                                                +#+#+#+#+#+   +#+           */
-/*   Created: 2024/07/21 08:57:54 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/09/01 10:19:33 by ljiriste         ###   ########.fr       */
-/*                                                                            */
-/* ************************************************************************** */
-
-#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, &copy) == 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);
-}
-
-static void    handle_fds(int *fd, int *sec_fd, const char *filename,
-               const t_parse_tree_node *operator)
-{
-       if (*fd < 0)
-       {
-               if (is_token_type(operator, "LESS"))
-                       *fd = STDIN_FILENO;
-               else
-                       *fd = STDOUT_FILENO;
-       }
-       if (is_token_type(operator, "LESS"))
-               *sec_fd = open(filename, O_RDONLY);
-       else 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);
-       return ;
-}
-
-int    add_redirection_file(t_vec *redirections,
-       t_parse_tree_node *io_file, int fd, 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);
-       handle_fds(&fd, &sec_fd, filename, operator);
-       if (sec_fd < 0)
-       {
-               free(filename);
-               env->ret_val = 1;
-               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);
-}
-
-static 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);
-}
-
-static char    *here_file_getline(void)
-{
-       ft_printf("> ");
-       return (get_next_line(STDIN_FILENO));
-}
-
-// In case of an error the pipe_fd is repurposed to indicate the error.
-// This is done to save a few lines
-int    here_file_to_pipe(int pipe_fd, char *delimiter,
-       const t_execution_env *env)
-{
-       int             expand;
-       char    *line;
-
-       expand = !unquote_field(delimiter);
-       line = here_file_getline();
-       while (line && ft_strncmp(line, delimiter, ft_strlen(line) - 1))
-       {
-               if (write_line_to_pipe(pipe_fd, line, env, expand))
-               {
-                       pipe_fd = -1;
-                       break ;
-               }
-               free(line);
-               line = here_file_getline();
-       }
-       if (!line)
-               ft_printf
-               ("minishell: warning: here-document delimited by EOF instead of %s\n",
-                       delimiter);
-       get_next_line(-1);
-       free(line);
-       return (pipe_fd == -1);
-}
-
-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, 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, 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, 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 char    *get_value(const char *word, size_t *i, const t_execution_env *env)
-{
-       char            *var;
-       char            *value;
-       const char      *const_val;
-
-       if (word[*i] == '?')
-       {
-               ++*i;
-               value = ft_itoa(env->ret_val);
-       }
-       else
-       {
-               var = get_var_name(word + *i);
-               if (!var)
-                       return (NULL);
-               *i += ft_strlen(var);
-               const_val = get_env_var_value(env, var);
-               free(var);
-               if (!const_val)
-                       return (ft_strdup(""));
-               value = ft_strdup(const_val);
-       }
-       return (value);
-}
-
-static int     append_value(t_vec *exp_str, const char *value, int enquote_result)
-{
-       int     error;
-
-       if (!value)
-               return (1);
-       if (enquote_result)
-       {
-               error = ft_vec_append(exp_str, "'") != success;
-               error = error
-                       || ft_vec_append_range(exp_str, value, ft_strlen(value)) != success;
-               error = error || ft_vec_append(exp_str, "'") != success;
-               return (error);
-       }
-       return (ft_vec_append_range(exp_str, value, ft_strlen(value)) != success);
-}
-
-// Returns 1 when quote is set (or unset)
-// and 0 when quote is left in current state
-int    set_quote(char *quote, char c)
-{
-       if (c == '"' || c == '\'')
-       {
-               if (*quote == '\0')
-                       *quote = c;
-               else if (*quote == c)
-                       *quote = '\0';
-               else
-                       return (0);
-               return (1);
-       }
-       return (0);
-}
-
-int    is_expandable(const char *str)
-{
-       return (str[0] == '$'
-               && (ft_isalpha(str[1])
-                       || str[1] == '_'
-                       || str[1] == '?'));
-}
-
-int    add_word(t_vec *exp_str, const char *word,
-       const t_execution_env *env, int enquote_result)
-{
-       size_t          i;
-       char            quote;
-       const char      space = ' ';
-       char            *value;
-
-       quote = '\0';
-       i = 0;
-       while (word[i])
-       {
-               set_quote(&quote, word[i]);
-               if (is_expandable(word + (i++)) && quote != '\'')
-               {
-                       value = get_value(word, &i, env);
-                       if (append_value(exp_str, value, enquote_result))
-                       {
-                               free(value);
-                               return (1);
-                       }
-                       free(value);
-               }
-               else
-                       if (ft_vec_append(exp_str, word + i - 1) != success)
-                               return (1);
-       }
-       return (ft_vec_append(exp_str, &space) != success);
-}
-
-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 ;
-               set_quote(&quote, str[n]);
-               ++n;
-       }
-       return (n);
-}
-
-// Returns 1 if any unquoting happened else returns 0
-int    unquote_field(char *field)
-{
-       int             res;
-       size_t  i;
-       char    quote;
-
-       res = 0;
-       quote = 0;
-       i = 0;
-       while (field && field[i])
-       {
-               if (field[i] == '"' || field[i] == '\'')
-               {
-                       if (!set_quote(&quote, field[i]))
-                       {
-                               ++i;
-                               continue ;
-                       }
-                       res = 1;
-                       ft_memmove(field + i, field + i + 1, ft_strlen(field + i + 1) + 1);
-               }
-               else
-                       ++i;
-       }
-       return (res);
-}
-
-void   unquote(char **fields)
-{
-       size_t  i;
-
-       i = 0;
-       while (fields[i])
-       {
-               unquote_field(fields[i]);
-               ++i;
-       }
-       return ;
-}
-
-int    process_word(const char *str, t_vec *fields, size_t *i)
-{
-       size_t  n;
-       char    *new_str;
-
-       while (str[*i] == ' ')
-               ++*i;
-       n = get_next_word_size(str + *i);
-       if (n == 0)
-               return (0);
-       new_str = ft_strndup(str + *i, n);
-       if (!new_str)
-               return (1);
-       if (ft_vec_append(fields, &new_str) != success)
-       {
-               free(new_str);
-               return (1);
-       }
-       *i += n;
-       return (0);
-}
-
-char   **quoted_split(const char *str)
-{
-       size_t          i;
-       t_vec           fields;
-       const void      *g_nullptr = NULL;
-
-       if (ft_vec_init(&fields, sizeof(char *)) != success)
-               return (NULL);
-       i = 0;
-       while (str[i])
-       {
-               if (process_word(str, &fields, &i))
-               {
-                       ft_vec_free(&fields, free);
-                       return (NULL);
-               }
-       }
-       if (ft_vec_append(&fields, &g_nullptr) != success)
-       {
-               ft_vec_free(&fields, free);
-               return (NULL);
-       }
-       return (fields.vec);
-}
-
-int    expand_child(t_parse_tree_node *subnode,
-               t_vec *expanded_str, const t_execution_env *env)
-{
-       if ((is_token_type(subnode, "cmd_name")
-                       || is_token_type(subnode, "cmd_word")
-                       || is_token_type(subnode, "cmd_suffix"))
-               && expand_cmd(expanded_str, subnode, env))
-               return (1);
-       return (0);
-}
-
-char   **expand(t_parse_tree_node *simple_command, const t_execution_env *env)
-{
-       const char      g_null_char = '\0';
-       size_t          i;
-       char            **fields;
-       t_vec           expanded_str;
-
-       ft_vec_init(&expanded_str, sizeof(char));
-       i = 0;
-       while (i < simple_command->children.size)
-       {
-               if (expand_child(ft_vec_access(&simple_command->children, i++),
-                               &expanded_str, env))
-               {
-                       ft_vec_free(&expanded_str, NULL);
-                       return (NULL);
-               }
-       }
-       if (ft_vec_append(&expanded_str, &g_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;
-
-       if (!fields)
-               return ;
-       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);
-       if (env->stdin_fd != STDIN_FILENO)
-               close(env->stdin_fd);
-       if (env->stdout_fd != STDOUT_FILENO)
-               close(env->stdout_fd);
-       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(t_vec *assignments, 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)
-                       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->builtin_ret_val = cd(count_fields(fields), fields, env);
-       else if (!ft_strcmp(fields[0], "echo"))
-               env->builtin_ret_val = echo(count_fields(fields), fields);
-       else if (!ft_strcmp(fields[0], "pwd"))
-               env->builtin_ret_val = pwd();
-       else if (!ft_strcmp(fields[0], "env"))
-               env->builtin_ret_val = ft_env(count_fields(fields), env);
-       else if (!ft_strcmp(fields[0], "export"))
-               env->builtin_ret_val = export(count_fields(fields), fields, env);
-       else if (!ft_strcmp(fields[0], "unset"))
-               env->builtin_ret_val = unset(count_fields(fields), fields, env);
-       else if (!ft_strcmp(fields[0], "exit"))
-               env->builtin_ret_val = execute_exit(count_fields(fields), fields, env);
-       else
-               return (1);
-       close_redirections(redirections);
-       close_pipes(env);
-       restore_std_filenos(fds);
-       return (0);
-}
-
-void   close_fds(t_vec *fds_to_close)
-{
-       int             fd;
-       size_t  i;
-
-       i = 0;
-       while (i < fds_to_close->size)
-       {
-               fd = *(int *)ft_vec_access(fds_to_close, i);
-               close(fd);
-               ++i;
-       }
-       return ;
-}
-
-char   *get_path(const char *cmd, t_execution_env *env)
-{
-       char    *path;
-
-       path = NULL;
-       if (contains_path(cmd) && file_exists(cmd))
-               path = ft_strdup(cmd);
-       else if (!contains_path(cmd))
-               path = find_exe(cmd, env);
-       if (!path)
-               env->ret_val = 127;
-       return (path);
-}
-
-int    prepare_env(t_execution_env *env,
-               const t_vec *redirections, t_vec *assignments)
-{
-       int     res;
-
-       close_fds(&env->fds_to_close);
-       res = dup_pipes(env);
-       res = dup_redirections(redirections) || res;
-       res = add_exported(assignments, env) || res;
-       return (res);
-}
-
-int    ex_fields(char **fields, t_vec *assignments,
-       const t_vec *redirections, t_execution_env *env)
-{
-       pid_t   pid;
-       char    *path;
-
-       env->last_was_builtin = is_builtin(fields[0]);
-       if (env->last_was_builtin)
-               return (ex_builtin(fields, assignments, redirections, env));
-       path = get_path(fields[0], env);
-       if (!path)
-               return (1);
-       pid = fork();
-       if (pid == 0)
-       {
-               if (prepare_env(env, redirections, assignments) == 0)
-                       execve(path, fields, assignments->vec);
-               exit(-1);
-       }
-       free(path);
-       if (pid < 0)
-               return (1);
-       if (ft_vec_append(&env->child_pids, &pid) != success)
-       {
-               kill(pid, SIGTERM);
-               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)
-               res = 1;
-       else if (!*fields)
-               res = assignments_to_env(&assignments, env);
-       else
-               res = ex_fields(fields, &assignments, &redirections, env);
-       free_split(fields);
-       ft_vec_free(&redirections, close_redirection);
-       ft_vec_free(&assignments, free_str);
-       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_all_to_end(t_vec *child_pids)
-{
-       size_t  i;
-       pid_t   pid;
-       int             sig_num;
-
-       sig_num = 0;
-       i = child_pids->size;
-       while (i > 0)
-       {
-               --i;
-               pid = *(pid_t *)ft_vec_access(child_pids, i);
-               if (g_last_signal == 0)
-                       waitpid(pid, NULL, 0);
-               if (g_last_signal)
-               {
-                       sig_num = g_last_signal;
-                       g_last_signal = 0;
-                       killall(child_pids, g_last_signal);
-                       i = child_pids->size;
-               }
-               ft_vec_forget(child_pids, i);
-       }
-       ft_vec_free(child_pids, NULL);
-       if (g_last_signal == 0)
-               g_last_signal = sig_num;
-       return ;
-}
-
-void   wait_for_return(t_execution_env *env)
-{
-       pid_t   last_pid;
-       int             status;
-
-       if (env->last_was_builtin)
-               env->ret_val = env->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)
-                       if (WIFEXITED(status))
-                               env->ret_val = WEXITSTATUS(status);
-       }
-       wait_for_all_to_end(&env->child_pids);
-       return ;
-}
-
-int    ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth);
-
-int    advance_pipeline(t_parse_tree_node *pipeline,
-               t_execution_env *env, int depth)
-{
-       int     pipe_fds[2];
-       int     res;
-
-       if (pipe(pipe_fds))
-               return (1);
-       res = ft_vec_append(&env->fds_to_close, &pipe_fds[0]);
-       res = res || ft_vec_append(&env->fds_to_close, &env->stdout_fd);
-       ft_swap_int(&pipe_fds[1], &env->stdout_fd);
-       res = res
-               || ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1);
-       ft_swap_int(&pipe_fds[1], &env->stdout_fd);
-       close(pipe_fds[1]);
-       if (res == 0)
-       {
-               ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
-               ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
-       }
-       ft_swap_int(&pipe_fds[0], &env->stdin_fd);
-       res = res || ex_command(ft_vec_access(&pipeline->children, 2), env);
-       ft_swap_int(&pipe_fds[0], &env->stdin_fd);
-       close(pipe_fds[0]);
-       return (res);
-}
-
-int    ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth)
-{
-       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 (advance_pipeline(pipeline, env, depth))
-               {
-                       killall(&env->child_pids, SIGTERM);
-                       return (1);
-               }
-       }
-       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);
-}
diff --git a/src/expand.c b/src/expand.c
new file mode 100644 (file)
index 0000000..a8c0674
--- /dev/null
@@ -0,0 +1,91 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   expand.c                                           :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:53:33 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:31:20 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+
+static void    unquote(char **fields)
+{
+       size_t  i;
+
+       i = 0;
+       while (fields[i])
+       {
+               unquote_field(fields[i]);
+               ++i;
+       }
+       return ;
+}
+
+static 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);
+}
+
+static int     expand_child(t_parse_tree_node *subnode,
+               t_vec *expanded_str, const t_execution_env *env)
+{
+       if ((is_token_type(subnode, "cmd_name")
+                       || is_token_type(subnode, "cmd_word")
+                       || is_token_type(subnode, "cmd_suffix"))
+               && expand_cmd(expanded_str, subnode, env))
+               return (1);
+       return (0);
+}
+
+char   **expand(t_parse_tree_node *simple_command, const t_execution_env *env)
+{
+       const char      g_null_char = '\0';
+       size_t          i;
+       char            **fields;
+       t_vec           expanded_str;
+
+       ft_vec_init(&expanded_str, sizeof(char));
+       i = 0;
+       while (i < simple_command->children.size)
+       {
+               if (expand_child(ft_vec_access(&simple_command->children, i++),
+                               &expanded_str, env))
+               {
+                       ft_vec_free(&expanded_str, NULL);
+                       return (NULL);
+               }
+       }
+       if (ft_vec_append(&expanded_str, &g_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);
+}
\ No newline at end of file
diff --git a/src/expand_split.c b/src/expand_split.c
new file mode 100644 (file)
index 0000000..e2a2fe6
--- /dev/null
@@ -0,0 +1,79 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   expand_split.c                                     :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:51:34 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:30:17 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "libft.h"
+#include <stdlib.h>
+
+static 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 ;
+               set_quote(&quote, str[n]);
+               ++n;
+       }
+       return (n);
+}
+
+static int     process_word(const char *str, t_vec *fields, size_t *i)
+{
+       size_t  n;
+       char    *new_str;
+
+       while (str[*i] == ' ')
+               ++*i;
+       n = get_next_word_size(str + *i);
+       if (n == 0)
+               return (0);
+       new_str = ft_strndup(str + *i, n);
+       if (!new_str)
+               return (1);
+       if (ft_vec_append(fields, &new_str) != success)
+       {
+               free(new_str);
+               return (1);
+       }
+       *i += n;
+       return (0);
+}
+
+char   **quoted_split(const char *str)
+{
+       size_t          i;
+       t_vec           fields;
+       const void      *g_nullptr = NULL;
+
+       if (ft_vec_init(&fields, sizeof(char *)) != success)
+               return (NULL);
+       i = 0;
+       while (str[i])
+       {
+               if (process_word(str, &fields, &i))
+               {
+                       ft_vec_free(&fields, free);
+                       return (NULL);
+               }
+       }
+       if (ft_vec_append(&fields, &g_nullptr) != success)
+       {
+               ft_vec_free(&fields, free);
+               return (NULL);
+       }
+       return (fields.vec);
+}
\ No newline at end of file
diff --git a/src/redir_file.c b/src/redir_file.c
new file mode 100644 (file)
index 0000000..b19e1c9
--- /dev/null
@@ -0,0 +1,83 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   redir_file.c                                       :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:23:57 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 14:02:22 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static void    handle_fds(int *fd, int *sec_fd, const char *filename,
+               const t_parse_tree_node *operator)
+{
+       if (*fd < 0)
+       {
+               if (is_token_type(operator, "LESS"))
+                       *fd = STDIN_FILENO;
+               else
+                       *fd = STDOUT_FILENO;
+       }
+       if (is_token_type(operator, "LESS"))
+               *sec_fd = open(filename, O_RDONLY);
+       else 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);
+       return ;
+}
+
+static 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, 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);
+       handle_fds(&fd, &sec_fd, filename, operator);
+       if (sec_fd < 0)
+       {
+               free(filename);
+               env->ret_val = 1;
+               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);
+}
+
diff --git a/src/redir_here.c b/src/redir_here.c
new file mode 100644 (file)
index 0000000..cdaacbb
--- /dev/null
@@ -0,0 +1,112 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   redir_here.c                                       :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:48:10 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 13:31:59 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+
+static char    *here_file_getline(void)
+{
+       ft_printf("> ");
+       return (get_next_line(STDIN_FILENO));
+}
+
+static 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);
+}
+
+// In case of an error the pipe_fd is repurposed to indicate the error.
+// This is done to save a few lines
+int    here_file_to_pipe(int pipe_fd, char *delimiter,
+       const t_execution_env *env)
+{
+       int             expand;
+       char    *line;
+
+       expand = !unquote_field(delimiter);
+       line = here_file_getline();
+       while (line && ft_strncmp(line, delimiter, ft_strlen(line) - 1))
+       {
+               if (write_line_to_pipe(pipe_fd, line, env, expand))
+               {
+                       pipe_fd = -1;
+                       break ;
+               }
+               free(line);
+               line = here_file_getline();
+       }
+       if (!line)
+               ft_printf
+               ("minishell: warning: here-document delimited by EOF instead of %s\n",
+                       delimiter);
+       get_next_line(-1);
+       free(line);
+       return (pipe_fd == -1);
+}
+
+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);
+}
\ No newline at end of file
diff --git a/src/redirection.c b/src/redirection.c
new file mode 100644 (file)
index 0000000..9f4bbce
--- /dev/null
@@ -0,0 +1,89 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   redirection.c                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/09/01 11:49:27 by lnikolov          #+#    #+#             */
+/*   Updated: 2024/09/01 14:02:49 by lnikolov         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "execution.h"
+#include "minishell_structs.h"
+#include "libft.h"
+
+
+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);
+}
+
+static int     add_redirection(t_vec *redirections,
+       t_parse_tree_node *redirect, 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));
+}
+
+static int     save_redirections_psfix(t_vec *redirections,
+       t_parse_tree_node *node, 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, 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);
+}