feat: Added signals
Added functionality of the signals ctrl+d, ctrl+c and ctr+\
This commit is contained in:
@@ -34,8 +34,8 @@ typedef enum e_token_type
|
||||
typedef struct s_token
|
||||
{
|
||||
t_token_type type;
|
||||
char *value;
|
||||
} t_token;
|
||||
char *value;
|
||||
} t_token;
|
||||
|
||||
typedef enum e_redirection_type
|
||||
{
|
||||
@@ -49,7 +49,7 @@ typedef struct s_redirection
|
||||
{
|
||||
t_token_type type;
|
||||
char *target;
|
||||
} t_redirection;
|
||||
} t_redirection;
|
||||
|
||||
/**
|
||||
* @brief Structure that holds both environment and internal variables
|
||||
@@ -123,6 +123,14 @@ extern void minishell_run(t_minishell *minishell);
|
||||
|
||||
extern void minishell_clear(t_minishell *minishell);
|
||||
|
||||
extern void minishell_set_interactive_signals(void);
|
||||
|
||||
extern void minishell_set_execution_signals(void);
|
||||
|
||||
extern void minishell_set_child_signals(void);
|
||||
|
||||
extern bool minishell_consume_sigint(void);
|
||||
|
||||
/* environment.c */
|
||||
|
||||
extern void set_envp(char **envp, t_minishell *msh);
|
||||
|
||||
66
src/core/signals.c
Normal file
66
src/core/signals.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* signals.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/13 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/13 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static int g_signal = 0;
|
||||
|
||||
static void sigint_handler(int signal)
|
||||
{
|
||||
g_signal = signal;
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
rl_on_new_line();
|
||||
rl_replace_line("", 0);
|
||||
rl_redisplay();
|
||||
}
|
||||
|
||||
void minishell_set_interactive_signals(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
ft_bzero(&action, sizeof(action));
|
||||
action.sa_handler = sigint_handler;
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
action.sa_handler = SIG_IGN;
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
}
|
||||
|
||||
void minishell_set_execution_signals(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
ft_bzero(&action, sizeof(action));
|
||||
action.sa_handler = SIG_IGN;
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
}
|
||||
|
||||
void minishell_set_child_signals(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
ft_bzero(&action, sizeof(action));
|
||||
action.sa_handler = SIG_DFL;
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
}
|
||||
|
||||
bool minishell_consume_sigint(void)
|
||||
{
|
||||
if (g_signal != SIGINT)
|
||||
return (false);
|
||||
g_signal = 0;
|
||||
return (true);
|
||||
}
|
||||
54
src/executor/command_free.c
Normal file
54
src/executor/command_free.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* command_free.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/13 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/13 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
|
||||
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 cmdfree_redirection(
|
||||
t_redirection *redirection
|
||||
)
|
||||
{
|
||||
if (redirection == NULL)
|
||||
return ;
|
||||
free(redirection->target);
|
||||
free(redirection);
|
||||
}
|
||||
|
||||
void executor_cmdfree(
|
||||
t_command *command
|
||||
)
|
||||
{
|
||||
if (command == NULL)
|
||||
return ;
|
||||
cmdfree_argv(command->argv);
|
||||
free(command->path);
|
||||
ft_lstclear(&command->redirections,
|
||||
(void (*)(void *))cmdfree_redirection);
|
||||
ft_lstclear(&command->heredocs, (void (*)(void *))cmdfree_redirection);
|
||||
free(command);
|
||||
}
|
||||
@@ -40,15 +40,29 @@ static bool fork_current_command(
|
||||
return (true);
|
||||
}
|
||||
|
||||
static void run_command_in_parent(
|
||||
t_exec_state *state,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
t_command *command;
|
||||
int saved_stdin;
|
||||
int saved_stdout;
|
||||
|
||||
command = state->current_command->content;
|
||||
if (!executor_apply_redirections(command, &saved_stdin, &saved_stdout))
|
||||
state->exit_status = EXIT_FAILURE;
|
||||
else
|
||||
state->exit_status = executor_execute_command(command, minishell);
|
||||
executor_restore_redirections(saved_stdin, saved_stdout);
|
||||
}
|
||||
|
||||
static bool run_current_command(
|
||||
t_exec_state *state,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
bool should_fork;
|
||||
t_command *command;
|
||||
int saved_stdin;
|
||||
int saved_stdout;
|
||||
|
||||
if (executor_create_pipe_if_needed(state->current_command,
|
||||
&state->pipeline) == PIPE_ERROR)
|
||||
@@ -61,14 +75,7 @@ static bool run_current_command(
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
command = state->current_command->content;
|
||||
if (!executor_apply_redirections(command, &saved_stdin, &saved_stdout))
|
||||
state->exit_status = EXIT_FAILURE;
|
||||
else
|
||||
state->exit_status = executor_execute_command(command, minishell);
|
||||
executor_restore_redirections(saved_stdin, saved_stdout);
|
||||
}
|
||||
run_command_in_parent(state, minishell);
|
||||
executor_parent_cleanup(state->current_command, &state->pipeline);
|
||||
state->current_command = state->current_command->next;
|
||||
return (true);
|
||||
@@ -82,6 +89,7 @@ uint8_t execute(
|
||||
t_exec_state state;
|
||||
|
||||
init_exec_state(&state, command_list);
|
||||
minishell_set_execution_signals();
|
||||
while (state.current_command)
|
||||
{
|
||||
if (!run_current_command(&state, minishell))
|
||||
@@ -89,6 +97,7 @@ uint8_t execute(
|
||||
}
|
||||
if (state.last_child_pid > 0)
|
||||
state.exit_status = executor_wait_for_children(state.last_child_pid);
|
||||
minishell_set_interactive_signals();
|
||||
minishell->exit_status = state.exit_status;
|
||||
ft_lstclear(&command_list, (void (*)(void *))executor_cmdfree);
|
||||
return (state.exit_status);
|
||||
|
||||
@@ -12,6 +12,34 @@
|
||||
|
||||
#include "executor.h"
|
||||
|
||||
static void set_signal_exit_status(
|
||||
int status,
|
||||
uint8_t *exit_status
|
||||
)
|
||||
{
|
||||
if (WTERMSIG(status) == SIGINT)
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
else if (WTERMSIG(status) == SIGQUIT)
|
||||
{
|
||||
if (WCOREDUMP(status))
|
||||
write(STDERR_FILENO, "Quit (core dumped)\n", 19);
|
||||
else
|
||||
write(STDERR_FILENO, "Quit\n", 5);
|
||||
}
|
||||
*exit_status = 128 + WTERMSIG(status);
|
||||
}
|
||||
|
||||
static void set_last_child_status(
|
||||
int status,
|
||||
uint8_t *exit_status
|
||||
)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
*exit_status = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
set_signal_exit_status(status, exit_status);
|
||||
}
|
||||
|
||||
void executor_child_process(
|
||||
t_list *current_command,
|
||||
t_pipeline *pipeline,
|
||||
@@ -22,6 +50,7 @@ void executor_child_process(
|
||||
t_command *command;
|
||||
|
||||
command = current_command->content;
|
||||
minishell_set_child_signals();
|
||||
executor_setup_child_input(pipeline);
|
||||
executor_setup_child_output(current_command, pipeline);
|
||||
if (!executor_apply_redirections(command, NULL, NULL))
|
||||
@@ -59,54 +88,8 @@ uint8_t executor_wait_for_children(
|
||||
while (last_child_pid > 0 && pid > 0)
|
||||
{
|
||||
if (pid == last_child_pid)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
exit_status = 128 + WTERMSIG(status);
|
||||
}
|
||||
set_last_child_status(status, &exit_status);
|
||||
pid = wait(&status);
|
||||
}
|
||||
return (exit_status);
|
||||
}
|
||||
|
||||
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 cmdfree_redirection(
|
||||
t_redirection *redirection
|
||||
)
|
||||
{
|
||||
if (redirection == NULL)
|
||||
return ;
|
||||
free(redirection->target);
|
||||
free(redirection);
|
||||
}
|
||||
|
||||
void executor_cmdfree(
|
||||
t_command *command
|
||||
)
|
||||
{
|
||||
if (command == NULL)
|
||||
return ;
|
||||
cmdfree_argv(command->argv);
|
||||
free(command->path);
|
||||
ft_lstclear(&command->redirections,
|
||||
(void (*)(void *))cmdfree_redirection);
|
||||
ft_lstclear(&command->heredocs, (void (*)(void *))cmdfree_redirection);
|
||||
free(command);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,28 @@
|
||||
#include "parser.h"
|
||||
#include "executor.h"
|
||||
|
||||
static void handle_sigint_status(
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
if (!minishell_consume_sigint())
|
||||
return ;
|
||||
minishell->exit_status = 130;
|
||||
}
|
||||
|
||||
static bool handle_eof(
|
||||
char *line,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
if (line != NULL)
|
||||
return (false);
|
||||
if (isatty(STDIN_FILENO))
|
||||
ft_putendl("exit");
|
||||
minishell->exit = true;
|
||||
return (true);
|
||||
}
|
||||
|
||||
void minishell_init(
|
||||
t_minishell *minishell,
|
||||
char **envp
|
||||
@@ -33,23 +55,21 @@ void minishell_run(
|
||||
t_list *commands;
|
||||
|
||||
if (minishell == NULL)
|
||||
{
|
||||
minishell->exit_status = EXIT_FAILURE;
|
||||
return ;
|
||||
}
|
||||
minishell_set_interactive_signals();
|
||||
while (!minishell->exit)
|
||||
{
|
||||
line = readline(DEFAULT_PS1);
|
||||
if (line != NULL)
|
||||
handle_sigint_status(minishell);
|
||||
if (handle_eof(line, minishell))
|
||||
continue ;
|
||||
if (*line != '\0')
|
||||
{
|
||||
if (*line != '\0')
|
||||
{
|
||||
add_history(line);
|
||||
commands = parse(line, minishell);
|
||||
minishell->exit_status = execute(commands, minishell);
|
||||
}
|
||||
free(line);
|
||||
add_history(line);
|
||||
commands = parse(line, minishell);
|
||||
minishell->exit_status = execute(commands, minishell);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user