feat: Added signals

Added functionality of the signals ctrl+d, ctrl+c and ctr+\
This commit is contained in:
marcnava-42cursus
2026-02-13 18:08:45 +01:00
parent 3e31447073
commit c166d0f77a
6 changed files with 212 additions and 72 deletions

View File

@@ -123,6 +123,14 @@ extern void minishell_run(t_minishell *minishell);
extern void minishell_clear(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 */ /* environment.c */
extern void set_envp(char **envp, t_minishell *msh); extern void set_envp(char **envp, t_minishell *msh);

66
src/core/signals.c Normal file
View 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);
}

View 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);
}

View File

@@ -40,15 +40,29 @@ static bool fork_current_command(
return (true); 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( static bool run_current_command(
t_exec_state *state, t_exec_state *state,
t_minishell *minishell t_minishell *minishell
) )
{ {
bool should_fork; bool should_fork;
t_command *command;
int saved_stdin;
int saved_stdout;
if (executor_create_pipe_if_needed(state->current_command, if (executor_create_pipe_if_needed(state->current_command,
&state->pipeline) == PIPE_ERROR) &state->pipeline) == PIPE_ERROR)
@@ -61,14 +75,7 @@ static bool run_current_command(
return (false); return (false);
} }
else else
{ run_command_in_parent(state, minishell);
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);
}
executor_parent_cleanup(state->current_command, &state->pipeline); executor_parent_cleanup(state->current_command, &state->pipeline);
state->current_command = state->current_command->next; state->current_command = state->current_command->next;
return (true); return (true);
@@ -82,6 +89,7 @@ uint8_t execute(
t_exec_state state; t_exec_state state;
init_exec_state(&state, command_list); init_exec_state(&state, command_list);
minishell_set_execution_signals();
while (state.current_command) while (state.current_command)
{ {
if (!run_current_command(&state, minishell)) if (!run_current_command(&state, minishell))
@@ -89,6 +97,7 @@ uint8_t execute(
} }
if (state.last_child_pid > 0) if (state.last_child_pid > 0)
state.exit_status = executor_wait_for_children(state.last_child_pid); state.exit_status = executor_wait_for_children(state.last_child_pid);
minishell_set_interactive_signals();
minishell->exit_status = state.exit_status; minishell->exit_status = state.exit_status;
ft_lstclear(&command_list, (void (*)(void *))executor_cmdfree); ft_lstclear(&command_list, (void (*)(void *))executor_cmdfree);
return (state.exit_status); return (state.exit_status);

View File

@@ -12,6 +12,34 @@
#include "executor.h" #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( void executor_child_process(
t_list *current_command, t_list *current_command,
t_pipeline *pipeline, t_pipeline *pipeline,
@@ -22,6 +50,7 @@ void executor_child_process(
t_command *command; t_command *command;
command = current_command->content; command = current_command->content;
minishell_set_child_signals();
executor_setup_child_input(pipeline); executor_setup_child_input(pipeline);
executor_setup_child_output(current_command, pipeline); executor_setup_child_output(current_command, pipeline);
if (!executor_apply_redirections(command, NULL, NULL)) if (!executor_apply_redirections(command, NULL, NULL))
@@ -59,54 +88,8 @@ uint8_t executor_wait_for_children(
while (last_child_pid > 0 && pid > 0) while (last_child_pid > 0 && pid > 0)
{ {
if (pid == last_child_pid) if (pid == last_child_pid)
{ set_last_child_status(status, &exit_status);
if (WIFEXITED(status))
exit_status = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
exit_status = 128 + WTERMSIG(status);
}
pid = wait(&status); pid = wait(&status);
} }
return (exit_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);
}

View File

@@ -15,6 +15,28 @@
#include "parser.h" #include "parser.h"
#include "executor.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( void minishell_init(
t_minishell *minishell, t_minishell *minishell,
char **envp char **envp
@@ -33,15 +55,14 @@ void minishell_run(
t_list *commands; t_list *commands;
if (minishell == NULL) if (minishell == NULL)
{
minishell->exit_status = EXIT_FAILURE;
return ; return ;
} minishell_set_interactive_signals();
while (!minishell->exit) while (!minishell->exit)
{ {
line = readline(DEFAULT_PS1); 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); add_history(line);
@@ -50,7 +71,6 @@ void minishell_run(
} }
free(line); free(line);
} }
}
} }
void minishell_clear( void minishell_clear(