2 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 #include "mutt_curses.h"
31 static sigset_t Sigset;
32 static sigset_t SigsetSys;
33 static struct sigaction SysOldInt;
34 static struct sigaction SysOldQuit;
35 static int IsEndwin = 0;
37 /* Attempt to catch "ordinary" signals and shut down gracefully. */
38 RETSIGTYPE exit_handler (int sig)
41 endwin (); /* just to be safe */
42 #if SYS_SIGLIST_DECLARED
43 printf (_("%s... Exiting.\n"), sys_siglist[sig]);
45 #if (__sun__ && __svr4__)
46 printf (_("Caught %s... Exiting.\n"), _sys_siglist[sig]);
48 #if (__alpha && __osf__)
49 printf (_("Caught %s... Exiting.\n"), __sys_siglist[sig]);
51 printf (_("Caught signal %d... Exiting.\n"), sig);
58 RETSIGTYPE chld_handler (int sig)
63 RETSIGTYPE sighandler (int sig)
65 int save_errno = errno;
68 case SIGTSTP: /* user requested a suspend */
69 if (!option (OPTSUSPEND))
71 IsEndwin = isendwin ();
81 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
82 /* We don't receive SIGWINCH when suspended; however, no harm is done by
83 * just assuming we received one, and triggering the 'resize' anyway. */
88 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
102 #ifdef USE_SLANG_CURSES
103 int mutt_intr_hook (void)
107 #endif /* USE_SLANG_CURSES */
109 void mutt_signal_init (void)
111 struct sigaction act;
113 sigemptyset (&act.sa_mask);
115 act.sa_handler = SIG_IGN;
116 sigaction (SIGPIPE, &act, NULL);
118 act.sa_handler = exit_handler;
119 sigaction (SIGTERM, &act, NULL);
120 sigaction (SIGHUP, &act, NULL);
121 sigaction (SIGQUIT, &act, NULL);
123 /* we want to avoid race conditions */
124 sigaddset (&act.sa_mask, SIGTSTP);
126 act.sa_handler = sighandler;
128 /* we want SIGALRM to abort the current syscall, so we do this before
129 * setting the SA_RESTART flag below. currently this is only used to
130 * timeout on a connect() call in a reasonable amout of time.
132 sigaction (SIGALRM, &act, NULL);
134 /* we also don't want to mess with interrupted system calls */
136 act.sa_flags = SA_RESTART;
139 sigaction (SIGCONT, &act, NULL);
140 sigaction (SIGTSTP, &act, NULL);
141 sigaction (SIGINT, &act, NULL);
142 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
143 sigaction (SIGWINCH, &act, NULL);
146 /* POSIX doesn't allow us to ignore SIGCHLD,
147 * so we just install a dummy handler for it
149 act.sa_handler = chld_handler;
150 /* don't need to block any other signals here */
151 sigemptyset (&act.sa_mask);
152 /* we don't want to mess with stopped children */
153 act.sa_flags |= SA_NOCLDSTOP;
154 sigaction (SIGCHLD, &act, NULL);
156 #ifdef USE_SLANG_CURSES
157 /* This bit of code is required because of the implementation of
158 * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we
159 * are in blocking mode, SLsys_getkey() will not return an error unless
160 * a handler function is defined and it returns -1. This is needed so
161 * that if the user resizes the screen while at a prompt, it will just
162 * abort and go back to the main-menu.
164 SLang_getkey_intr_hook = mutt_intr_hook;
168 /* signals which are important to block while doing critical ops */
169 void mutt_block_signals (void)
171 if (!option (OPTSIGNALSBLOCKED)) {
172 sigemptyset (&Sigset);
173 sigaddset (&Sigset, SIGTERM);
174 sigaddset (&Sigset, SIGHUP);
175 sigaddset (&Sigset, SIGTSTP);
176 sigaddset (&Sigset, SIGINT);
177 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
178 sigaddset (&Sigset, SIGWINCH);
180 sigprocmask (SIG_BLOCK, &Sigset, 0);
181 set_option (OPTSIGNALSBLOCKED);
185 /* restore the previous signal mask */
186 void mutt_unblock_signals (void)
188 if (option (OPTSIGNALSBLOCKED)) {
189 sigprocmask (SIG_UNBLOCK, &Sigset, 0);
190 unset_option (OPTSIGNALSBLOCKED);
194 void mutt_block_signals_system (void)
198 if (!option (OPTSYSSIGNALSBLOCKED)) {
199 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
200 sa.sa_handler = SIG_IGN;
202 sigemptyset (&sa.sa_mask);
203 sigaction (SIGINT, &sa, &SysOldInt);
204 sigaction (SIGQUIT, &sa, &SysOldQuit);
206 sigemptyset (&SigsetSys);
207 sigaddset (&SigsetSys, SIGCHLD);
208 sigprocmask (SIG_BLOCK, &SigsetSys, 0);
209 set_option (OPTSYSSIGNALSBLOCKED);
213 void mutt_unblock_signals_system (int catch)
215 if (option (OPTSYSSIGNALSBLOCKED)) {
216 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
218 sigaction (SIGQUIT, &SysOldQuit, NULL);
219 sigaction (SIGINT, &SysOldInt, NULL);
224 sa.sa_handler = SIG_DFL;
225 sigemptyset (&sa.sa_mask);
227 sigaction (SIGQUIT, &sa, NULL);
228 sigaction (SIGINT, &sa, NULL);
231 unset_option (OPTSYSSIGNALSBLOCKED);
235 void mutt_allow_interrupt (int disposition)
239 memset (&sa, 0, sizeof sa);
240 sa.sa_handler = sighandler;
242 if (disposition == 0)
243 sa.sa_flags |= SA_RESTART;
245 sigaction (SIGINT, &sa, NULL);