Add the save_redirections function
authorLukas Jiriste <ljiriste@student.42prague.com>
Sun, 21 Jul 2024 15:44:24 +0000 (17:44 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Sun, 21 Jul 2024 15:44:54 +0000 (17:44 +0200)
This function traverses the command prefix and suffix, opens all the
files needed for redirection and saves the information to a t_vec.

inc/minishell.h
src/execution.c

index a5446b54fe804dd8cbd5acbaf964d731aed04d59..0835940d9a5b12fb0dd922738aebac972bc0c351 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/02 13:22:57 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/07/21 13:00:33 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/07/21 17:19:11 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -23,8 +23,8 @@ typedef struct s_vars
 
 typedef struct s_redirection
 {
-       int     from_fd;
-       int     to_fd;
+       int             from_to_fds[2];
+       size_t  created;
 }              t_redirection;
 
 typedef struct s_execution_env
@@ -32,7 +32,7 @@ typedef struct s_execution_env
        int             stdin_fd;
        int             stdout_fd;
        int             ret_val;
-       t_vars  *env_vars;
+       t_vars  *vars;
        t_vec   redirections;
 }                      t_execution_env;
 
index eb14d4bb167b4eee2b95ac8ecffc17f41b7604d2..004da7d114768e65d3b938706c52fcb232d1f308 100644 (file)
@@ -6,11 +6,16 @@
 /*   By: ljiriste <ljiriste@student.42prague.com>   +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/07/21 08:57:54 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/07/21 14:24:33 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/07/21 17:41:29 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 int    cmp_var_name(const char *a, const char *b)
 {
@@ -22,7 +27,7 @@ int   cmp_var_name(const char *a, const char *b)
        eq_ptr = ft_strchr(b, '=');
        if (namelen != eq_ptr - b)
                return (1);
-       return (ft_strcmp(a, b, namelen));
+       return (ft_strncmp(a, b, namelen));
 }
 
 void   clear_old(t_vec *assignments, const char *new)
@@ -44,23 +49,20 @@ void        clear_old(t_vec *assignments, const char *new)
 
 int    add_assignment(t_vec *assignments, const char *assignment)
 {
-       size_t  i;
        char    *copy;
 
-       copy = ft_strdup(subnode->token.str);
+       copy = ft_strdup(assignment);
        if (!copy)
                return (1);
        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)
 {
        size_t                          i;
-       char                            *assignment;
        t_parse_tree_node       *subnode;
 
        i = 0;
@@ -91,6 +93,273 @@ int save_assignments(t_vec *assignments, t_parse_tree_node *simple_command)
        return (0);
 }
 
+char   *get_word(const t_parse_tree_node *parent)
+{
+       char                                    *res;
+       const t_parse_tree_node *word = ft_vec_caccess(&parent->children, 2);
+
+       res = ft_strdup(word->token.str);
+       return (res);
+}
+
+int    add_redirection_file(t_vec *redirections, t_parse_tree_node *io_file, int fd)
+{
+       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);
+       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)
+                       return (1);
+               redir = (t_redirection){.from_to_fds[0] = sec_fd, .from_to_fds[1] = fd, .created = 0};
+       }
+       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)
+                       return (1);
+               redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd, .created = 1};
+       }
+       return (ft_vec_append(redirections, &redir) != success);
+}
+
+char   *get_var_name(const char *line)
+{
+       size_t  i;
+
+       i = 0;
+       while (line[i] && !ft_isspace(line[i]))
+               ++i;
+       return (ft_strndup(line, i));
+}
+
+char   *get_var_value(const t_vec *vars, const char *var_name)
+{
+       size_t          len;
+       size_t          i;
+       const char      *const *line;
+
+       len = ft_strlen(var_name);
+       i = 0;
+       while (i < vars->size)
+       {
+               line = ft_vec_caccess(vars, i);
+               if (ft_strncmp(*line, var_name, len) && (*line)[len + 1] == '=')
+                       return (ft_strdup(*line + len + 2));
+               ++i;
+       }
+       return (ft_strdup(""));
+}
+
+char   *get_env_var_value(const t_execution_env *env, const char *var_name)
+{
+       char    *res;
+
+       res = get_var_value(&env->vars->other, var_name);
+       if (!res || res[0])
+               return (res);
+       res = get_var_value(&env->vars->exported, var_name);
+       return (res);
+}
+
+int    write_line_to_pipe(int pipe_fd, const char *line, const t_execution_env *env, int expand)
+{
+       size_t  i;
+       char    *var;
+       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)
+               {
+                       free(var);
+                       return (1);
+               }
+               ft_dprintf(pipe_fd, "%s", value);
+               i += ft_strlen(var);
+               free(var);
+               free(value);
+       }
+       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_strcmp(line, unquoted_delimiter))
+       {
+               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] = pipe_fds[0], .from_to_fds[1] = fd, .created = 1};
+       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));
+       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);
+}
+
 int    ex_simple_command(t_parse_tree_node *simple_command, t_execution_env *env)
 {
        t_vec   redirections;
@@ -98,7 +367,7 @@ int  ex_simple_command(t_parse_tree_node *simple_command, t_execution_env *env)
        char    **fields;
        int             res;
 
-       res = save_redirections(&redirections, simple_command);
+       res = save_redirections(&redirections, simple_command, env);
        res = res || save_assignments(&assignments, simple_command);
        if (!res)
                fields = expand(simple_command, env, &redirections, &assignments);