From 140549db00e99351012b8a10f3285c016a768c59 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Tue, 16 Nov 2021 08:49:57 +0100 Subject: [PATCH] WIP exec_cmd_line() + fix error handle in redirections() + rename ft_free_cmd_arr() to free_pipeline() + "char **path" added to "struct t_all" + misc --- Makefile | 1 + headers/minishell_prototypes.h | 12 +- headers/minishell_structs.h | 16 +-- srcs/builtins/exit.c | 2 +- srcs/exec_cmd_line.c | 138 +++++++++++++++++++++ srcs/free.c | 42 +++++-- srcs/init.c | 26 +++- srcs/parsing/expansions/words_expansions.c | 4 +- srcs/parsing/parsing.c | 6 +- srcs/parsing/redirections/redirections.c | 35 ++++-- srcs/shell_loop.c | 8 +- 11 files changed, 239 insertions(+), 51 deletions(-) create mode 100644 srcs/exec_cmd_line.c diff --git a/Makefile b/Makefile index 56750a8..9d3fe83 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ SRCS = main.c init.c free.c generic.c \ words_expansions.c expand_token.c rejoin_after_expand.c new_token_for_each_field.c \ ft_split_quotes.c ft_strdup_quotes.c \ redirections.c here_doc.c \ + exec_cmd_line.c \ env.c exit.c echo.c DIR_OBJS = builds diff --git a/headers/minishell_prototypes.h b/headers/minishell_prototypes.h index 667b29e..6e5aed9 100644 --- a/headers/minishell_prototypes.h +++ b/headers/minishell_prototypes.h @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */ -/* Updated: 2021/11/14 12:23:38 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 08:04:08 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,6 +15,7 @@ // Init int init(t_all *c, char *envp[]); +char **retrieve_path(char *envp[]); int set_signals_handling(struct sigaction *ori_signal_behaviour, struct sigaction *signal_behaviour); int set_terminal_attributes(struct termios *ori_termios, @@ -40,6 +41,9 @@ int words_expansions(t_token *token_list); int token_expansions(t_token **t); int redirections(t_token *token_list, t_cmd **cmd_arr); +// Exec +int exec_cmd_line(t_all *c); + // Builtins int builtin_env(int argc, char *argv[], t_all *c); int builtin_exit(int argc, char *argv[], t_all *c); @@ -47,7 +51,9 @@ int builtin_echo(int argc, char *argv[], t_all *c); // Free int free_exit(t_all *c, int exit_status); -void ft_free_cmd_arr(t_cmd **cmd_arr); +void free_pipeline(t_cmd **pipeline_ptr[]); +void close_pipeline_fd(t_cmd *pipeline[]); +typedef void (*t_free_f)(void *); // generic // Generic char *ft_strjoinfree(char *s1, char *s2); @@ -61,7 +67,7 @@ void *ft_resize_2d_arr(void *ptr, size_t add_nbr); void print_matrix(char **matrix, char *sep); t_list *ft_lstbeforelast(t_list *lst); t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size); -typedef void *(*t_dup_func)(void *); +typedef void *(*t_dup_f)(void *); void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *)); void ft_perror_io(char *err_str, char *io_file); int ft_reti_perror_io(int ret, char *err_str, char *io_file); diff --git a/headers/minishell_structs.h b/headers/minishell_structs.h index 742272b..1fca47b 100644 --- a/headers/minishell_structs.h +++ b/headers/minishell_structs.h @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */ -/* Updated: 2021/11/11 07:21:47 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 08:45:10 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,21 +36,23 @@ typedef struct s_token enum e_token_id id; } t_token; -typedef int (*t_builtin_ptr)(int,char **,struct s_all *); +typedef int (*t_builtin_f)(int,char **,struct s_all *); typedef struct s_cmd { - char **argv; - pid_t pid; - t_builtin_ptr *builtin_command; - int fd_in; - int fd_out; + char **argv; + char *path; + t_builtin_f builtin_func; + int fd_in; + int fd_out; + pid_t pid; } t_cmd; typedef struct s_all { t_cmd **cmd_arr; char **envp; + char **path; char *prompt_base; char *prompt; t_token *token_list; diff --git a/srcs/builtins/exit.c b/srcs/builtins/exit.c index 71e09f7..e6f6ca5 100644 --- a/srcs/builtins/exit.c +++ b/srcs/builtins/exit.c @@ -36,7 +36,7 @@ int builtin_exit(int argc, char *argv[], t_all *c) // WIP return (ft_reti_print(2, " numeric argument required\n", 2)); } } - status = ft_atoi(argv[1]); + status = ft_atoi(argv[1]); } return (free_exit(c, status)); } diff --git a/srcs/exec_cmd_line.c b/srcs/exec_cmd_line.c new file mode 100644 index 0000000..b690dd5 --- /dev/null +++ b/srcs/exec_cmd_line.c @@ -0,0 +1,138 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_cmd_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/16 08:42:01 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01 +// Bien penser à mettre les ptr à NULL aprés free en cas d'erreur (pour ne pas double free si appel à free_exit()) + +int pipeline(t_all *c); +int open_pipes(t_cmd *pipeline[]); +int pipeline_access_cmd(t_cmd *pipeline[], char *path[]); +void pipeline_exec(t_cmd *pipeline[], t_all *c); +int cmd_exec_in_subshell(t_cmd *cmd, t_all *c); +int simple_cmd_builtin(t_cmd *cmd, t_all *c); + +int exec_cmd_line(t_all *c) +{ + if (!pipeline(c)) + { + free_pipeline(&c->cmd_arr); + return (0); + } + return (1); +} + +int pipeline(t_all *c) +{ + if (!open_pipes(c->cmd_arr)) + return (0); + if (!pipeline_access_cmd(c->cmd_arr, c->path)) + return (0); + if (ft_2d_arrlen(pipeline) == 1 && c->cmd_arr[0]->builtin_func) + { + simple_cmd_builtin(c->cmd_arr[0], c); + free_pipeline(&c->cmd_arr); + } + else + { + pipeline_exec(c->cmd_arr, c); + free_pipeline(&c->cmd_arr); + // TODO wait process here + } + return (1); +} + +int open_pipes(t_cmd *pipeline[]) +{ + int i; + int pipes[2]; + + i = 0; + while (pipeline[i] && pipeline[i + 1]) + { + if (pipe(pipes) == -1) + return (ft_reti_perror(0, "pipe()")); + if (pipeline[i]->fd_out == STDOUT_FILENO) + pipeline[i]->fd_out = pipes[STDOUT_FILENO]; + else + if (close(pipes[STDOUT_FILENO]) == -1) + perror("close()"); + if (pipeline[i]->fd_in == STDIN_FILENO) + pipeline[i + 1]->fd_in = pipes[STDIN_FILENO]; + else + if (close(pipes[STDIN_FILENO]) == -1) + perror("close()"); + i++; + } + return (1); +} + +int pipeline_access_cmd(t_cmd *pipeline[], char *path[]) +{ + // TODO + // Penser à : path = strdup(argv[0]); + // et non : path = argv[0]; + // pour ne pas double free + + return (1); +} + +int simple_cmd_builtin(t_cmd *cmd, t_all *c) +{ + // TODO + return (1); +} + +// TODO : Change exit status as in documentation : +// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 +void pipeline_exec(t_cmd *pipeline[], t_all *c) +{ + int i; + int ret; + + i = 0; + while (pipeline[i]) + { + if (pipeline[i]->pid == 0) // Pid var as error mark, WIP + { + ret = cmd_exec_in_subshell(pipeline[i], c); + if (ret != EXIT_SUCCESS) + free_exit(c, ret); + } + i++; + } +} + +int cmd_exec_in_subshell(t_cmd *cmd, t_all *c) +{ + cmd->pid = fork(); + if (cmd->pid == -1) + perror("fork()"); + if (cmd->pid == 0) + { + if (cmd->fd_in != STDIN_FILENO) + if (dup2(cmd->fd_in, STDIN_FILENO) == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup2()")); + if (cmd->fd_out != STDOUT_FILENO) + if (dup2(cmd->fd_out, STDOUT_FILENO) == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup2()")); + close_pipeline_fd(c->cmd_arr); + if (cmd->builtin_func) + free_exit(c, cmd->builtin_func(ft_2d_arrlen(cmd->argv), cmd->argv,c)); + else if (execve("/bin/echo", cmd->argv, c->envp) == -1) // WIP, TEST + return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0])); + //else if (execve(cmd->path, cmd->argv, c->envp) == -1) + // return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0])); + } + return (EXIT_SUCCESS); +} diff --git a/srcs/free.c b/srcs/free.c index 2e299fd..4dfd055 100644 --- a/srcs/free.c +++ b/srcs/free.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */ -/* Updated: 2021/11/14 08:26:32 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 08:03:30 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,7 +18,7 @@ int free_exit(t_all *c, int exit_status) free(c->prompt); ft_lstclear((t_list **)&c->token_list, free); // a voir avec Hugo, il y a un truc qui me semble superflu dans la fonction ft_free_2d_arr(c->envp); - ft_free_cmd_arr(c->cmd_arr); + free_pipeline(&c->cmd_arr); if (c->termios_changed) tcsetattr(STDIN_FILENO, TCSANOW, &c->ori_termios); gnl(STDIN_FILENO, NULL, 1); @@ -26,23 +26,41 @@ int free_exit(t_all *c, int exit_status) exit(exit_status); } -void ft_free_cmd_arr(t_cmd **cmd_arr) +void free_pipeline(t_cmd **pipeline_ptr[]) { - int i; + int i; + t_cmd **pipeline; - if (!cmd_arr) + pipeline = *pipeline_ptr; + if (!pipeline) + return ; + close_pipeline_fd(pipeline); + i = 0; + while (pipeline[i]) + { + ft_free_2d_arr(pipeline[i]->argv); + free(pipeline[i]->path); + i++; + } + ft_free_2d_arr(pipeline); + *pipeline_ptr = NULL; +} + +void close_pipeline_fd(t_cmd *pipeline[]) +{ + int i; + + if (!pipeline) return ; i = 0; - while (cmd_arr[i]) + while (pipeline[i]) { - ft_free_2d_arr(cmd_arr[i]->argv); - if (cmd_arr[i]->fd_in != STDIN_FILENO && cmd_arr[i]->fd_in > 0) - if (close(cmd_arr[i]->fd_in) == -1) + if (pipeline[i]->fd_in != STDIN_FILENO && pipeline[i]->fd_in > 0) + if (close(pipeline[i]->fd_in) == -1) perror("close()"); - if (cmd_arr[i]->fd_out != STDOUT_FILENO && cmd_arr[i]->fd_out > 0) - if (close(cmd_arr[i]->fd_out) == -1) + if (pipeline[i]->fd_out != STDOUT_FILENO && pipeline[i]->fd_out > 0) + if (close(pipeline[i]->fd_out) == -1) perror("close()"); i++; } - ft_free_2d_arr(cmd_arr); } diff --git a/srcs/init.c b/srcs/init.c index 5052a64..75b2484 100644 --- a/srcs/init.c +++ b/srcs/init.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ -/* Updated: 2021/11/13 05:31:47 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 03:45:10 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,10 +19,11 @@ int init(t_all *c, char *envp[]) { g_all = c; ft_bzero(c, sizeof (*c)); - c->envp = ft_dup_2d_arr(envp, (t_dup_func)ft_strdup); // TEST WIP + c->envp = ft_dup_2d_arr(envp, (t_dup_f)ft_strdup); // TEST WIP if (!c->envp) return (ft_reti_perror(0, "ft_dup_2d_char_arr(envp) error")); //print_matrix(c->envp, "\n --- \n"); // TEST WIP + c->path = retrieve_path(c->envp); // No return check. Its intended. PATH is optional c->prompt_base = init_prompt_base(); if (!c->prompt_base) return (ft_reti_perror(0, "init_prompt_base() error")); @@ -39,7 +40,24 @@ int init(t_all *c, char *envp[]) return (1); } -static char *init_prompt_base(void) +// TODO : Un appel à builtin_export() modifiant $PATH doit aussi entrainer un appel à "c->path = retrieve_path()" +char **retrieve_path(char *envp[]) +{ + char *path; + char **path_split; + + (void)envp; + //path = search_env_var(envp, "PATH"); // A reprendre du projet pipex si besoin de remplacer getenv() + path = getenv("PATH"); + if (!path) + return (ft_retp_print(NULL, "minishell: Warning, $PATH not set\n", 2)); + path_split = ft_split(path, ':'); + if (!path_split) + return (ft_retp_perror(NULL, "retrieve_path()")); + return (path_split); +} + +static char *init_prompt_base(void) // WIP, error return TODO { char *prompt_base; char *tmp; @@ -59,7 +77,7 @@ static char *init_prompt_base(void) return (prompt_base); } -static char *init_prompt(char *prompt_base) +static char *init_prompt(char *prompt_base) // WIP, error return TODO { char *prompt; diff --git a/srcs/parsing/expansions/words_expansions.c b/srcs/parsing/expansions/words_expansions.c index 400e286..a802bee 100644 --- a/srcs/parsing/expansions/words_expansions.c +++ b/srcs/parsing/expansions/words_expansions.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ -/* Updated: 2021/11/14 10:13:38 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 03:45:15 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -63,7 +63,7 @@ int token_expansions(t_token **t) if (!tmp_split) return (0); // 4 - tmp = ft_dup_2d_arr(tmp_split, (t_dup_func)ft_strdup_quotes); + tmp = ft_dup_2d_arr(tmp_split, (t_dup_f)ft_strdup_quotes); ft_free_2d_arr(tmp_split); tmp_split = tmp; if (!tmp_split) diff --git a/srcs/parsing/parsing.c b/srcs/parsing/parsing.c index d97c3ce..4025472 100644 --- a/srcs/parsing/parsing.c +++ b/srcs/parsing/parsing.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */ -/* Updated: 2021/11/14 12:53:40 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 08:02:56 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -79,11 +79,11 @@ t_cmd **parsing(t_token *token_list) // 2.9.1 - 3) Redirection if (!redirections(token_list, cmd_arr)) - return (ft_retp_free(NULL, cmd_arr, (void(*)(void *))ft_free_cmd_arr)); + return (ft_retp_free(NULL, &cmd_arr, (t_free_f)free_pipeline)); // Struct CMD fill if (!cmd_array_fill_argv(token_list, cmd_arr)) - return (ft_retp_free(NULL, cmd_arr, (void(*)(void *))ft_free_cmd_arr)); + return (ft_retp_free(NULL, &cmd_arr, (t_free_f)free_pipeline)); print_cmd_array(cmd_arr); // HUGO WIP diff --git a/srcs/parsing/redirections/redirections.c b/srcs/parsing/redirections/redirections.c index 0870bcd..0363e0b 100644 --- a/srcs/parsing/redirections/redirections.c +++ b/srcs/parsing/redirections/redirections.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */ -/* Updated: 2021/11/14 10:04:21 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 08:08:18 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,15 +24,18 @@ int redirections(t_token *t, t_cmd **cmd_arr) i = 0; while (t) { - if (t->id == '<' || t->id == T_DLESS) + if (cmd_arr[i]->pid == 0) // Pid var as error mark, WIP { - if (!redirect_cmd_input(t, cmd_arr[i])) - return (0); - } - else if (t->id == '>' || t->id == T_DGREAT) - { - if (!redirect_cmd_output(t, cmd_arr[i])) - return (0); + if (t->id == '<' || t->id == T_DLESS) + { + if (!redirect_cmd_input(t, cmd_arr[i])) + return (0); + } + else if (t->id == '>' || t->id == T_DGREAT) + { + if (!redirect_cmd_output(t, cmd_arr[i])) + return (0); + } } else if (t->id == '|') i++; @@ -43,7 +46,7 @@ int redirections(t_token *t, t_cmd **cmd_arr) static int redirect_cmd_input(t_token *t, t_cmd *cmd) { - if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0) + if (cmd->fd_in != STDIN_FILENO) if (close(cmd->fd_in) == -1) perror("close()"); if (t->id == '<') @@ -55,7 +58,10 @@ static int redirect_cmd_input(t_token *t, t_cmd *cmd) //EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER(); cmd->fd_in = open(t->next->content, O_RDONLY); if (cmd->fd_in == -1) - ft_perror_io("open() ", t->next->content); + { + ft_perror_io("open() ", t->next->content); // todo error + cmd->pid = -1; // Pid var as error mark, WIP + } } else if (t->id == T_DLESS) { @@ -70,7 +76,7 @@ static int redirect_cmd_output(t_token *t, t_cmd *cmd) { int flags; - if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0) + if (cmd->fd_out != STDOUT_FILENO) if (close(cmd->fd_out) == -1) perror("close()"); // TODO : Expansion + quote removal sur le word t->next->content. @@ -85,6 +91,9 @@ static int redirect_cmd_output(t_token *t, t_cmd *cmd) flags = flags | O_APPEND; cmd->fd_out = open(t->next->content, flags, S_IRWXU); if (cmd->fd_out == -1) - return (ft_reti_perror_io(0, "open() ", t->next->content)); + { + ft_perror_io("open() ", t->next->content); + cmd->pid = -1; // Pid var as error mark, WIP + } return (1); } diff --git a/srcs/shell_loop.c b/srcs/shell_loop.c index 683aa32..f202194 100644 --- a/srcs/shell_loop.c +++ b/srcs/shell_loop.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */ -/* Updated: 2021/11/14 03:59:01 by lperrey ### ########.fr */ +/* Updated: 2021/11/16 03:52:37 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,12 +41,8 @@ void shell_loop(t_all *c) ft_lstclear((t_list **)&c->token_list, free); if (!c->cmd_arr) continue ; - // Search Path/builtins - // Bien penser à mettre les ptr à NULL aprés free en cas d'erreur (pour ne pas double free si appel à free_exit()) // Exec Pipeline - //execute_cmd(c->envp, c->cmd_arr); - ft_free_cmd_arr(c->cmd_arr); - c->cmd_arr = NULL; + exec_cmd_line(c); } else if (!line_input) write(1, "\n", 1);