#include "minishell.h" static int exec_external(t_command *cmd, t_shell *sh) { char **envp = env_to_envp(sh); if (!envp) return 1; execve(cmd->path, cmd->argv, envp); perror(cmd->path); env_free_envp(envp); return 126; } static int run_command_child(t_command *cmd, t_shell *sh) { int saved_in, saved_out; if (apply_redirections(cmd, &saved_in, &saved_out) != 0) return 1; if (is_builtin(cmd->argv[0])) return exec_builtin(cmd, sh); return exec_external(cmd, sh); } static int run_command_parent_builtin(t_command *cmd, t_shell *sh) { int saved_in, saved_out; int status; if (apply_redirections(cmd, &saved_in, &saved_out) != 0) return 1; status = exec_builtin(cmd, sh); restore_redirections(saved_in, saved_out); return status; } static int setup_pipes(int idx, int count, int pipefd[2]) { if (idx + 1 >= count) return 0; if (pipe(pipefd) == -1) return 1; return 0; } static void setup_child_fds(int idx, int count, int prev_read, int pipefd[2]) { if (prev_read != -1) { dup2(prev_read, STDIN_FILENO); close(prev_read); } if (idx + 1 < count) { dup2(pipefd[1], STDOUT_FILENO); close(pipefd[0]); close(pipefd[1]); } } static void close_parent_fds(int idx, int count, int *prev_read, int pipefd[2]) { if (*prev_read != -1) close(*prev_read); if (idx + 1 < count) { close(pipefd[1]); *prev_read = pipefd[0]; } else *prev_read = -1; } int execute_pipeline(t_pipeline *p, t_shell *sh) { int i; int prev_read = -1; pid_t *pids; int status = 0; if (!p || p->count == 0) return 0; if (prepare_heredocs(p, sh) != 0) return sh->exit_status; for (size_t k = 0; k < p->count; k++) { if (!p->cmds[k]->argv || !p->cmds[k]->argv[0]) return 1; free(p->cmds[k]->path); p->cmds[k]->path = resolve_path(p->cmds[k]->argv[0], sh); } if (p->count == 1 && is_builtin(p->cmds[0]->argv[0])) return run_command_parent_builtin(p->cmds[0], sh); pids = (pid_t *)calloc(p->count, sizeof(pid_t)); if (!pids) return 1; for (i = 0; i < (int)p->count; i++) { int pipefd[2] = {-1, -1}; if (setup_pipes(i, (int)p->count, pipefd)) break; pids[i] = fork(); if (pids[i] == 0) { ms_set_child_signals(); setup_child_fds(i, (int)p->count, prev_read, pipefd); if (!p->cmds[i]->path) { fprintf(stderr, "minishell: %s: command not found\n", p->cmds[i]->argv[0]); exit(127); } status = run_command_child(p->cmds[i], sh); exit(status); } close_parent_fds(i, (int)p->count, &prev_read, pipefd); } for (i = 0; i < (int)p->count; i++) { int wstatus = 0; if (pids[i] > 0) { waitpid(pids[i], &wstatus, 0); if (i == (int)p->count - 1) { if (WIFEXITED(wstatus)) status = WEXITSTATUS(wstatus); else if (WIFSIGNALED(wstatus)) status = 128 + WTERMSIG(wstatus); } } } free(pids); return status; }