Refactor input_method.c to rl and noleaks versions
authorLukas Jiriste <ljiriste@student.42prague.com>
Sat, 31 Aug 2024 08:25:48 +0000 (10:25 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Sat, 31 Aug 2024 08:25:48 +0000 (10:25 +0200)
Makefile
inc/minishell.h
src/execution.c.orig [new file with mode: 0644]
src/main.c
src/noleaks_input.c [new file with mode: 0644]
src/readline_input.c [moved from src/input_method.c with 55% similarity]

index d9ab6f96bb1d95db66e558a480432e7ed5425040..fe257ef0a7607795770d4de0ebe06d0bc16fecfe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,6 @@ INCLUDE := $(addprefix -I, $(INCDIR))
 SRCDIR := src
 
 SOURCES :=     main.c                          \
-                       input_method.c          \
                        env.c                           \
                        vars.c                          \
                        input_handling.c        \
@@ -42,6 +41,12 @@ SOURCES :=   main.c                          \
                        builtins/unset.c        \
                        builtins/exit.c         \
 
+ifneq ("$(wildcard .noleaks)","")
+       SOURCES += noleaks_input.c
+else
+       SOURCES += readline_input.c
+endif
+
 SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES))
 
 OBJECTS := $(SOURCES:.c=.o)
@@ -50,8 +55,6 @@ NAME := minishell
 
 all : $(NAME)
 
-.PHONY : Libft/libft.a
-
 debug : .debug
        $(MAKE) -C Libft debug
        $(MAKE) all
@@ -62,16 +65,19 @@ nodebug :
        $(MAKE) shallow_re
 
 noleaks : .noleaks
+       $(RM) $(SRCDIR)/readline_input.o
        $(MAKE) all
 
 readline :
-       $(RM) .noleaks
+       $(RM) $(SRCDIR)/noleaks_input.o .noleaks
        $(MAKE) shallow_re
 
 .% :
        $(MAKE) shallow_fclean
        touch $@
 
+.PHONY : Libft/libft.a
+
 $(NAME) : $(OBJECTS) Libft/libft.a
        $(CC) $(CFLAGS) -o $@ $^ $(LINKS)
 
index e77f81b5983f75dd5493aecc45066421d5d1ca88..be6479a2f1b7ca4ea9bacb6308155da55d7c233d 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/02 13:22:57 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/29 16:17:10 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/31 10:04:30 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 
 extern volatile sig_atomic_t   g_last_signal;
 
-void   minishell_flush(void);
+void   handler(int sig_num);
+
 char   *get_line(void);
 void   terminate_input(void);
+void   set_input_handler(void);
 
 void   handle_input(char **line, t_execution_env *env);
 
diff --git a/src/execution.c.orig b/src/execution.c.orig
new file mode 100644 (file)
index 0000000..e762104
--- /dev/null
@@ -0,0 +1,1078 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   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, &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);
+}
+
+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);
+}
index 3e2f92b759551396c9fbe5c7badc82afb9e58029..9902951933d158552cb90d41d004e7328eaeff3d 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/04/26 13:11:47 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/31 09:08:57 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/31 09:55:10 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include <termios.h>
 #include <unistd.h>
 
-#ifndef NOLEAKS
-# include <stdio.h>                            // readline
-# include <readline/readline.h>        // readline
-# include <readline/history.h> // readline
-#endif // NOLEAKS
-
 volatile sig_atomic_t  g_last_signal;
 
 void   handler(int     sig_num)
@@ -33,48 +27,6 @@ void handler(int     sig_num)
        return ;
 }
 
-#ifndef NOLEAKS
-void   rl_handler(int sig_num)
-{
-       if (sig_num != SIGINT)
-               return ;
-       write(1, "\n", 1);
-       rl_on_new_line();
-       rl_replace_line("", 0);
-       rl_redisplay();
-       return ;
-}
-
-void   set_input_handler(void)
-{
-       struct sigaction        sa;
-
-       ft_memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = SIG_IGN;
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = 0;
-       sigaction(SIGQUIT, &sa, NULL);
-       sa.sa_handler = rl_handler;
-       sigaction(SIGINT, &sa, NULL);
-       return ;
-}
-#else
-void   set_input_handler(void)
-{
-       struct sigaction        sa;
-
-       ft_memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = SIG_IGN;
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = 0;
-       sigaction(SIGQUIT, &sa, NULL);
-       sa.sa_handler = handler;
-       sigaction(SIGINT, &sa, NULL);
-       return ;
-}
-
-#endif // NOLEAKS
-
 void   set_execution_handler(void)
 {
        struct sigaction        sa;
@@ -131,17 +83,6 @@ void        regenerate_terminal(void)
        return ;
 }
 
-#ifdef NOLEAKS
-void   minishell_flush(void)
-{
-       struct termios  termios;
-
-       tcgetattr(STDIN_FILENO, &termios);
-       tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
-       return ;
-}
-#endif // NOLEAKS
-
 /*
 // This would be more portable than the main with 3 input args
 extern char    **environ;
diff --git a/src/noleaks_input.c b/src/noleaks_input.c
new file mode 100644 (file)
index 0000000..d534f36
--- /dev/null
@@ -0,0 +1,74 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   noleaks_input.c                                    :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/08/31 09:48:30 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/08/31 10:03:56 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+
+static void    minishell_flush(void)
+{
+       struct termios  termios;
+
+       tcgetattr(STDIN_FILENO, &termios);
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
+       return ;
+}
+
+char   *get_line(void)
+{
+       char    *cwd;
+       char    *prompt;
+       char    *line;
+
+       cwd = getcwd(NULL, 0);
+       prompt = ft_strjoin(cwd, "$ ");
+       free(cwd);
+       ft_printf("%s", prompt);
+       free(prompt);
+       line = get_next_line(STDIN_FILENO);
+       if (!line)
+       {
+               ft_printf("\n");
+               if (g_last_signal == SIGINT)
+               {
+                       g_last_signal = 0;
+                       minishell_flush();
+                       return (get_line());
+               }
+               return (line);
+       }
+       if (line[ft_strlen(line) - 1] != '\n')
+               ft_printf("\n");
+       return (line);
+}
+
+void   terminate_input(void)
+{
+       get_next_line(-1);
+       return ;
+}
+
+void   set_input_handler(void)
+{
+       struct sigaction        sa;
+
+       ft_memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIG_IGN;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = 0;
+       sigaction(SIGQUIT, &sa, NULL);
+       sa.sa_handler = handler;
+       sigaction(SIGINT, &sa, NULL);
+       return ;
+}
similarity index 55%
rename from src/input_method.c
rename to src/readline_input.c
index ddb7681400a8acce8f81a8af7b1e4c4fa9d9c88d..d7125839cd41b12475951966f6b4983223240d8e 100644 (file)
@@ -1,27 +1,34 @@
 /* ************************************************************************** */
 /*                                                                            */
 /*                                                        :::      ::::::::   */
-/*   input_method.c                                     :+:      :+:    :+:   */
+/*   readline_input.c                                   :+:      :+:    :+:   */
 /*                                                    +:+ +:+         +:+     */
-/*   By: ljiriste <ljiriste@student.42prague.com>   +#+  +:+       +#+        */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
-/*   Created: 2024/08/27 14:22:08 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/29 17:11:41 by ljiriste         ###   ########.fr       */
+/*   Created: 2024/08/31 09:46:31 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/08/31 10:01:38 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
-#include "minishell.h"
-#include <stdlib.h>
-#include <unistd.h>                            // getcwd
 #include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
 
-#ifndef NOLEAKS
-# include <stdio.h>                            // readline
-# include <readline/readline.h>        // readline
-# include <readline/history.h> // readline
-#endif // NOLEAKS
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
 
-#ifndef NOLEAKS
+static void    rl_handler(int sig_num)
+{
+       if (sig_num != SIGINT)
+               return ;
+       write(1, "\n", 1);
+       rl_on_new_line();
+       rl_replace_line("", 0);
+       rl_redisplay();
+       return ;
+}
 
 // A string "is_almost_empty" if it:
 //             is a NULL pointer
@@ -56,46 +63,22 @@ char        *get_line(void)
        return (line);
 }
 
-void   terminate_input(void)
-{
-       rl_clear_history();
-       return ;
-}
-
-#else // NOLEAKS
-
-char   *get_line(void)
+void   set_input_handler(void)
 {
-       char    *cwd;
-       char    *prompt;
-       char    *line;
+       struct sigaction        sa;
 
-       cwd = getcwd(NULL, 0);
-       prompt = ft_strjoin(cwd, "$ ");
-       free(cwd);
-       ft_printf("%s", prompt);
-       free(prompt);
-       line = get_next_line(STDIN_FILENO);
-       if (!line)
-       {
-               ft_printf("\n");
-               if (g_last_signal == SIGINT)
-               {
-                       g_last_signal = 0;
-                       minishell_flush();
-                       return (get_line());
-               }
-               return (line);
-       }
-       if (line[ft_strlen(line) - 1] != '\n')
-               ft_printf("\n");
-       return (line);
+       ft_memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIG_IGN;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = 0;
+       sigaction(SIGQUIT, &sa, NULL);
+       sa.sa_handler = rl_handler;
+       sigaction(SIGINT, &sa, NULL);
+       return ;
 }
 
 void   terminate_input(void)
 {
-       get_next_line(-1);
+       rl_clear_history();
        return ;
 }
-
-#endif // NOLEAKS