Files
minishell/executor_new_previous.c
2026-02-09 20:47:43 +01:00

341 lines
7.7 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* executor_new.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/28 13:03:44 by sede-san #+# #+# */
/* Updated: 2026/02/08 19:05:37 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "executor.h"
#include "builtins.h"
#include <stdint.h>
#include <errno.h>
static void handle_execve_error();
static void handle_parent_process(
int *prev_read_fd,
t_list *current_command,
int pipefd[2]
);
static int handle_pipeline(
t_list *current_command,
int pipefd[2],
int *exit_status
);
static inline uint8_t execute_builtin(
t_command *command,
t_minishell *minishell
);
static void execute_external_command(
t_command *command,
t_minishell *minishell
);
static pid_t handle_fork(
t_list *current_command,
t_minishell *minishell
);
static uint8_t execute_command(
t_command *command,
t_minishell *minishell
);
static inline bool can_execute_command(t_command *command, t_minishell *minishell);
static inline bool command_exists(t_command *command, t_minishell *minishell);
static void cmdfree(t_command *command);
static void cmdfree_argv(char **argv);
# define WRITE_PIPE 1
# define READ_PIPE 0
# define CHILD_PID 0
u_int8_t execute(
t_list *command_list,
t_minishell *minishell
) {
t_list *current_command;
int prev_read_fd;
int exit_status;
int pipefd[2];
pid_t pid;
prev_read_fd = -1;
exit_status = EXIT_SUCCESS;
current_command = command_list;
while (current_command != NULL)
{
if (handle_pipeline(current_command, pipefd, &exit_status) == EXIT_FAILURE)
break ;
pid = handle_fork(current_command, minishell);
if (pid == -1)
{
perror("fork");
exit_status = EXIT_FAILURE;
break ;
}
if (pid == CHILD_PID)
handle_child_process(prev_read_fd, current_command, pipefd, minishell);
handle_parent_process(&prev_read_fd, current_command, pipefd);
current_command = current_command->next;
}
ft_lstclear(&command_list, (void (*)(void *))cmdfree);
while (wait(&exit_status) > 0)
{
if (WIFEXITED(exit_status))
exit_status = WEXITSTATUS(exit_status);
}
return (exit_status);
}
static int handle_pipeline(
t_list *current_command,
int pipefd[2],
int *exit_status
) {
if (current_command->next) // create pipe if needed
{
if (pipe(pipefd) == -1)
{
perror("pipe");
*exit_status = EXIT_FAILURE;
return (EXIT_FAILURE);
}
}
return (EXIT_SUCCESS);
}
static void handle_parent_process(
int *prev_read_fd,
t_list *current_command,
int pipefd[2]
) {
if (*prev_read_fd != -1)
close(*prev_read_fd);
if (current_command->next)
{
close(pipefd[WRITE_PIPE]); // parent does not write
*prev_read_fd = pipefd[READ_PIPE]; // pass read end forward
}
else
*prev_read_fd = -1;
}
static pid_t handle_fork(
t_list *current_command,
t_minishell *minishell
) {
pid_t pid;
const t_command *command = (t_command *)current_command->content;
pid = 0;
if (current_command->next != NULL
|| !is_builtin(command->path, minishell))
pid = fork();
return (pid);
}
void handle_child_process(int prev_read_fd, t_list *current_command, int pipefd[2], t_minishell *minishell)
{
redirect_pipes(prev_read_fd, current_command, pipefd);
execute_command((t_command *)current_command->content, minishell);
}
void redirect_pipes(int prev_read_fd, t_list *current_command, int pipefd[2])
{
redirect_input_pipe(prev_read_fd);
redirect_output_pipe(current_command, pipefd);
}
void redirect_output_pipe(t_list * current_command, int pipefd[2])
{
if (current_command->next)
{
dup2(pipefd[WRITE_PIPE], STDOUT_FILENO);
close(pipefd[READ_PIPE]);
close(pipefd[WRITE_PIPE]);
}
}
void redirect_input_pipe(int prev_read_fd)
{
if (prev_read_fd != -1)
{
dup2(prev_read_fd, STDIN_FILENO);
close(prev_read_fd);
}
}
static inline bool can_execute_command(
t_command *command,
t_minishell *minishell
) {
if (!is_builtin(command->path, minishell)
&& access(command->path, X_OK) != EXIT_SUCCESS)
return (false);
return (true);
}
static inline bool command_exists(
t_command *command,
t_minishell *minishell
) {
if (!is_builtin(command->path, minishell)
&& access(command->path, F_OK) != EXIT_SUCCESS)
return (false);
return (true);
}
static uint8_t execute_command(
t_command *command,
t_minishell *minishell
) {
if (is_builtin(command->path, minishell))
return (execute_builtin(command, minishell));
else
{
execute_external_command(command, minishell);
return (EXIT_FAILURE); //! should never reach here
}
}
static inline uint8_t execute_builtin(
t_command *command,
t_minishell *minishell
) {
const t_builtin_func builtin
= ft_hashmap_get(minishell->builtins, command->path);
return (builtin(*command, minishell));
}
static void execute_external_command(
t_command *command,
t_minishell *minishell
) {
char **envp;
envp = get_envp(minishell);
if (envp == NULL)
{
perror("get_envp");
exit(EXIT_FAILURE);
}
execve(command->path, command->argv, envp);
handle_execve_error();
}
static void handle_execve_error() {
perror("execve");
exit(EXIT_FAILURE);
}
// static inline bool is_piped(
// t_command *command
// ) {
// return (command->piped_to != NULL || command->piped_from != NULL);
// }
// static u_int8_t handle_child_process(
// t_command *command,
// t_minishell *minishell
// ) {
// if (!redirect_pipes(command))
// exit(EXIT_FAILURE);
// execute_command(command, minishell);
// exit(EXIT_FAILURE);
// }
// static int redirect_pipe(
// int from,
// int to
// ) {
// if (dup2(from, to) == -1)
// return (-1);
// close(from);
// return (0);
// }
// static int redirect_pipes(
// t_command *command
// ) {
// if (command->piped_from &&
// redirect_pipe(command->piped_from->outfile, STDIN_FILENO) == -1)
// {
// perror("dup2");
// return (0);
// }
// if (command->piped_to &&
// redirect_pipe(command->outfile, STDOUT_FILENO) == -1)
// {
// perror("dup2");
// return (0);
// }
// return (1);
// }
// static void show_error(
// t_command *command,
// t_minishell *minishell
// ) {
// if (!command_exists(command, minishell))
// {
// ft_eprintf("minishell: %s: command not found\n", command->argv[0]);
// minishell->exit_status = 127;
// }
// else if (!can_execute_command(command, minishell))
// {
// ft_eprintf("minishell: %s: %s\n", command->path, strerror(errno));
// minishell->exit_status = errno;
// }
// }
static void cmdfree(
t_command *command
) {
if (command == NULL)
return ;
cmdfree_argv(command->argv);
free(command->path);
free(command);
}
static void cmdfree_argv(
char **argv
) {
size_t i;
if (argv == NULL)
return ;
i = 0;
while (argv[i] != NULL)
{
free(argv[i]);
i++;
}
free(argv);
}
// static void debug_print_command_info(
// t_command *command
// ) {
// size_t i;
// if (command == NULL)
// {
// printf("Command is NULL\n");
// return ;
// }
// printf("Command info:\n");
// printf(" Path: %s\n", command->path);
// printf(" Argc: %d\n", command->argc);
// printf(" Argv:\n");
// for (i = 0; i < (size_t)command->argc; i++)
// printf(" arg[%zu]: %s\n", i, command->argv[i]);
// printf(" Infile FD: %d\n", command->infile);
// printf(" Outfile FD: %d\n", command->outfile);
// printf("--------------------------\n");
// }