2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
5 * This file is part of mutt-ng, see http://www.muttng.org/.
6 * It's licensed under the GNU General Public License,
7 * please see the file GPL in the top level source directory.
19 #include <lib-lib/macros.h>
21 #include <lib-ui/curses.h>
23 #include "mutt_signal.h"
25 static sigset_t Sigset;
26 static sigset_t SigsetSys;
27 static struct sigaction SysOldInt;
28 static struct sigaction SysOldQuit;
29 static int IsEndwin = 0;
31 /* Attempt to catch "ordinary" signals and shut down gracefully. */
32 RETSIGTYPE exit_handler (int sig)
35 endwin (); /* just to be safe */
36 #ifdef SYS_SIGLIST_DECLARED
37 printf (_("%s... Exiting.\n"), sys_siglist[sig]);
39 #if defined(__sun__) && defined(__svr4__)
40 printf (_("Caught %s... Exiting.\n"), _sys_siglist[sig]);
42 #if defined(__alpha) && defined(__osf__)
43 printf (_("Caught %s... Exiting.\n"), __sys_siglist[sig]);
45 printf (_("Caught signal %d... Exiting.\n"), sig);
52 RETSIGTYPE chld_handler(int sig __attribute__((unused)))
57 RETSIGTYPE sighandler (int sig)
59 int save_errno = errno;
62 case SIGTSTP: /* user requested a suspend */
63 if (!option (OPTSUSPEND))
65 IsEndwin = isendwin ();
75 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
76 /* We don't receive SIGWINCH when suspended; however, no harm is done by
77 * just assuming we received one, and triggering the 'resize' anyway. */
82 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
96 #ifdef USE_SLANG_CURSES
97 int mutt_intr_hook (void)
101 #endif /* USE_SLANG_CURSES */
103 void mutt_signal_initialize (void)
105 struct sigaction act;
107 sigemptyset (&act.sa_mask);
109 act.sa_handler = SIG_IGN;
110 sigaction (SIGPIPE, &act, NULL);
112 act.sa_handler = exit_handler;
113 sigaction (SIGTERM, &act, NULL);
114 sigaction (SIGHUP, &act, NULL);
115 sigaction (SIGQUIT, &act, NULL);
117 /* we want to avoid race conditions */
118 sigaddset (&act.sa_mask, SIGTSTP);
120 act.sa_handler = sighandler;
122 /* we want SIGALRM to abort the current syscall, so we do this before
123 * setting the SA_RESTART flag below. currently this is only used to
124 * timeout on a connect() call in a reasonable amout of time.
126 sigaction (SIGALRM, &act, NULL);
128 /* we also don't want to mess with interrupted system calls */
130 act.sa_flags = SA_RESTART;
133 sigaction (SIGCONT, &act, NULL);
134 sigaction (SIGTSTP, &act, NULL);
135 sigaction (SIGINT, &act, NULL);
136 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
137 sigaction (SIGWINCH, &act, NULL);
140 /* POSIX doesn't allow us to ignore SIGCHLD,
141 * so we just install a dummy handler for it
143 act.sa_handler = chld_handler;
144 /* don't need to block any other signals here */
145 sigemptyset (&act.sa_mask);
146 /* we don't want to mess with stopped children */
147 act.sa_flags |= SA_NOCLDSTOP;
148 sigaction (SIGCHLD, &act, NULL);
150 #ifdef USE_SLANG_CURSES
151 /* This bit of code is required because of the implementation of
152 * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
153 * are in blocking mode, SLsys_getkey() will not return an error unless
154 * a handler function is defined and it returns -1. This is needed so
155 * that if the user resizes the screen while at a prompt, it will just
156 * abort and go back to the main-menu.
158 SLang_getkey_intr_hook = mutt_intr_hook;
162 /* signals which are important to block while doing critical ops */
163 void mutt_block_signals (void)
165 if (!option (OPTSIGNALSBLOCKED)) {
166 sigemptyset (&Sigset);
167 sigaddset (&Sigset, SIGTERM);
168 sigaddset (&Sigset, SIGHUP);
169 sigaddset (&Sigset, SIGTSTP);
170 sigaddset (&Sigset, SIGINT);
171 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
172 sigaddset (&Sigset, SIGWINCH);
174 sigprocmask (SIG_BLOCK, &Sigset, 0);
175 set_option (OPTSIGNALSBLOCKED);
179 /* restore the previous signal mask */
180 void mutt_unblock_signals (void)
182 if (option (OPTSIGNALSBLOCKED)) {
183 sigprocmask (SIG_UNBLOCK, &Sigset, 0);
184 unset_option (OPTSIGNALSBLOCKED);
188 void mutt_block_signals_system (void)
192 if (!option (OPTSYSSIGNALSBLOCKED)) {
193 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
194 sa.sa_handler = SIG_IGN;
196 sigemptyset (&sa.sa_mask);
197 sigaction (SIGINT, &sa, &SysOldInt);
198 sigaction (SIGQUIT, &sa, &SysOldQuit);
200 sigemptyset (&SigsetSys);
201 sigaddset (&SigsetSys, SIGCHLD);
202 sigprocmask (SIG_BLOCK, &SigsetSys, 0);
203 set_option (OPTSYSSIGNALSBLOCKED);
207 void mutt_unblock_signals_system (int catch)
209 if (option (OPTSYSSIGNALSBLOCKED)) {
210 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
212 sigaction (SIGQUIT, &SysOldQuit, NULL);
213 sigaction (SIGINT, &SysOldInt, NULL);
218 sa.sa_handler = SIG_DFL;
219 sigemptyset (&sa.sa_mask);
221 sigaction (SIGQUIT, &sa, NULL);
222 sigaction (SIGINT, &sa, NULL);
225 unset_option (OPTSYSSIGNALSBLOCKED);
229 void mutt_allow_interrupt (int disposition)
234 sa.sa_handler = sighandler;
236 if (disposition == 0)
237 sa.sa_flags |= SA_RESTART;
239 sigaction (SIGINT, &sa, NULL);