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.
10 #include <lib-lib/lib-lib.h>
12 #include <lib-ui/curses.h>
14 #include "mutt_signal.h"
16 static sigset_t Sigset;
17 static sigset_t SigsetSys;
18 static struct sigaction SysOldInt;
19 static struct sigaction SysOldQuit;
20 static int IsEndwin = 0;
22 /* Attempt to catch "ordinary" signals and shut down gracefully. */
23 static void exit_handler (int sig)
26 endwin (); /* just to be safe */
27 printf(_("Caught %s... Exiting.\n"), strsignal(sig));
31 static void chld_handler(int sig __attribute__((unused)))
36 static void sighandler (int sig)
38 int save_errno = errno;
41 case SIGTSTP: /* user requested a suspend */
42 if (!option (OPTSUSPEND))
44 IsEndwin = isendwin ();
54 #if defined (HAVE_RESIZETERM)
55 /* We don't receive SIGWINCH when suspended; however, no harm is done by
56 * just assuming we received one, and triggering the 'resize' anyway. */
61 #if defined (HAVE_RESIZETERM)
75 void mutt_signal_initialize (void)
79 sigemptyset (&act.sa_mask);
81 act.sa_handler = SIG_IGN;
82 sigaction (SIGPIPE, &act, NULL);
84 act.sa_handler = exit_handler;
85 sigaction (SIGTERM, &act, NULL);
86 sigaction (SIGHUP, &act, NULL);
87 sigaction (SIGQUIT, &act, NULL);
89 /* we want to avoid race conditions */
90 sigaddset (&act.sa_mask, SIGTSTP);
92 act.sa_handler = sighandler;
94 /* we want SIGALRM to abort the current syscall, so we do this before
95 * setting the SA_RESTART flag below. currently this is only used to
96 * timeout on a connect() call in a reasonable amout of time.
98 sigaction (SIGALRM, &act, NULL);
100 /* we also don't want to mess with interrupted system calls */
102 act.sa_flags = SA_RESTART;
105 sigaction (SIGCONT, &act, NULL);
106 sigaction (SIGTSTP, &act, NULL);
107 sigaction (SIGINT, &act, NULL);
108 #if defined (HAVE_RESIZETERM)
109 sigaction (SIGWINCH, &act, NULL);
112 /* POSIX doesn't allow us to ignore SIGCHLD,
113 * so we just install a dummy handler for it
115 act.sa_handler = chld_handler;
116 /* don't need to block any other signals here */
117 sigemptyset (&act.sa_mask);
118 /* we don't want to mess with stopped children */
119 act.sa_flags |= SA_NOCLDSTOP;
120 sigaction (SIGCHLD, &act, NULL);
123 /* signals which are important to block while doing critical ops */
124 void mutt_block_signals (void)
126 if (!option (OPTSIGNALSBLOCKED)) {
127 sigemptyset (&Sigset);
128 sigaddset (&Sigset, SIGTERM);
129 sigaddset (&Sigset, SIGHUP);
130 sigaddset (&Sigset, SIGTSTP);
131 sigaddset (&Sigset, SIGINT);
132 #if defined (HAVE_RESIZETERM)
133 sigaddset (&Sigset, SIGWINCH);
135 sigprocmask (SIG_BLOCK, &Sigset, 0);
136 set_option (OPTSIGNALSBLOCKED);
140 /* restore the previous signal mask */
141 void mutt_unblock_signals (void)
143 if (option (OPTSIGNALSBLOCKED)) {
144 sigprocmask (SIG_UNBLOCK, &Sigset, 0);
145 unset_option (OPTSIGNALSBLOCKED);
149 void mutt_block_signals_system (void)
153 if (!option (OPTSYSSIGNALSBLOCKED)) {
154 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
155 sa.sa_handler = SIG_IGN;
157 sigemptyset (&sa.sa_mask);
158 sigaction (SIGINT, &sa, &SysOldInt);
159 sigaction (SIGQUIT, &sa, &SysOldQuit);
161 sigemptyset (&SigsetSys);
162 sigaddset (&SigsetSys, SIGCHLD);
163 sigprocmask (SIG_BLOCK, &SigsetSys, 0);
164 set_option (OPTSYSSIGNALSBLOCKED);
168 void mutt_unblock_signals_system (int catch)
170 if (option (OPTSYSSIGNALSBLOCKED)) {
171 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
173 sigaction (SIGQUIT, &SysOldQuit, NULL);
174 sigaction (SIGINT, &SysOldInt, NULL);
179 sa.sa_handler = SIG_DFL;
180 sigemptyset (&sa.sa_mask);
182 sigaction (SIGQUIT, &sa, NULL);
183 sigaction (SIGINT, &sa, NULL);
186 unset_option (OPTSYSSIGNALSBLOCKED);
190 void mutt_allow_interrupt (int disposition)
195 sa.sa_handler = sighandler;
197 if (disposition == 0)
198 sa.sa_flags |= SA_RESTART;
200 sigaction (SIGINT, &sa, NULL);