Fix pipeline behaviour
authorLukáš Jiřiště <jiriste@icpf.cas.cz>
Tue, 27 Aug 2024 09:37:57 +0000 (11:37 +0200)
committerLukáš Jiřiště <jiriste@icpf.cas.cz>
Tue, 27 Aug 2024 09:37:57 +0000 (11:37 +0200)
The return value is now set only after pipeline finishes (to the return
value of last command).
The shell also does not wait for each commmand in pipeline to end before
starting the following command (preventing getting stuck on full pipe).
Built-in functions still can get stuck when pipe gets full.

inc/minishell_structs.h
src/env.c
src/execution.c
src/main.c

index eb44ef1ec26dac443055cd66e1e8cb946cceb3eb..3cfc08898571cb1cd2a74116930969970b307b62 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <ljiriste@student.42prague.com>   +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/08/26 09:08:46 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/26 09:31:09 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/27 11:35:10 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -31,7 +31,10 @@ typedef struct s_execution_env
        int             stdin_fd;
        int             stdout_fd;
        int             ret_val;
+       int             last_was_builtin;
+       int             last_builtin_ret_val;
        t_vars  *vars;
+       t_vec   child_pids;
 }                      t_execution_env;
 
 typedef struct s_wildcard_info
index ad5dca6a68c644cac93797ee400db7dab67268ac..936d7ba31d3e2defb7f5d2d1a3ccba98c0222d83 100644 (file)
--- a/src/env.c
+++ b/src/env.c
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/07/21 21:24:52 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/26 09:19:22 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/27 10:34:14 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 
 int    init_env(t_execution_env *env, char **envp)
 {
+       int     res;
+
        env->stdin_fd = STDIN_FILENO;
        env->stdout_fd = STDOUT_FILENO;
        env->ret_val = 0;
        env->vars = malloc(sizeof(t_vars));
        if (!env->vars)
                return (1);
-       return (init_vars(env->vars, envp));
+       res = init_vars(env->vars, envp);
+       res = (ft_vec_init(&env->child_pids, sizeof(pid_t)) != success) || res;
+       if (res)
+               clean_env(env);
+       return (res);
 }
 
 void   clean_env(t_execution_env *env)
 {
        clean_vars(env->vars);
        free(env->vars);
+       ft_vec_free(&env->child_pids, NULL);
        return ;
 }
index 775cf77a7c9258a4c4b5a0fa6e8e54b9a0ab2b8f..94df96df3d4984ec210b861fff05f9ce7617a226 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: lnikolov <lnikolov@student.42prague.com    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/07/21 08:57:54 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/27 10:06:59 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/27 11:37:08 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -784,19 +784,20 @@ int       ex_builtin(char **fields, __attribute__((unused)) t_vec *assignments, __attr
        dup_pipes(env);
        dup_redirections(redirections);
        if (!ft_strcmp(fields[0], "cd"))
-               env->ret_val = cd(count_fields(fields), fields, env);
+               env->last_builtin_ret_val = cd(count_fields(fields), fields, env);
        else if (!ft_strcmp(fields[0], "echo"))
-               env->ret_val = echo(count_fields(fields), fields);
+               env->last_builtin_ret_val = echo(count_fields(fields), fields);
        else if (!ft_strcmp(fields[0], "pwd"))
-               env->ret_val = pwd();
+               env->last_builtin_ret_val = pwd();
        else if (!ft_strcmp(fields[0], "env"))
-               env->ret_val = ft_env(count_fields(fields), env);
+               env->last_builtin_ret_val = ft_env(count_fields(fields), env);
        else if (!ft_strcmp(fields[0], "export"))
-               env->ret_val = export(count_fields(fields), fields, env);
+               env->last_builtin_ret_val = export(count_fields(fields), fields, env);
        else if (!ft_strcmp(fields[0], "unset"))
-               env->ret_val = unset(count_fields(fields), fields, env);
+               env->last_builtin_ret_val = unset(count_fields(fields), fields, env);
        else
                return (1);
+       env->last_was_builtin = 1;
        close_redirections(redirections);
        close_pipes(env);
        restore_std_filenos(fds);
@@ -806,11 +807,11 @@ int       ex_builtin(char **fields, __attribute__((unused)) t_vec *assignments, __attr
 int    ex_fields(char **fields, t_vec *assignments, const t_vec *redirections, t_execution_env *env)
 {
        pid_t   pid;
-       int             status;
        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]);
@@ -828,18 +829,14 @@ int       ex_fields(char **fields, t_vec *assignments, const t_vec *redirections, t_ex
                execve(path, fields, assignments->vec);
                exit(-1);
        }
-       else if (pid > 0)
+       free(path);
+       if (pid > 0)
        {
-               free(path);
-               waitpid(pid, &status, 0);
-               if (WIFEXITED(status))
-                       env->ret_val = WEXITSTATUS(status);
+               if (ft_vec_append(&env->child_pids, &pid) != success)
+                       return (1);
        }
        else
-       {
-               free(path);
                return (1);
-       }
        return (0);
 }
 
@@ -962,18 +959,41 @@ int       ex_command(t_parse_tree_node *command, t_execution_env *env)
        }
 }
 
-int    ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env)
+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 (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 (pipeline->children.size == 1)
-               return (ex_command(ft_vec_access(&pipeline->children, 0), env));
+       {
+               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);
+               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);
@@ -981,24 +1001,26 @@ int      ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *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));
+               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));
+                       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));
+                       return (ex_pipeline(ft_vec_access(&program->children, 2), env, 0));
        }
        return (0);
 }
index 75762e774a3728438221af2544cfa8a206cd6d52..708d3196f56972358955901bc435014baf39ba05 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/04/26 13:11:47 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/26 09:41:50 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/27 10:20:29 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -81,10 +81,7 @@ int  main(int argc, __attribute__((unused)) char **argv, char **envp)
                return (1);
        }
        if (init_env(&env, envp))
-       {
-               clean_env(&env);
                return (2);
-       }
        while (1)
        {
                line = rl_get_line();