Fixed command exit status and exec bugs, read relative and absolute paths and correctly resolved
This commit is contained in:
@@ -12,12 +12,14 @@
|
|||||||
|
|
||||||
#include "executor.h"
|
#include "executor.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
static bool is_path_explicit(const char *command_name);
|
static bool is_path_explicit(const char *command_name);
|
||||||
static char *resolve_path_from_env(const char *command_name,
|
static char *resolve_path_from_env(const char *command_name,
|
||||||
t_minishell *minishell);
|
t_minishell *minishell);
|
||||||
static char *resolve_command_path(const t_command *command,
|
static char *resolve_command_path(const t_command *command,
|
||||||
t_minishell *minishell);
|
t_minishell *minishell);
|
||||||
|
static uint8_t resolve_execve_status(void);
|
||||||
static inline uint8_t execute_builtin(
|
static inline uint8_t execute_builtin(
|
||||||
const t_command *command,
|
const t_command *command,
|
||||||
t_minishell *minishell
|
t_minishell *minishell
|
||||||
@@ -34,9 +36,11 @@ static void handle_execve_error(
|
|||||||
char **envp
|
char **envp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const uint8_t exit_status = resolve_execve_status();
|
||||||
|
|
||||||
free_envp(envp);
|
free_envp(envp);
|
||||||
perror(command->path);
|
perror(command->path);
|
||||||
exit(EXIT_FAILURE);
|
exit(exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute_external_command(
|
static void execute_external_command(
|
||||||
@@ -112,6 +116,15 @@ static char *resolve_command_path(
|
|||||||
return (command_path);
|
return (command_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t resolve_execve_status(void)
|
||||||
|
{
|
||||||
|
if (errno == ENOENT)
|
||||||
|
return (127);
|
||||||
|
if (errno == EACCES || errno == ENOEXEC || errno == EISDIR)
|
||||||
|
return (126);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t execute_command(
|
static uint8_t execute_command(
|
||||||
t_command *command,
|
t_command *command,
|
||||||
t_minishell *minishell
|
t_minishell *minishell
|
||||||
@@ -188,29 +201,16 @@ static int create_pipe_if_needed(
|
|||||||
|
|
||||||
static bool is_fork_required(
|
static bool is_fork_required(
|
||||||
t_list *current_command,
|
t_list *current_command,
|
||||||
|
const t_pipeline *pipeline,
|
||||||
t_minishell *minishell
|
t_minishell *minishell
|
||||||
) {
|
) {
|
||||||
const t_command *command = current_command->content;
|
const t_command *command = current_command->content;
|
||||||
|
|
||||||
return (current_command->next != NULL
|
return (pipeline->prev_read_fd != -1
|
||||||
|
|| current_command->next != NULL
|
||||||
|| !is_builtin_command(command, minishell));
|
|| !is_builtin_command(command, minishell));
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t fork_process(
|
|
||||||
t_list *current_command,
|
|
||||||
t_minishell *minishell
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
pid = 0;
|
|
||||||
if (is_fork_required(current_command, minishell))
|
|
||||||
pid = fork();
|
|
||||||
if (pid == FORK_ERROR)
|
|
||||||
perror("fork");
|
|
||||||
return (pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup_child_input(
|
static void setup_child_input(
|
||||||
t_pipeline *pipeline
|
t_pipeline *pipeline
|
||||||
)
|
)
|
||||||
@@ -248,7 +248,6 @@ static void child_process(
|
|||||||
setup_child_input(pipeline);
|
setup_child_input(pipeline);
|
||||||
setup_child_output(current_command, pipeline);
|
setup_child_output(current_command, pipeline);
|
||||||
exit_status = execute_command(command, minishell);
|
exit_status = execute_command(command, minishell);
|
||||||
if (is_fork_required(current_command, minishell))
|
|
||||||
exit(exit_status);
|
exit(exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,16 +267,24 @@ static void parent_cleanup(
|
|||||||
pipeline->prev_read_fd = -1;
|
pipeline->prev_read_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t wait_for_children(void)
|
static uint8_t wait_for_children(
|
||||||
|
pid_t last_child_pid
|
||||||
|
)
|
||||||
{
|
{
|
||||||
uint8_t exit_status;
|
uint8_t exit_status;
|
||||||
int status;
|
int status;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
while (wait(&status) > 0)
|
while (last_child_pid > 0 && (pid = wait(&status)) > 0)
|
||||||
|
{
|
||||||
|
if (pid == last_child_pid)
|
||||||
{
|
{
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
exit_status = WEXITSTATUS(status);
|
exit_status = WEXITSTATUS(status);
|
||||||
|
else if (WIFSIGNALED(status))
|
||||||
|
exit_status = 128 + WTERMSIG(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (exit_status);
|
return (exit_status);
|
||||||
}
|
}
|
||||||
@@ -291,22 +298,46 @@ uint8_t execute(
|
|||||||
t_pipeline pipeline;
|
t_pipeline pipeline;
|
||||||
t_list *current_command;
|
t_list *current_command;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
pid_t last_child_pid;
|
||||||
|
t_command *command;
|
||||||
|
bool should_fork;
|
||||||
|
|
||||||
pipeline.prev_read_fd = -1;
|
pipeline.prev_read_fd = -1;
|
||||||
|
exit_status = EXIT_SUCCESS;
|
||||||
|
last_child_pid = -1;
|
||||||
current_command = command_list;
|
current_command = command_list;
|
||||||
while (current_command)
|
while (current_command)
|
||||||
{
|
{
|
||||||
if (create_pipe_if_needed(current_command, &pipeline) == PIPE_ERROR)
|
if (create_pipe_if_needed(current_command, &pipeline) == PIPE_ERROR)
|
||||||
|
{
|
||||||
|
exit_status = EXIT_FAILURE;
|
||||||
break ;
|
break ;
|
||||||
pid = fork_process(current_command, minishell);
|
}
|
||||||
|
should_fork = is_fork_required(current_command, &pipeline, minishell);
|
||||||
|
if (should_fork)
|
||||||
|
{
|
||||||
|
pid = fork();
|
||||||
if (pid == FORK_ERROR)
|
if (pid == FORK_ERROR)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
exit_status = EXIT_FAILURE;
|
||||||
break ;
|
break ;
|
||||||
|
}
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
child_process(current_command, &pipeline, minishell);
|
child_process(current_command, &pipeline, minishell);
|
||||||
|
last_child_pid = pid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command = current_command->content;
|
||||||
|
exit_status = execute_command(command, minishell);
|
||||||
|
}
|
||||||
parent_cleanup(current_command, &pipeline);
|
parent_cleanup(current_command, &pipeline);
|
||||||
current_command = current_command->next;
|
current_command = current_command->next;
|
||||||
}
|
}
|
||||||
exit_status = wait_for_children();
|
if (last_child_pid > 0)
|
||||||
|
exit_status = wait_for_children(last_child_pid);
|
||||||
|
minishell->exit_status = exit_status;
|
||||||
ft_lstclear(&command_list, (void (*)(void *))cmdfree);
|
ft_lstclear(&command_list, (void (*)(void *))cmdfree);
|
||||||
return (exit_status);
|
return (exit_status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void minishell_run(
|
|||||||
{
|
{
|
||||||
add_history(line);
|
add_history(line);
|
||||||
commands = parse(line, minishell);
|
commands = parse(line, minishell);
|
||||||
execute(commands, minishell);
|
minishell->exit_status = execute(commands, minishell);
|
||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user