save commit
This commit is contained in:
134
minishell-codex/src/executor/exec.c
Normal file
134
minishell-codex/src/executor/exec.c
Normal file
@@ -0,0 +1,134 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user