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.
15 #include "mutt_curses.h"
22 static sigset_t Sigset;
23 static sigset_t SigsetSys;
24 static struct sigaction SysOldInt;
25 static struct sigaction SysOldQuit;
26 static int IsEndwin = 0;
28 /* Attempt to catch "ordinary" signals and shut down gracefully. */
29 RETSIGTYPE exit_handler (int sig)
32 endwin (); /* just to be safe */
33 #if SYS_SIGLIST_DECLARED
34 printf (_("%s... Exiting.\n"), sys_siglist[sig]);
36 #if (__sun__ && __svr4__)
37 printf (_("Caught %s... Exiting.\n"), _sys_siglist[sig]);
39 #if (__alpha && __osf__)
40 printf (_("Caught %s... Exiting.\n"), __sys_siglist[sig]);
42 printf (_("Caught signal %d... Exiting.\n"), sig);
49 RETSIGTYPE chld_handler (int sig)
54 RETSIGTYPE sighandler (int sig)
56 int save_errno = errno;
59 case SIGTSTP: /* user requested a suspend */
60 if (!option (OPTSUSPEND))
62 IsEndwin = isendwin ();
72 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
73 /* We don't receive SIGWINCH when suspended; however, no harm is done by
74 * just assuming we received one, and triggering the 'resize' anyway. */
79 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
93 #ifdef USE_SLANG_CURSES
94 int mutt_intr_hook (void)
98 #endif /* USE_SLANG_CURSES */
100 void mutt_signal_init (void)
102 struct sigaction act;
104 sigemptyset (&act.sa_mask);
106 act.sa_handler = SIG_IGN;
107 sigaction (SIGPIPE, &act, NULL);
109 act.sa_handler = exit_handler;
110 sigaction (SIGTERM, &act, NULL);
111 sigaction (SIGHUP, &act, NULL);
112 sigaction (SIGQUIT, &act, NULL);
114 /* we want to avoid race conditions */
115 sigaddset (&act.sa_mask, SIGTSTP);
117 act.sa_handler = sighandler;
119 /* we want SIGALRM to abort the current syscall, so we do this before
120 * setting the SA_RESTART flag below. currently this is only used to
121 * timeout on a connect() call in a reasonable amout of time.
123 sigaction (SIGALRM, &act, NULL);
125 /* we also don't want to mess with interrupted system calls */
127 act.sa_flags = SA_RESTART;
130 sigaction (SIGCONT, &act, NULL);
131 sigaction (SIGTSTP, &act, NULL);
132 sigaction (SIGINT, &act, NULL);
133 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
134 sigaction (SIGWINCH, &act, NULL);
137 /* POSIX doesn't allow us to ignore SIGCHLD,
138 * so we just install a dummy handler for it
140 act.sa_handler = chld_handler;
141 /* don't need to block any other signals here */
142 sigemptyset (&act.sa_mask);
143 /* we don't want to mess with stopped children */
144 act.sa_flags |= SA_NOCLDSTOP;
145 sigaction (SIGCHLD, &act, NULL);
147 #ifdef USE_SLANG_CURSES
148 /* This bit of code is required because of the implementation of
149 * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
150 * are in blocking mode, SLsys_getkey() will not return an error unless
151 * a handler function is defined and it returns -1. This is needed so
152 * that if the user resizes the screen while at a prompt, it will just
153 * abort and go back to the main-menu.
155 SLang_getkey_intr_hook = mutt_intr_hook;
159 /* signals which are important to block while doing critical ops */
160 void mutt_block_signals (void)
162 if (!option (OPTSIGNALSBLOCKED)) {
163 sigemptyset (&Sigset);
164 sigaddset (&Sigset, SIGTERM);
165 sigaddset (&Sigset, SIGHUP);
166 sigaddset (&Sigset, SIGTSTP);
167 sigaddset (&Sigset, SIGINT);
168 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
169 sigaddset (&Sigset, SIGWINCH);
171 sigprocmask (SIG_BLOCK, &Sigset, 0);
172 set_option (OPTSIGNALSBLOCKED);
176 /* restore the previous signal mask */
177 void mutt_unblock_signals (void)
179 if (option (OPTSIGNALSBLOCKED)) {
180 sigprocmask (SIG_UNBLOCK, &Sigset, 0);
181 unset_option (OPTSIGNALSBLOCKED);
185 void mutt_block_signals_system (void)
189 if (!option (OPTSYSSIGNALSBLOCKED)) {
190 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
191 sa.sa_handler = SIG_IGN;
193 sigemptyset (&sa.sa_mask);
194 sigaction (SIGINT, &sa, &SysOldInt);
195 sigaction (SIGQUIT, &sa, &SysOldQuit);
197 sigemptyset (&SigsetSys);
198 sigaddset (&SigsetSys, SIGCHLD);
199 sigprocmask (SIG_BLOCK, &SigsetSys, 0);
200 set_option (OPTSYSSIGNALSBLOCKED);
204 void mutt_unblock_signals_system (int catch)
206 if (option (OPTSYSSIGNALSBLOCKED)) {
207 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
209 sigaction (SIGQUIT, &SysOldQuit, NULL);
210 sigaction (SIGINT, &SysOldInt, NULL);
215 sa.sa_handler = SIG_DFL;
216 sigemptyset (&sa.sa_mask);
218 sigaction (SIGQUIT, &sa, NULL);
219 sigaction (SIGINT, &sa, NULL);
222 unset_option (OPTSYSSIGNALSBLOCKED);
226 void mutt_allow_interrupt (int disposition)
230 memset (&sa, 0, sizeof sa);
231 sa.sa_handler = sighandler;
233 if (disposition == 0)
234 sa.sa_flags |= SA_RESTART;
236 sigaction (SIGINT, &sa, NULL);