Fix readline behaviour on SIGINT
authorLukas Jiriste <ljiriste@student.42prague.com>
Sat, 31 Aug 2024 07:10:24 +0000 (09:10 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Sat, 31 Aug 2024 07:10:24 +0000 (09:10 +0200)
Special signal handler is provided that uses readling functions.
I could not find info on whether the functions used in this handler are
reentrant but hopefully this will work.

src/main.c

index d65381c63fb6b685bff0052432482430aaa66105..3e2f92b759551396c9fbe5c7badc82afb9e58029 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/04/26 13:11:47 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/29 17:17:15 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/31 09:08:57 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include <termios.h>
 #include <unistd.h>
 
+#ifndef NOLEAKS
+# include <stdio.h>                            // readline
+# include <readline/readline.h>        // readline
+# include <readline/history.h> // readline
+#endif // NOLEAKS
+
 volatile sig_atomic_t  g_last_signal;
 
 void   handler(int     sig_num)
@@ -27,42 +33,58 @@ void        handler(int     sig_num)
        return ;
 }
 
-void   setup_signal_hadling(void)
+#ifndef NOLEAKS
+void   rl_handler(int sig_num)
+{
+       if (sig_num != SIGINT)
+               return ;
+       write(1, "\n", 1);
+       rl_on_new_line();
+       rl_replace_line("", 0);
+       rl_redisplay();
+       return ;
+}
+
+void   set_input_handler(void)
 {
        struct sigaction        sa;
 
-       g_last_signal = 0;
        ft_memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = handler;
+       sa.sa_handler = SIG_IGN;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
-       sigaction(SIGINT, &sa, NULL);
-       sa.sa_handler = SIG_IGN;
        sigaction(SIGQUIT, &sa, NULL);
+       sa.sa_handler = rl_handler;
+       sigaction(SIGINT, &sa, NULL);
        return ;
 }
-
-void   catch_sigquit(void)
+#else
+void   set_input_handler(void)
 {
        struct sigaction        sa;
 
        ft_memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = handler;
+       sa.sa_handler = SIG_IGN;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sigaction(SIGQUIT, &sa, NULL);
+       sa.sa_handler = handler;
+       sigaction(SIGINT, &sa, NULL);
        return ;
 }
 
-void   ignore_sigquit(void)
+#endif // NOLEAKS
+
+void   set_execution_handler(void)
 {
        struct sigaction        sa;
 
        ft_memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = SIG_IGN;
+       sa.sa_handler = handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sigaction(SIGQUIT, &sa, NULL);
+       sigaction(SIGINT, &sa, NULL);
        return ;
 }
 
@@ -109,6 +131,7 @@ void        regenerate_terminal(void)
        return ;
 }
 
+#ifdef NOLEAKS
 void   minishell_flush(void)
 {
        struct termios  termios;
@@ -117,6 +140,7 @@ void        minishell_flush(void)
        tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
        return ;
 }
+#endif // NOLEAKS
 
 /*
 // This would be more portable than the main with 3 input args
@@ -131,7 +155,6 @@ int main(int argc, __attribute__((unused)) char **argv, char **envp)
        char            *line;
        t_execution_env env;
 
-       setup_signal_hadling();
        if (argc > 1)
        {
                print_help();
@@ -145,14 +168,14 @@ int       main(int argc, __attribute__((unused)) char **argv, char **envp)
        while (env.exit == 0)
        {
                setup_terminal();
-               ignore_sigquit();
+               set_input_handler();
                line = get_line();
                if (!line)
                {
                        env.ret_val = 0;
                        break ;
                }
-               catch_sigquit();
+               set_execution_handler();
                regenerate_terminal();
                handle_input(&line, &env);
                free(line);