diff --git a/Makefile b/Makefile index fb1cc76..d39a39c 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: ttsubo +#+ +:+ +#+ # +# By: dayano +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/03 12:55:20 by ttsubo #+# #+# # -# Updated: 2025/04/26 11:30:48 by ttsubo ### ########.fr # +# Updated: 2025/04/29 16:48:58 by dayano ### ########.fr # # # # **************************************************************************** # @@ -45,9 +45,10 @@ define define_rule endef # 2.Add the source code when it is added -ROOT_SRC = main.c minish_signal.c initialize.c +ROOT_SRC = main.c minish_signal.c initialize.c error.c INVOKE_CMD_SRC = create_envp.c exec_pipeline.c execute_cmd.c \ - execute_cmd_helper.c invoke_command.c pipeline_helper.c + execute_cmd_helper.c invoke_command.c pipeline_helper.c \ + redirect.c fds.c wait_pipeline.c TOKENIZER_SRC = tokenizer.c tokenizer_error.c read_token.c \ is_quote_closed.c get_token_capa.c is_redirect_validate.c PARSER_SRC = allocate_cmds.c parser.c parser_utils.c setup_cmds.c \ diff --git a/inc/cmd.h b/inc/cmd.h index 4320694..d998913 100644 --- a/inc/cmd.h +++ b/inc/cmd.h @@ -3,16 +3,18 @@ /* ::: :::::::: */ /* cmd.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: ttsubo +#+ +:+ +#+ */ +/* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/13 13:47:36 by ttsubo #+# #+# */ -/* Updated: 2025/04/14 21:30:15 by ttsubo ### ########.fr */ +/* Updated: 2025/04/29 16:53:33 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef CMD_H # define CMD_H +# include + typedef enum e_redir_type { REDIR_NONE, @@ -29,8 +31,8 @@ typedef struct s_cmd char **argv; int capa; int status; - int pid; + pid_t pid; struct s_cmd *next; } t_cmd; -#endif \ No newline at end of file +#endif diff --git a/inc/error.h b/inc/error.h new file mode 100644 index 0000000..ba2e68d --- /dev/null +++ b/inc/error.h @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 13:48:47 by dayano #+# #+# */ +/* Updated: 2025/04/29 14:35:12 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ERROR_H +# define ERROR_H + +void print_error(char *cmd_or_path); + +#endif diff --git a/inc/exec_pipeline.h b/inc/exec_pipeline.h index 6793f29..e964098 100644 --- a/inc/exec_pipeline.h +++ b/inc/exec_pipeline.h @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 13:12:27 by dayano #+# #+# */ -/* Updated: 2025/04/24 14:17:43 by dayano ### ########.fr */ +/* Updated: 2025/04/29 16:11:28 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,6 +15,12 @@ # include "cmd.h" +typedef struct s_pipe_io +{ + int prev_fds[2]; + int curr_fds[2]; +} t_pipe_io; + void exec_pipeline(t_cmd *cmd_head, t_minish *minish); int wait_pipeline(t_cmd *cmd_head); diff --git a/inc/execute_cmd.h b/inc/execute_cmd.h index 1e9d0bb..da773ac 100644 --- a/inc/execute_cmd.h +++ b/inc/execute_cmd.h @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 21:39:18 by dayano #+# #+# */ -/* Updated: 2025/04/28 12:00:45 by dayano ### ########.fr */ +/* Updated: 2025/04/28 13:56:33 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,6 +15,8 @@ # define PATH_PREFIX_LEN 5 # define EQUAL_LEN 1 + +# define CMD_FAILED_EXIT_STATUS 126 # define CMD_NOT_FOUND_EXIT_STATUS 127 void execute_cmd(t_cmd *cmd, t_minish *minish); diff --git a/inc/invoke_command.h b/inc/invoke_command.h index bba0a58..6275686 100644 --- a/inc/invoke_command.h +++ b/inc/invoke_command.h @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 21:21:13 by dayano #+# #+# */ -/* Updated: 2025/04/21 21:00:48 by dayano ### ########.fr */ +/* Updated: 2025/04/29 16:47:04 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,18 @@ # define INVOKE_COMMAND_H # include "cmd.h" +# include -int invoke_commands(t_cmd *cmd_head, t_minish *minish); +int invoke_commands(t_cmd *cmd_head, t_minish *minish); +int exec_unit_builtin(t_cmd *cmd_head); + +// wait_pipeline.c +int wait_pipeline(t_cmd *cmd_head); + +// fds.c +void init_fds(int fds[2]); +void cleanup_fds(int fds1[2]); +void swap_fds(int prev_fds[2], int curr_fds[2]); +void create_pipe(bool need, int fds[2], t_cmd *cmd); #endif diff --git a/inc/main.h b/inc/main.h index d3118a6..fd50d89 100644 --- a/inc/main.h +++ b/inc/main.h @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/03 12:50:38 by ttsubo #+# #+# */ -/* Updated: 2025/04/28 12:00:56 by dayano ### ########.fr */ +/* Updated: 2025/04/29 16:09:27 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,7 @@ # include "create_envp.h" # include "env_utils.h" # include "env_utils_2.h" +# include "error.h" # include "exec_pipeline.h" # include "execute_cmd.h" # include "initialize.h" @@ -27,13 +28,19 @@ # include "minish_signal.h" # include "parser.h" # include "pipeline_helper.h" +# include "redirect.h" # include "struct.h" # include "tokenizer.h" +# include # include # include # include # include # include +# include +# include +# include +# include # include #endif diff --git a/inc/pipeline_helper.h b/inc/pipeline_helper.h index 774f3e8..d147757 100644 --- a/inc/pipeline_helper.h +++ b/inc/pipeline_helper.h @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 14:32:27 by dayano #+# #+# */ -/* Updated: 2025/04/24 15:02:17 by dayano ### ########.fr */ +/* Updated: 2025/04/28 14:56:23 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,12 +14,13 @@ # define PIPELINE_HELPER_H # include "cmd.h" +# include # include // pipeline_helper.c void redirect_stdout(t_cmd *cmd); bool is_redirect(t_cmd *cmd); -bool is_head(t_cmd *cmd); +bool is_head(t_cmd *cmd, t_cmd *cmd_head); bool is_tail(t_cmd *cmd); bool is_builtin(t_cmd *cmd); diff --git a/inc/redirect.h b/inc/redirect.h new file mode 100644 index 0000000..bf37425 --- /dev/null +++ b/inc/redirect.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:20:03 by dayano #+# #+# */ +/* Updated: 2025/04/28 15:30:35 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef REDIRECT_H +# define REDIRECT_H + +# include "cmd.h" + +void redirect(t_cmd *cmd); +void redirect_stdout(t_cmd *cmd); +void redirect_stdin(t_cmd *cmd); + +#endif diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..f764645 --- /dev/null +++ b/src/error.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 13:16:23 by dayano #+# #+# */ +/* Updated: 2025/04/29 14:33:57 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +/** + * @brief print error + * format: minish: : + * + * @param cmd_or_path + */ +void print_error(char *cmd_or_path) +{ + char *error_msg; + + error_msg = strerror(errno); + ft_putstr_fd("minish: ", STDERR_FILENO); + ft_putstr_fd(cmd_or_path, STDERR_FILENO); + ft_putstr_fd(": ", STDERR_FILENO); + ft_putendl_fd(error_msg, STDERR_FILENO); +} diff --git a/src/invoke_cmd/exec_pipeline.c b/src/invoke_cmd/exec_pipeline.c index 9fb79cf..f6c1dbd 100644 --- a/src/invoke_cmd/exec_pipeline.c +++ b/src/invoke_cmd/exec_pipeline.c @@ -6,93 +6,89 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 13:14:15 by dayano #+# #+# */ -/* Updated: 2025/04/25 21:16:09 by dayano ### ########.fr */ +/* Updated: 2025/04/29 16:52:01 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -void initialize_fds(int fds1[2], int fds2[2]) +static void _setup_stdin(t_cmd *cmd, t_cmd *cmd_head, int prev_fds[2]) { - fds1[0] = -1; - fds1[1] = -1; - fds2[0] = -1; - fds2[1] = -1; + if (is_head(cmd, cmd_head) || prev_fds[0] < 0) + return ; + if (dup2(prev_fds[0], STDIN_FILENO) < 0) + { + print_error(cmd->argv[0]); + exit(EX_OSERR); + } + close(prev_fds[0]); + close(prev_fds[1]); +} + +static void _setup_stdout(t_cmd *cmd, int curr_fds[2]) +{ + if (!is_tail(cmd) || curr_fds[1] >= 0) + { + close(curr_fds[0]); + if (dup2(curr_fds[1], STDOUT_FILENO) < 0) + { + print_error(cmd->argv[0]); + exit(EX_OSERR); + } + close(curr_fds[1]); + } +} + +static pid_t _fork_command(t_cmd *cmd, t_cmd *cmd_head, t_pipe_io *pipefds, + t_minish *minish) +{ + pid_t pid; + + pid = fork(); + if (pid < 0) + { + print_error(cmd->argv[0]); + exit(EX_OSERR); + } + if (pid > 0) + return (pid); + _setup_stdin(cmd, cmd_head, pipefds->prev_fds); + _setup_stdout(cmd, pipefds->curr_fds); + if ((cmd->next != NULL) && is_redirect(cmd->next)) + redirect(cmd->next); + if (is_builtin(cmd)) + exit(exec_unit_builtin(cmd)); + execute_cmd(cmd, minish); + print_error(cmd->argv[0]); + exit(EXIT_FAILURE); } /** - * @brief // execvp(cmd->argv[0], cmd->argv); - // fprintf(stderr, "%s: command not found: %s\n", program_name, - // cmd->argv[0]); - * @brief - * @param cmd_head - * @param minish + * @brief Execute a pipeline of commands. + * + * For each command, create a pipe if needed, fork a child, redirect its + * stdin/stdout through the pipes, and record its PID for waiting. + * + * @param cmd_head First command in the pipeline. + * @param minish Shell context for built-ins and execution. */ -// note : process in while loop of inside -// fds1[0] = fds2[0]; -// fds1[1] = fds2[1]; -// if (!is_tail(cmd)) -// { -// if (pipe(fds2) < 0) -// { -// perror("pipe"); -// exit(3); -// } -// } -// cmd->pid = fork(); -// if (cmd->pid < 0) -// { -// perror("fork"); -// exit(3); -// } -// if (cmd->pid > 0) -// { -// if (fds1[0] != -1) -// close(fds1[0]); -// if (fds1[1] != -1) -// close(fds1[1]); -// continue ; -// } -// if (!is_head(cmd)) -// { -// close(STDIN_FILENO); -// dup2(fds1[0], STDIN_FILENO); -// close(fds1[0]); -// close(fds1[1]); -// } -// if (!is_tail(cmd)) -// { -// close(fds2[0]); -// close(STDOUT_FILENO); -// dup2(fds2[1], STDOUT_FILENO); -// close(fds2[1]); -// } -// if ((cmd->next != NULL) && is_redirect(cmd->next)) -// { -// redirect_stdout(cmd->next); -// } -// if (!is_builtin(cmd)) -// { -// execute_cmd(cmd, minish); -// exit(EXIT_FAILURE); -// } -// cmd = cmd->next; void exec_pipeline(t_cmd *cmd_head, t_minish *minish) { - t_cmd *cmd; - int fds1[2]; - int fds2[2]; + t_cmd *cmd; + t_pipe_io pipefds; + bool need_pipe; - (void)minish; cmd = cmd_head; - initialize_fds(fds1, fds2); + init_fds(pipefds.prev_fds); + init_fds(pipefds.curr_fds); while (cmd && !is_redirect(cmd)) { + need_pipe = !is_tail(cmd); + create_pipe(need_pipe, pipefds.curr_fds, cmd); + cmd->pid = _fork_command(cmd, cmd_head, &pipefds, minish); + cleanup_fds(pipefds.prev_fds); + swap_fds(pipefds.prev_fds, pipefds.curr_fds); + init_fds(pipefds.curr_fds); + cmd = cmd->next; } } - -int wait_pipeline(t_cmd *cmd_head) -{ - (void)cmd_head; - return (0); -} diff --git a/src/invoke_cmd/execute_cmd.c b/src/invoke_cmd/execute_cmd.c index 8d3f4ca..aeac624 100644 --- a/src/invoke_cmd/execute_cmd.c +++ b/src/invoke_cmd/execute_cmd.c @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 21:25:41 by dayano #+# #+# */ -/* Updated: 2025/04/25 21:17:14 by dayano ### ########.fr */ +/* Updated: 2025/04/28 13:56:43 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -37,6 +37,8 @@ char *get_cmd_path(char *cmd, char **envp) char **path_set; char *full_path; + if (!cmd && ft_strlen(cmd) == 0) + return (NULL); if (access(cmd, X_OK) == 0) return (cmd); path_line = get_path_line(envp); @@ -69,19 +71,14 @@ void execute_cmd(t_cmd *cmd, t_minish *minish) print_cmd_not_found(cmd); return ; } - if (!cmd->argv[0] || ft_strlen(cmd->argv[0]) == 0) - { - ft_putstr_fd("Command '' not found\n", STDERR_FILENO); - exit(127); - } if (!is_pathname(cmd->argv[0], envp, &fullpath)) { - ft_putstr_fd("Command '' not found\n", STDERR_FILENO); - exit(127); + print_cmd_not_found(cmd); + return ; } if (execve(fullpath, cmd->argv, envp) < 0) { free(fullpath); - perror("execve"); + cmd->status = CMD_FAILED_EXIT_STATUS; } } diff --git a/src/invoke_cmd/fds.c b/src/invoke_cmd/fds.c new file mode 100644 index 0000000..70dc718 --- /dev/null +++ b/src/invoke_cmd/fds.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* fds.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 16:45:58 by dayano #+# #+# */ +/* Updated: 2025/04/29 16:46:03 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +void init_fds(int fds[2]) +{ + fds[0] = -1; + fds[1] = -1; +} + +void cleanup_fds(int fds1[2]) +{ + if (fds1[0] != -1) + close(fds1[0]); + if (fds1[1] != -1) + close(fds1[1]); +} + +void swap_fds(int prev_fds[2], int curr_fds[2]) +{ + prev_fds[0] = curr_fds[0]; + prev_fds[1] = curr_fds[1]; +} + +void create_pipe(bool need, int fds[2], t_cmd *cmd) +{ + if (!need) + { + fds[0] = -1; + fds[1] = -1; + return ; + } + if (pipe(fds) < 0) + { + print_error(cmd->argv[0]); + exit(EX_OSERR); + } +} diff --git a/src/invoke_cmd/invoke_command.c b/src/invoke_cmd/invoke_command.c index 65d53c6..6375ade 100644 --- a/src/invoke_cmd/invoke_command.c +++ b/src/invoke_cmd/invoke_command.c @@ -6,7 +6,7 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 21:19:33 by dayano #+# #+# */ -/* Updated: 2025/04/25 21:05:18 by dayano ### ########.fr */ +/* Updated: 2025/04/28 21:37:53 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,7 @@ static bool is_unit_builtin(t_cmd *cmd_head) { (void)cmd_head; - return (true); + return (false); } /** @@ -35,7 +35,7 @@ static bool is_unit_builtin(t_cmd *cmd_head) * @param cmd_head * @return int */ -static int exec_unit_builtin(t_cmd *cmd_head) +int exec_unit_builtin(t_cmd *cmd_head) { (void)cmd_head; return (0); diff --git a/src/invoke_cmd/pipeline_helper.c b/src/invoke_cmd/pipeline_helper.c index 2381e68..1548f3c 100644 --- a/src/invoke_cmd/pipeline_helper.c +++ b/src/invoke_cmd/pipeline_helper.c @@ -6,17 +6,12 @@ /* By: dayano +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 14:29:29 by dayano #+# #+# */ -/* Updated: 2025/04/24 14:57:00 by dayano ### ########.fr */ +/* Updated: 2025/04/28 21:07:41 by dayano ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -void redirect_stdout(t_cmd *cmd) -{ - (void)cmd; -} - bool is_redirect(t_cmd *cmd) { if (cmd->type != REDIR_NONE) @@ -24,20 +19,22 @@ bool is_redirect(t_cmd *cmd) return (false); } -bool is_head(t_cmd *cmd) +bool is_head(t_cmd *cmd, t_cmd *cmd_head) { - (void)cmd; - return (true); + if (cmd == cmd_head) + return (true); + return (false); } bool is_tail(t_cmd *cmd) { - (void)cmd; - return (true); + if (cmd->next == NULL || is_redirect(cmd->next)) + return (true); + return (false); } bool is_builtin(t_cmd *cmd) { (void)cmd; - return (true); + return (false); } diff --git a/src/invoke_cmd/redirect.c b/src/invoke_cmd/redirect.c new file mode 100644 index 0000000..877cb8a --- /dev/null +++ b/src/invoke_cmd/redirect.c @@ -0,0 +1,119 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:19:19 by dayano #+# #+# */ +/* Updated: 2025/04/28 16:57:45 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +void redirect_stdout(t_cmd *cmd) +{ + int fd; + char *path; + + path = cmd->argv[0]; + if (cmd->type == REDIR_OUT) + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + else if (cmd->type == REDIR_APPEND) + fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644); + else + return ; + if (fd < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror(path); + return ; + } + if (dup2(fd, STDOUT_FILENO) < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror(path); + } + close(fd); +} + +bool is_limiter(int fd, char *limiter) +{ + char *line; + + line = NULL; + line = readline("> "); + if (!line) + { + write(STDOUT_FILENO, "\n", 1); + return (true); + } + if (ft_strcmp(line, limiter) == 0) + { + free(line); + return (true); + } + write(fd, line, ft_strlen(line)); + write(fd, "\n", 1); + free(line); + return (false); +} + +void here_doc(char *limiter) +{ + int pipefd[2]; + + if (pipe(pipefd) < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror("pipe"); + return ; + } + while (!is_limiter(pipefd[1], limiter)) + ; + close(pipefd[1]); + if (dup2(pipefd[0], STDIN_FILENO) < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror("here_doc"); + } + close(pipefd[0]); +} + +void redirect_stdin(t_cmd *cmd) +{ + int fd; + char *path; + + path = cmd->argv[0]; + if (cmd->type == REDIR_HEREDOC) + { + here_doc(cmd->argv[0]); + return ; + } + else if (cmd->type == REDIR_IN) + { + fd = open(path, O_RDONLY); + if (fd < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror(path); + return ; + } + if (dup2(fd, STDIN_FILENO) < 0) + { + ft_putstr_fd("minish: ", STDERR_FILENO); + perror(path); + } + close(fd); + } +} + +void redirect(t_cmd *cmd) +{ + if (cmd->type == REDIR_IN || cmd->type == REDIR_HEREDOC) + redirect_stdin(cmd); + if (cmd->type == REDIR_OUT || cmd->type == REDIR_APPEND) + redirect_stdout(cmd); +} diff --git a/src/invoke_cmd/wait_pipeline.c b/src/invoke_cmd/wait_pipeline.c new file mode 100644 index 0000000..88c7226 --- /dev/null +++ b/src/invoke_cmd/wait_pipeline.c @@ -0,0 +1,73 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wait_pipeline.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 16:42:14 by dayano #+# #+# */ +/* Updated: 2025/04/29 16:42:50 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +/** + * @brief Wait for one command’s process to finish. + * + * This function calls waitpid() for cmd->pid, stores the exit + * or signal status into cmd->status, and returns that status. + * + * @param cmd The command whose child process to wait for. + * @return The exit status or 128+signal number on signal, + or EXIT_FAILURE on error. + */ +static int _get_status(t_cmd *cmd) +{ + int ret; + int status; + + ret = 0; + ret = waitpid(cmd->pid, &status, 0); + if (ret < 0) + { + cmd->status = EXIT_FAILURE; + return (cmd->status); + } + if (WIFEXITED(status)) + cmd->status = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + cmd->status = 128 + WTERMSIG(status); + else + cmd->status = EXIT_FAILURE; + return (cmd->status); +} + +/** + * @brief Wait for all child processes in the pipeline to finish. + * + * This function walks through each command in the pipeline, + * calls waitpid() for every non-redirect node, stores each + * child’s exit or signal status into cmd->status, and then + * returns the status of the last command executed. + * + * @param cmd_head Pointer to the head of the command list. + * @return The exit status of the last command in the pipeline. + */ +int wait_pipeline(t_cmd *cmd_head) +{ + int last_status; + int ret; + t_cmd *cmd; + + last_status = 0; + ret = 0; + cmd = cmd_head; + while (cmd) + { + if (!is_redirect(cmd)) + last_status = _get_status(cmd); + cmd = cmd->next; + } + return (last_status); +} diff --git a/src/main.c b/src/main.c index 06ec84c..d3307c7 100644 --- a/src/main.c +++ b/src/main.c @@ -39,13 +39,12 @@ static void destroy_minish(t_minish *minish) * @return true * @return false */ -static bool prompt(char *program_name, t_minish *minish, int *status) +static bool prompt(char *program_name, t_minish *minish) { char *line; char **tokens; t_cmd **cmds; - (void)status; line = readline("$ "); if (!line) return (false); @@ -60,7 +59,7 @@ static bool prompt(char *program_name, t_minish *minish, int *status) return (false); } if (cmds[0]->argc > 0) - *status = invoke_commands(cmds[0], minish); + minish->last_status = invoke_commands(cmds[0], minish); _free_tokens(tokens); free_cmds(cmds, cmds_len(cmds)); free(line); @@ -71,14 +70,13 @@ int main(int argc, char **argv, char **envp) { t_minish *minish; char *program_name; - int exit_status; (void)argc; program_name = argv[0]; minish = initialize(envp); minish_signal(); - while (prompt(program_name, minish, &exit_status)) + while (prompt(program_name, minish)) ; destroy_minish(minish); - return (exit_status); + return (minish->last_status); }