From 0bd9dcb3bb9fbad5dc8d8c81d2899784b297922e Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Thu, 18 Nov 2021 14:28:56 +0100 Subject: [PATCH] simple_cmd_builtin() done. + exec_cmd_line.c split in multiples files --- Makefile | 3 +- headers/minishell_prototypes.h | 7 +- srcs/exec/exec_cmd_line.c | 250 +-------------------------------- srcs/exec/find_access.c | 113 +++++++++++++++ srcs/exec/pipeline.c | 95 +++++++++++++ srcs/exec/simple_cmd_builtin.c | 63 +++++++++ srcs/exec/subshell_exec.c | 37 +++++ srcs/exec/subshell_wait.c | 53 +++++++ 8 files changed, 370 insertions(+), 251 deletions(-) create mode 100644 srcs/exec/find_access.c create mode 100644 srcs/exec/pipeline.c create mode 100644 srcs/exec/simple_cmd_builtin.c create mode 100644 srcs/exec/subshell_exec.c create mode 100644 srcs/exec/subshell_wait.c diff --git a/Makefile b/Makefile index fd56e97..bdedc6e 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ 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 \ + exec_cmd_line.c pipeline.c \ + find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \ cd.c pwd.c export.c unset.c exit.c env.c echo.c DIR_OBJS = builds diff --git a/headers/minishell_prototypes.h b/headers/minishell_prototypes.h index 064ffce..ff2143c 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/16 22:58:35 by lperrey ### ########.fr */ +/* Updated: 2021/11/18 14:05:57 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,6 +42,11 @@ int redirections(t_token *token_list, t_cmd **cmd_arr); // Exec int exec_cmd_line(t_all *c); +int pipeline(t_all *c); +int cmd_find_access(t_cmd *cmd, char *path[]); +int cmd_exec_in_subshell(t_cmd *cmd, t_all *c); +void wait_subshell(pid_t last_cmd_pid, int *last_exit_status); +int simple_command_builtin(t_cmd *cmd, t_all *c); // Builtins int builtin_cd(int argc, char *argv[], t_all *c); diff --git a/srcs/exec/exec_cmd_line.c b/srcs/exec/exec_cmd_line.c index f532117..bbd417c 100644 --- a/srcs/exec/exec_cmd_line.c +++ b/srcs/exec/exec_cmd_line.c @@ -6,22 +6,13 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ -/* Updated: 2021/11/18 12:31:04 by lperrey ### ########.fr */ +/* Updated: 2021/11/18 13:29:25 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_find_access(t_cmd *pipeline[], char *path[]); -pid_t 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); -void wait_subshell(pid_t last_cmd_pid, int *last_exit_status); int exec_cmd_line(t_all *c) { @@ -32,242 +23,3 @@ int exec_cmd_line(t_all *c) } return (1); } - -int pipeline(t_all *c) -{ - if (!open_pipes(c->cmd_arr)) - return (0); - if (!pipeline_find_access(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); - else - wait_subshell(pipeline_exec(c->cmd_arr, c), &c->last_exit_status); - free_pipeline(&c->cmd_arr); - return (1); -} - -int simple_cmd_builtin(t_cmd *cmd, t_all *c) -{ - // TODO - 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); -} - -// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 -// faire des test sur la valeur de errno selon les cas (if directory, if pathname invalid, ...) -int handle_access_error(char *file_name) -{ - int tmp; - - tmp = errno; - ft_perror_io("minishell: ", file_name); - errno = tmp; - if (errno == EACCES) - return (127); - return (1); - // 126 -} - -static t_builtin_f search_builtin(char *cmd_name) -{ - if (ft_strncmp(cmd_name, "echo", 4 + 1) == 0) - return (&builtin_echo); - else if (ft_strncmp(cmd_name, "cd", 2 + 1) == 0) - return (&builtin_cd); - else if (ft_strncmp(cmd_name, "pwd", 3 + 1) == 0) - return (&builtin_pwd); - else if (ft_strncmp(cmd_name, "export", 6 + 1) == 0) - return (&builtin_export); - else if (ft_strncmp(cmd_name, "unset", 5 + 1) == 0) - return (&builtin_unset); - else if (ft_strncmp(cmd_name, "env", 3 + 1) == 0) - return (&builtin_env); - else if (ft_strncmp(cmd_name, "exit", 4 + 1) == 0) - return (&builtin_exit); - return (NULL); -} - -static int search_cmd_path(char *cmd_name, char **cmd_path, char *path[]) -{ - int i; - - if (!path) - return (1); - cmd_name = ft_strjoin("/", cmd_name); - if (!cmd_name) - return (ft_reti_perror(-1, "search_cmd_path()")); - i = 0; - while (path[i]) - { - *cmd_path = ft_strjoin(path[i], cmd_name); - if (!*cmd_path) - return (ft_reti_perror(-1, "search_cmd_path()")); - if (access(*cmd_path, X_OK) == 0) - break ; - else - { - free(*cmd_path); - *cmd_path = NULL; // TODO : free_null() - } - i++; - } - free(cmd_name); - return (1); -} - -int cmd_find_access(t_cmd *cmd, char *path[]) -{ - if (ft_strchr(cmd->argv[0], '/')) - { - if (access(cmd->argv[0], X_OK) == -1) - cmd->error = handle_access_error(cmd->argv[0]); - else - { - cmd->path = ft_strdup(cmd->argv[0]); - if (!cmd->path) - return (0); - } - } - else - { - cmd->builtin_func = search_builtin(cmd->argv[0]); - if (cmd->builtin_func) - return (1); - if (search_cmd_path(cmd->argv[0], &cmd->path, path) == -1) - return (0); - if (!cmd->path) - { - cmd->error = 127; - ft_putstr_fd("minishell: ", 2); - ft_putstr_fd(cmd->argv[0], 2); - ft_putstr_fd(": command not found\n", 2); - } - } - return (1); -} - -int pipeline_find_access(t_cmd *pipeline[], char *path[]) -{ - int i; - - i = 0; - while (pipeline[i]) - { - if (!cmd_find_access(pipeline[i], path)) - return (0); - i++; - } - return (1); -} - -// TODO : Change exit status as in documentation : -// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 -pid_t pipeline_exec(t_cmd *pipeline[], t_all *c) -{ - int i; - int ret; - - i = 0; - while (pipeline[i]) - { - if (!pipeline[i]->error) - { - ret = cmd_exec_in_subshell(pipeline[i], c); - if (ret != EXIT_SUCCESS) - free_exit(c, ret); - } - i++; - } - close_pipeline_fd(c->cmd_arr); - i -= 1; - if (pipeline[i]->error) - c->last_exit_status = pipeline[i]->error; - return (pipeline[i]->pid); -} - -int handle_wait_error(void) -{ - if (errno == ECHILD) - return (-1); - else if (errno == EINTR) - return (0); - else - perror("wait()"); - return (-1); -} - -void wait_subshell(pid_t last_cmd_pid, int *last_exit_status) -{ - int wstatus; - int ret; - - wstatus = 0; - if (last_cmd_pid > 0) - { - if (waitpid(last_cmd_pid, &wstatus, 0) == -1) - perror("waitpid()"); - if (WIFEXITED(wstatus)) - *last_exit_status = WEXITSTATUS(wstatus); - } - ret = 0; - while (ret != -1) - { - ret = wait(&wstatus); - if (ret == -1) - ret = handle_wait_error(); - } - if (WIFSIGNALED(wstatus)) - { - write(STDIN_FILENO, "\n", 1); - *last_exit_status = 128 + WTERMSIG(wstatus); - } -} - -int cmd_exec_in_subshell(t_cmd *cmd, t_all *c) -{ - cmd->pid = fork(); - if (cmd->pid == -1) - perror("fork()"); - if (cmd->pid == 0) - { - c->signal_behaviour.sa_handler = SIG_DFL; - sigaction(SIGINT, &c->signal_behaviour, NULL); - 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(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/exec/find_access.c b/srcs/exec/find_access.c new file mode 100644 index 0000000..2f2f53a --- /dev/null +++ b/srcs/exec/find_access.c @@ -0,0 +1,113 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* find_access.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/18 13:20:20 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int search_cmd_path(char *cmd_name, char **cmd_path, + char *path[]); +static t_builtin_f search_builtin(char *cmd_name); +static int handle_access_error(char *file_name); + +// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 +// faire des test sur la valeur de errno selon les cas (if directory, if pathname invalid, ...) + +int cmd_find_access(t_cmd *cmd, char *path[]) +{ + if (ft_strchr(cmd->argv[0], '/')) + { + if (access(cmd->argv[0], X_OK) == -1) + cmd->error = handle_access_error(cmd->argv[0]); + else + { + cmd->path = ft_strdup(cmd->argv[0]); + if (!cmd->path) + return (0); + } + } + else + { + cmd->builtin_func = search_builtin(cmd->argv[0]); + if (cmd->builtin_func) + return (1); + if (search_cmd_path(cmd->argv[0], &cmd->path, path) == -1) + return (0); + if (!cmd->path) + { + cmd->error = 127; + ft_putstr_fd("minishell: ", 2); + ft_putstr_fd(cmd->argv[0], 2); + ft_putstr_fd(": command not found\n", 2); + } + } + return (1); +} + + +static int search_cmd_path(char *cmd_name, char **cmd_path, char *path[]) +{ + int i; + + if (!path) + return (1); + cmd_name = ft_strjoin("/", cmd_name); + if (!cmd_name) + return (ft_reti_perror(-1, "search_cmd_path()")); + i = 0; + while (path[i]) + { + *cmd_path = ft_strjoin(path[i], cmd_name); + if (!*cmd_path) + return (ft_reti_perror(-1, "search_cmd_path()")); + if (access(*cmd_path, X_OK) == 0) + break ; + else + { + free(*cmd_path); + *cmd_path = NULL; // TODO : free_null() + } + i++; + } + free(cmd_name); + return (1); +} + +static t_builtin_f search_builtin(char *cmd_name) +{ + if (ft_strncmp(cmd_name, "echo", 4 + 1) == 0) + return (&builtin_echo); + else if (ft_strncmp(cmd_name, "cd", 2 + 1) == 0) + return (&builtin_cd); + else if (ft_strncmp(cmd_name, "pwd", 3 + 1) == 0) + return (&builtin_pwd); + else if (ft_strncmp(cmd_name, "export", 6 + 1) == 0) + return (&builtin_export); + else if (ft_strncmp(cmd_name, "unset", 5 + 1) == 0) + return (&builtin_unset); + else if (ft_strncmp(cmd_name, "env", 3 + 1) == 0) + return (&builtin_env); + else if (ft_strncmp(cmd_name, "exit", 4 + 1) == 0) + return (&builtin_exit); + return (NULL); +} + +static int handle_access_error(char *file_name) +{ + int tmp; + + tmp = errno; + ft_perror_io("minishell: ", file_name); + errno = tmp; + if (errno == EACCES) + return (127); + return (1); + // 126 +} diff --git a/srcs/exec/pipeline.c b/srcs/exec/pipeline.c new file mode 100644 index 0000000..576d3ae --- /dev/null +++ b/srcs/exec/pipeline.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pipeline.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/18 14:12:36 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int open_pipes(t_cmd *pipeline[]); +static int pipeline_find_access(t_cmd *pipeline[], char *path[]); +static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c); + +int pipeline(t_all *c) +{ + if (!open_pipes(c->cmd_arr)) + return (0); + if (!pipeline_find_access(c->cmd_arr, c->path)) + return (0); + if (ft_2d_arrlen(c->cmd_arr) == 1 && c->cmd_arr[0]->builtin_func) + simple_command_builtin(c->cmd_arr[0], c); + else + wait_subshell(pipeline_exec(c->cmd_arr, c), &c->last_exit_status); + free_pipeline(&c->cmd_arr); + return (1); +} + +static 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); +} + +static int pipeline_find_access(t_cmd *pipeline[], char *path[]) +{ + int i; + + i = 0; + while (pipeline[i]) + { + if (!cmd_find_access(pipeline[i], path)) + return (0); + i++; + } + return (1); +} + +// TODO : Change exit status as in documentation : +// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 +static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c) +{ + int i; + int ret; + + i = 0; + while (pipeline[i]) + { + if (!pipeline[i]->error) + { + ret = cmd_exec_in_subshell(pipeline[i], c); + if (ret != EXIT_SUCCESS) + free_exit(c, ret); + } + i++; + } + close_pipeline_fd(c->cmd_arr); + i -= 1; + if (pipeline[i]->error) + c->last_exit_status = pipeline[i]->error; + return (pipeline[i]->pid); +} diff --git a/srcs/exec/simple_cmd_builtin.c b/srcs/exec/simple_cmd_builtin.c new file mode 100644 index 0000000..902dfa8 --- /dev/null +++ b/srcs/exec/simple_cmd_builtin.c @@ -0,0 +1,63 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* simple_cmd_builtin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/18 14:08:56 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int restore_stdio(int stdin_dup, int stdout_dup); + +int simple_command_builtin(t_cmd *cmd, t_all *c) +{ + int stdin_dup; + int stdout_dup; + + stdin_dup = 0; + stdout_dup = 0; + if (cmd->fd_in != STDIN_FILENO) + { + stdin_dup = dup(STDIN_FILENO); + if (stdin_dup == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup()")); + if (dup2(cmd->fd_in, STDIN_FILENO) == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup2()")); + } + if (cmd->fd_out != STDOUT_FILENO) + { + stdout_dup = dup(STDOUT_FILENO); + if (stdout_dup == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup()")); + if (dup2(cmd->fd_out, STDOUT_FILENO) == -1) + return (ft_reti_perror(EXIT_FAILURE, "dup2()")); + } + c->last_exit_status = cmd->builtin_func(ft_2d_arrlen(cmd->argv), cmd->argv, c); + if (!restore_stdio(stdin_dup, stdout_dup)) + return (EXIT_FAILURE); + return (EXIT_SUCCESS); +} + +static int restore_stdio(int stdin_dup, int stdout_dup) +{ + if (stdin_dup) + { + if (dup2(stdin_dup, STDIN_FILENO) == -1) + return (ft_reti_perror(0, "dup2()")); + if (close(stdin_dup) == -1) + return (ft_reti_perror(0, "close()")); + } + if (stdout_dup) + { + if (dup2(stdout_dup, STDOUT_FILENO) == -1) + return (ft_reti_perror(0, "dup2()")); + if (close(stdout_dup) == -1) + return (ft_reti_perror(0, "close()")); + } + return (1); +} diff --git a/srcs/exec/subshell_exec.c b/srcs/exec/subshell_exec.c new file mode 100644 index 0000000..2f8b8df --- /dev/null +++ b/srcs/exec/subshell_exec.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* subshell_exec.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/18 13:37:17 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int cmd_exec_in_subshell(t_cmd *cmd, t_all *c) +{ + cmd->pid = fork(); + if (cmd->pid == -1) + perror("fork()"); + if (cmd->pid == 0) + { + c->signal_behaviour.sa_handler = SIG_DFL; + sigaction(SIGINT, &c->signal_behaviour, NULL); + 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(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/exec/subshell_wait.c b/srcs/exec/subshell_wait.c new file mode 100644 index 0000000..fdf16b0 --- /dev/null +++ b/srcs/exec/subshell_wait.c @@ -0,0 +1,53 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* subshell_wait.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ +/* Updated: 2021/11/18 13:27:43 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int handle_wait_error(void); + +void wait_subshell(pid_t last_cmd_pid, int *last_exit_status) +{ + int wstatus; + int ret; + + wstatus = 0; + if (last_cmd_pid > 0) + { + if (waitpid(last_cmd_pid, &wstatus, 0) == -1) + perror("waitpid()"); + if (WIFEXITED(wstatus)) + *last_exit_status = WEXITSTATUS(wstatus); + } + ret = 0; + while (ret != -1) + { + ret = wait(&wstatus); + if (ret == -1) + ret = handle_wait_error(); + } + if (WIFSIGNALED(wstatus)) + { + write(STDIN_FILENO, "\n", 1); + *last_exit_status = 128 + WTERMSIG(wstatus); + } +} + +static int handle_wait_error(void) +{ + if (errno == ECHILD) + return (-1); + else if (errno == EINTR) + return (0); + else + perror("wait()"); + return (-1); +}