X-Git-Url: http://git.madism.org/?a=blobdiff_plain;ds=sidebyside;f=lib-sys%2Fmutt_signal.c;fp=lib-sys%2Fmutt_signal.c;h=159612b8162babf5b84bcb5f141698a958b7438e;hb=dbacadf0ce81052365d7a43373ac7d4ac67ff91e;hp=0000000000000000000000000000000000000000;hpb=d04295aaf918032c1c2fafc94ddf637cf23341e9;p=apps%2Fmadmutt.git diff --git a/lib-sys/mutt_signal.c b/lib-sys/mutt_signal.c new file mode 100644 index 0000000..159612b --- /dev/null +++ b/lib-sys/mutt_signal.c @@ -0,0 +1,240 @@ +/* + * Copyright notice from original mutt: + * Copyright (C) 1996-2000 Michael R. Elkins + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include + +#include "mutt_signal.h" + +static sigset_t Sigset; +static sigset_t SigsetSys; +static struct sigaction SysOldInt; +static struct sigaction SysOldQuit; +static int IsEndwin = 0; + +/* Attempt to catch "ordinary" signals and shut down gracefully. */ +RETSIGTYPE exit_handler (int sig) +{ + curs_set (1); + endwin (); /* just to be safe */ +#ifdef SYS_SIGLIST_DECLARED + printf (_("%s... Exiting.\n"), sys_siglist[sig]); +#else +#if defined(__sun__) && defined(__svr4__) + printf (_("Caught %s... Exiting.\n"), _sys_siglist[sig]); +#else +#if defined(__alpha) && defined(__osf__) + printf (_("Caught %s... Exiting.\n"), __sys_siglist[sig]); +#else + printf (_("Caught signal %d... Exiting.\n"), sig); +#endif +#endif +#endif + exit (0); +} + +RETSIGTYPE chld_handler(int sig __attribute__((unused))) +{ + /* empty */ +} + +RETSIGTYPE sighandler (int sig) +{ + int save_errno = errno; + + switch (sig) { + case SIGTSTP: /* user requested a suspend */ + if (!option (OPTSUSPEND)) + break; + IsEndwin = isendwin (); + curs_set (1); + if (!IsEndwin) + endwin (); + kill (0, SIGSTOP); + + case SIGCONT: + if (!IsEndwin) + refresh (); + mutt_curs_set (-1); +#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) + /* We don't receive SIGWINCH when suspended; however, no harm is done by + * just assuming we received one, and triggering the 'resize' anyway. */ + SigWinch = 1; +#endif + break; + +#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) + case SIGWINCH: + SigWinch = 1; + break; +#endif + + case SIGINT: + SigInt = 1; + break; + + } + errno = save_errno; +} + +#ifdef USE_SLANG_CURSES +int mutt_intr_hook (void) +{ + return (-1); +} +#endif /* USE_SLANG_CURSES */ + +void mutt_signal_initialize (void) +{ + struct sigaction act; + + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &act, NULL); + + act.sa_handler = exit_handler; + sigaction (SIGTERM, &act, NULL); + sigaction (SIGHUP, &act, NULL); + sigaction (SIGQUIT, &act, NULL); + + /* we want to avoid race conditions */ + sigaddset (&act.sa_mask, SIGTSTP); + + act.sa_handler = sighandler; + + /* we want SIGALRM to abort the current syscall, so we do this before + * setting the SA_RESTART flag below. currently this is only used to + * timeout on a connect() call in a reasonable amout of time. + */ + sigaction (SIGALRM, &act, NULL); + + /* we also don't want to mess with interrupted system calls */ +#ifdef SA_RESTART + act.sa_flags = SA_RESTART; +#endif + + sigaction (SIGCONT, &act, NULL); + sigaction (SIGTSTP, &act, NULL); + sigaction (SIGINT, &act, NULL); +#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) + sigaction (SIGWINCH, &act, NULL); +#endif + + /* POSIX doesn't allow us to ignore SIGCHLD, + * so we just install a dummy handler for it + */ + act.sa_handler = chld_handler; + /* don't need to block any other signals here */ + sigemptyset (&act.sa_mask); + /* we don't want to mess with stopped children */ + act.sa_flags |= SA_NOCLDSTOP; + sigaction (SIGCHLD, &act, NULL); + +#ifdef USE_SLANG_CURSES + /* This bit of code is required because of the implementation of + * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we + * are in blocking mode, SLsys_getkey() will not return an error unless + * a handler function is defined and it returns -1. This is needed so + * that if the user resizes the screen while at a prompt, it will just + * abort and go back to the main-menu. + */ + SLang_getkey_intr_hook = mutt_intr_hook; +#endif +} + +/* signals which are important to block while doing critical ops */ +void mutt_block_signals (void) +{ + if (!option (OPTSIGNALSBLOCKED)) { + sigemptyset (&Sigset); + sigaddset (&Sigset, SIGTERM); + sigaddset (&Sigset, SIGHUP); + sigaddset (&Sigset, SIGTSTP); + sigaddset (&Sigset, SIGINT); +#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) + sigaddset (&Sigset, SIGWINCH); +#endif + sigprocmask (SIG_BLOCK, &Sigset, 0); + set_option (OPTSIGNALSBLOCKED); + } +} + +/* restore the previous signal mask */ +void mutt_unblock_signals (void) +{ + if (option (OPTSIGNALSBLOCKED)) { + sigprocmask (SIG_UNBLOCK, &Sigset, 0); + unset_option (OPTSIGNALSBLOCKED); + } +} + +void mutt_block_signals_system (void) +{ + struct sigaction sa; + + if (!option (OPTSYSSIGNALSBLOCKED)) { + /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */ + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + sigaction (SIGINT, &sa, &SysOldInt); + sigaction (SIGQUIT, &sa, &SysOldQuit); + + sigemptyset (&SigsetSys); + sigaddset (&SigsetSys, SIGCHLD); + sigprocmask (SIG_BLOCK, &SigsetSys, 0); + set_option (OPTSYSSIGNALSBLOCKED); + } +} + +void mutt_unblock_signals_system (int catch) +{ + if (option (OPTSYSSIGNALSBLOCKED)) { + sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL); + if (catch) { + sigaction (SIGQUIT, &SysOldQuit, NULL); + sigaction (SIGINT, &SysOldInt, NULL); + } + else { + struct sigaction sa; + + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGQUIT, &sa, NULL); + sigaction (SIGINT, &sa, NULL); + } + + unset_option (OPTSYSSIGNALSBLOCKED); + } +} + +void mutt_allow_interrupt (int disposition) +{ + struct sigaction sa; + + p_clear(&sa, 1); + sa.sa_handler = sighandler; +#ifdef SA_RESTART + if (disposition == 0) + sa.sa_flags |= SA_RESTART; +#endif + sigaction (SIGINT, &sa, NULL); +}