feat: Added signals
Added functionality of the signals ctrl+d, ctrl+c and ctr+\
This commit is contained in:
@@ -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
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);
|
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);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user