256 lines
6.3 KiB
C
256 lines
6.3 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* executor.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2025/10/28 13:03:44 by sede-san #+# #+# */
|
|
/* Updated: 2026/02/08 03:42:11 by sede-san ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "executor.h"
|
|
#include "builtins.h"
|
|
#include <errno.h>
|
|
|
|
static inline bool can_execute_command(t_command *command, t_minishell *minishell);
|
|
static inline bool command_exists(t_command *command, t_minishell *minishell);
|
|
static u_int8_t execute_command(t_command *command, t_minishell *minishell);
|
|
static u_int8_t execute_command(t_command *command, t_minishell *minishell);
|
|
// static inline bool is_piped(t_command *command);
|
|
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;
|
|
pid_t pid;
|
|
u_int8_t exit_status;
|
|
int child_exit_status;
|
|
|
|
prev_read_fd = -1;
|
|
exit_status = EXIT_SUCCESS;
|
|
current_command = command_list;
|
|
while (current_command != NULL)
|
|
{
|
|
t_command *command = (t_command *)current_command->content;
|
|
int pipefd[2];
|
|
|
|
/* Create pipe ONLY if there is a next command */
|
|
if (current_command->next)
|
|
{
|
|
if (pipe(pipefd) == -1)
|
|
{
|
|
perror("pipe");
|
|
exit_status = EXIT_FAILURE;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// create fork
|
|
pid = 0;
|
|
if (current_command->next != NULL
|
|
|| !is_builtin(command->path, minishell))
|
|
pid = fork();
|
|
// handle fork error
|
|
if (pid == -1)
|
|
{
|
|
perror("fork");
|
|
return (EXIT_FAILURE);
|
|
}
|
|
|
|
// handle child process
|
|
if (pid == CHILD_PID)
|
|
{
|
|
/* If we have input from previous pipe */
|
|
if (prev_read_fd != -1)
|
|
{
|
|
dup2(prev_read_fd, STDIN_FILENO);
|
|
close(prev_read_fd);
|
|
}
|
|
/* If we pipe output to next command */
|
|
if (current_command->next)
|
|
{
|
|
dup2(pipefd[WRITE_PIPE], STDOUT_FILENO);
|
|
close(pipefd[READ_PIPE]);
|
|
close(pipefd[WRITE_PIPE]);
|
|
}
|
|
execute_command(command, minishell); // child process exits here
|
|
}
|
|
|
|
// handle parent process
|
|
waitpid(pid, &child_exit_status, 0); // wait for child to finish
|
|
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;
|
|
|
|
// continue executing
|
|
current_command = current_command->next;
|
|
}
|
|
ft_lstclear(&command_list, (void (*)(void *))cmdfree);
|
|
exit_status = child_exit_status;
|
|
return (exit_status);
|
|
}
|
|
|
|
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 u_int8_t execute_command(
|
|
t_command *command,
|
|
t_minishell *minishell
|
|
)
|
|
{
|
|
char **envp;
|
|
t_builtin_func builtin;
|
|
|
|
if (is_builtin(command->path, minishell))
|
|
{
|
|
builtin = ft_hashmap_get(minishell->builtins, command->path);
|
|
return (builtin(*command, minishell));
|
|
}
|
|
envp = get_envp(minishell);
|
|
execve(command->path, command->argv, envp);
|
|
// handle error if execve fails
|
|
perror("execve");
|
|
free_envp(envp);
|
|
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");
|
|
// }
|