mutt stable branch with some hacks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at jcs 293 lines 6.9 kB view raw
1/* 2 * Copyright (C) 1996-2000,2012 Michael R. Elkins <me@mutt.org> 3 * 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. 8 * 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. 13 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#include "mutt_curses.h" 25 26#include <signal.h> 27#include <string.h> 28#include <sys/wait.h> 29#include <errno.h> 30#include <unistd.h> 31 32static sigset_t Sigset; 33static sigset_t SigsetSys; 34static struct sigaction SysOldInt; 35static struct sigaction SysOldQuit; 36static int IsEndwin = 0; 37 38static void exit_print_int_recursive (int n) 39{ 40 char digit; 41 42 if (n > 9) 43 exit_print_int_recursive (n / 10); 44 45 digit = '0' + (n % 10); 46 write (1, &digit, 1); 47} 48 49static void exit_print_int (int n) 50{ 51 if (n < 0) 52 { 53 write (1, "-", 1); 54 n = -n; 55 } 56 exit_print_int_recursive (n); 57} 58 59static void exit_print_string (const char *str) 60{ 61 size_t len = 0; 62 63 if (!str) 64 return; 65 66 while (str[len]) 67 len++; 68 69 if (len > 0) 70 write (1, str, len); 71} 72 73/* Attempt to catch "ordinary" signals and shut down gracefully. */ 74static void exit_handler (int sig) 75{ 76 curs_set (1); 77 endwin (); /* just to be safe */ 78 79 exit_print_string ("Caught signal "); 80#if SYS_SIGLIST_DECLARED 81 exit_print_string (sys_siglist[sig]); 82#else 83#if (__sun__ && __svr4__) 84 exit_print_string (_sys_siglist[sig]); 85#else 86#if (__alpha && __osf__) 87 exit_print_string (__sys_siglist[sig]); 88#else 89 exit_print_int (sig); 90#endif 91#endif 92#endif 93 exit_print_string ("... Exiting.\n"); 94 exit (0); 95} 96 97static void chld_handler (int sig) 98{ 99 /* empty */ 100} 101 102static void sighandler (int sig) 103{ 104 int save_errno = errno; 105 106 switch (sig) 107 { 108 case SIGTSTP: /* user requested a suspend */ 109 if (!option (OPTSUSPEND)) 110 break; 111 IsEndwin = isendwin (); 112 curs_set (1); 113 if (!IsEndwin) 114 endwin (); 115 kill (0, SIGSTOP); 116 /* fall through */ 117 118 case SIGCONT: 119 if (!IsEndwin) 120 refresh (); 121 mutt_curs_set (-1); 122#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) 123 /* We don't receive SIGWINCH when suspended; however, no harm is done by 124 * just assuming we received one, and triggering the 'resize' anyway. */ 125 SigWinch = 1; 126#endif 127 break; 128 129#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) 130 case SIGWINCH: 131 SigWinch = 1; 132 break; 133#endif 134 135 case SIGINT: 136 SigInt = 1; 137 break; 138 139 } 140 errno = save_errno; 141} 142 143#ifdef USE_SLANG_CURSES 144int mutt_intr_hook (void) 145{ 146 return (-1); 147} 148#endif /* USE_SLANG_CURSES */ 149 150void mutt_signal_init (void) 151{ 152 struct sigaction act; 153 154 sigemptyset (&act.sa_mask); 155 act.sa_flags = 0; 156 act.sa_handler = SIG_IGN; 157 sigaction (SIGPIPE, &act, NULL); 158 159 act.sa_handler = exit_handler; 160 sigaction (SIGTERM, &act, NULL); 161 sigaction (SIGHUP, &act, NULL); 162 sigaction (SIGQUIT, &act, NULL); 163 164 /* we want to avoid race conditions */ 165 sigaddset (&act.sa_mask, SIGTSTP); 166 167 act.sa_handler = sighandler; 168 169 /* we want SIGALRM to abort the current syscall, so we do this before 170 * setting the SA_RESTART flag below. currently this is only used to 171 * timeout on a connect() call in a reasonable amount of time. 172 */ 173 sigaction (SIGALRM, &act, NULL); 174 175 /* we also don't want to mess with interrupted system calls */ 176#ifdef SA_RESTART 177 act.sa_flags = SA_RESTART; 178#endif 179 180 sigaction (SIGCONT, &act, NULL); 181 sigaction (SIGTSTP, &act, NULL); 182 sigaction (SIGINT, &act, NULL); 183#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) 184 sigaction (SIGWINCH, &act, NULL); 185#endif 186 187 /* POSIX doesn't allow us to ignore SIGCHLD, 188 * so we just install a dummy handler for it 189 */ 190 act.sa_handler = chld_handler; 191 /* don't need to block any other signals here */ 192 sigemptyset (&act.sa_mask); 193 /* we don't want to mess with stopped children */ 194 act.sa_flags |= SA_NOCLDSTOP; 195 sigaction (SIGCHLD, &act, NULL); 196 197#ifdef USE_SLANG_CURSES 198 /* This bit of code is required because of the implementation of 199 * SLcurses_wgetch(). If a signal is received (like SIGWINCH) when we 200 * are in blocking mode, SLsys_getkey() will not return an error unless 201 * a handler function is defined and it returns -1. This is needed so 202 * that if the user resizes the screen while at a prompt, it will just 203 * abort and go back to the main-menu. 204 */ 205 SLang_getkey_intr_hook = mutt_intr_hook; 206#endif 207} 208 209/* signals which are important to block while doing critical ops */ 210void mutt_block_signals (void) 211{ 212 if (!option (OPTSIGNALSBLOCKED)) 213 { 214 sigemptyset (&Sigset); 215 sigaddset (&Sigset, SIGTERM); 216 sigaddset (&Sigset, SIGHUP); 217 sigaddset (&Sigset, SIGTSTP); 218 sigaddset (&Sigset, SIGINT); 219#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) 220 sigaddset (&Sigset, SIGWINCH); 221#endif 222 sigprocmask (SIG_BLOCK, &Sigset, 0); 223 set_option (OPTSIGNALSBLOCKED); 224 } 225} 226 227/* restore the previous signal mask */ 228void mutt_unblock_signals (void) 229{ 230 if (option (OPTSIGNALSBLOCKED)) 231 { 232 sigprocmask (SIG_UNBLOCK, &Sigset, 0); 233 unset_option (OPTSIGNALSBLOCKED); 234 } 235} 236 237void mutt_block_signals_system (void) 238{ 239 struct sigaction sa; 240 241 if (! option (OPTSYSSIGNALSBLOCKED)) 242 { 243 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */ 244 sa.sa_handler = SIG_IGN; 245 sa.sa_flags = 0; 246 sigemptyset (&sa.sa_mask); 247 sigaction (SIGINT, &sa, &SysOldInt); 248 sigaction (SIGQUIT, &sa, &SysOldQuit); 249 250 sigemptyset (&SigsetSys); 251 sigaddset (&SigsetSys, SIGCHLD); 252 sigprocmask (SIG_BLOCK, &SigsetSys, 0); 253 set_option (OPTSYSSIGNALSBLOCKED); 254 } 255} 256 257void mutt_unblock_signals_system (int catch) 258{ 259 if (option (OPTSYSSIGNALSBLOCKED)) 260 { 261 sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL); 262 if (catch) 263 { 264 sigaction (SIGQUIT, &SysOldQuit, NULL); 265 sigaction (SIGINT, &SysOldInt, NULL); 266 } 267 else 268 { 269 struct sigaction sa; 270 271 sa.sa_handler = SIG_DFL; 272 sigemptyset (&sa.sa_mask); 273 sa.sa_flags = 0; 274 sigaction (SIGQUIT, &sa, NULL); 275 sigaction (SIGINT, &sa, NULL); 276 } 277 278 unset_option (OPTSYSSIGNALSBLOCKED); 279 } 280} 281 282void mutt_allow_interrupt (int disposition) 283{ 284 struct sigaction sa; 285 286 memset (&sa, 0, sizeof sa); 287 sa.sa_handler = sighandler; 288#ifdef SA_RESTART 289 if (disposition == 0) 290 sa.sa_flags |= SA_RESTART; 291#endif 292 sigaction (SIGINT, &sa, NULL); 293}