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/lib-ui.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 sighandler (int sig)
33 int save_errno = errno;
36 case SIGTSTP: /* user requested a suspend */
37 IsEndwin = isendwin ();
47 /* We don't receive SIGWINCH when suspended; however, no harm is done by
48 * just assuming we received one, and triggering the 'resize' anyway. */
64 void mutt_signal_initialize (void)
68 sigemptyset (&act.sa_mask);
70 act.sa_handler = SIG_IGN;
71 sigaction (SIGPIPE, &act, NULL);
73 act.sa_handler = exit_handler;
74 sigaction (SIGTERM, &act, NULL);
75 sigaction (SIGHUP, &act, NULL);
76 sigaction (SIGQUIT, &act, NULL);
78 /* we want to avoid race conditions */
79 sigaddset (&act.sa_mask, SIGTSTP);
81 act.sa_handler = sighandler;
83 /* we want SIGALRM to abort the current syscall, so we do this before
84 * setting the SA_RESTART flag below. currently this is only used to
85 * timeout on a connect() call in a reasonable amout of time.
87 sigaction (SIGALRM, &act, NULL);
89 /* we also don't want to mess with interrupted system calls */
91 act.sa_flags = SA_RESTART;
94 sigaction (SIGCONT, &act, NULL);
95 sigaction (SIGTSTP, &act, NULL);
96 sigaction (SIGINT, &act, NULL);
97 sigaction (SIGWINCH, &act, NULL);
99 /* POSIX doesn't allow us to ignore SIGCHLD,
100 * so we just install a dummy handler for it
102 /* don't need to block any other signals here */
103 sigemptyset (&act.sa_mask);
104 /* we don't want to mess with stopped children */
105 act.sa_flags |= SA_NOCLDSTOP;
106 sigaction (SIGCHLD, &act, NULL);
109 /* signals which are important to block while doing critical ops */
110 void mutt_block_signals (void)
112 if (!option (OPTSIGNALSBLOCKED)) {
113 sigemptyset (&Sigset);
114 sigaddset (&Sigset, SIGTERM);
115 sigaddset (&Sigset, SIGHUP);
116 sigaddset (&Sigset, SIGTSTP);
117 sigaddset (&Sigset, SIGINT);
118 sigaddset (&Sigset, SIGWINCH);
119 sigprocmask (SIG_BLOCK, &Sigset, 0);
120 set_option (OPTSIGNALSBLOCKED);
124 /* restore the previous signal mask */
125 void mutt_unblock_signals (void)
127 if (option (OPTSIGNALSBLOCKED)) {
128 sigprocmask (SIG_UNBLOCK, &Sigset, 0);
129 unset_option (OPTSIGNALSBLOCKED);
133 void mutt_block_signals_system (void)
137 if (!option (OPTSYSSIGNALSBLOCKED)) {
138 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
139 sa.sa_handler = SIG_IGN;
141 sigemptyset (&sa.sa_mask);
142 sigaction (SIGINT, &sa, &SysOldInt);
143 sigaction (SIGQUIT, &sa, &SysOldQuit);
145 sigemptyset (&SigsetSys);
146 sigaddset (&SigsetSys, SIGCHLD);
147 sigprocmask (SIG_BLOCK, &SigsetSys, 0);
148 set_option (OPTSYSSIGNALSBLOCKED);
152 void mutt_unblock_signals_system (int catch)
154 if (option (OPTSYSSIGNALSBLOCKED)) {
155 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
157 sigaction (SIGQUIT, &SysOldQuit, NULL);
158 sigaction (SIGINT, &SysOldInt, NULL);
163 sa.sa_handler = SIG_DFL;
164 sigemptyset (&sa.sa_mask);
166 sigaction (SIGQUIT, &sa, NULL);
167 sigaction (SIGINT, &sa, NULL);
170 unset_option (OPTSYSSIGNALSBLOCKED);
174 void mutt_allow_interrupt (int disposition)
179 sa.sa_handler = sighandler;
181 if (disposition == 0)
182 sa.sa_flags |= SA_RESTART;
184 sigaction (SIGINT, &sa, NULL);