From c166d0f77a64691ae9ac0a334b4833b7667b63f4 Mon Sep 17 00:00:00 2001 From: marcnava-42cursus Date: Fri, 13 Feb 2026 18:08:45 +0100 Subject: [PATCH] feat: Added signals Added functionality of the signals ctrl+d, ctrl+c and ctr+\ --- include/core.h | 14 +++++-- src/core/signals.c | 66 +++++++++++++++++++++++++++++ src/executor/command_free.c | 54 ++++++++++++++++++++++++ src/executor/executor.c | 31 +++++++++----- src/executor/process_helpers.c | 77 +++++++++++++--------------------- src/minishell.c | 42 ++++++++++++++----- 6 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 src/core/signals.c create mode 100644 src/executor/command_free.c diff --git a/include/core.h b/include/core.h index dddc0fb..52cbbc9 100644 --- a/include/core.h +++ b/include/core.h @@ -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); diff --git a/src/core/signals.c b/src/core/signals.c new file mode 100644 index 0000000..03dcb16 --- /dev/null +++ b/src/core/signals.c @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* signals.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san 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); +} diff --git a/src/executor/executor.c b/src/executor/executor.c index 645b106..c93d325 100644 --- a/src/executor/executor.c +++ b/src/executor/executor.c @@ -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); diff --git a/src/executor/process_helpers.c b/src/executor/process_helpers.c index e34fc1e..1a4fca2 100644 --- a/src/executor/process_helpers.c +++ b/src/executor/process_helpers.c @@ -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); -} diff --git a/src/minishell.c b/src/minishell.c index 387d24a..5040e24 100644 --- a/src/minishell.c +++ b/src/minishell.c @@ -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); } }