~ubuntu-branches/debian/squeeze/mutt/squeeze

1.1.2 by Martin Pitt
Import upstream version 1.5.11+cvs20060403
1
/*
2
 * Copyright (C) 1996-2000 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
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;
36
37
/* Attempt to catch "ordinary" signals and shut down gracefully. */
1.1.10 by Bhavani Shankar
Import upstream version 1.5.19
38
static RETSIGTYPE exit_handler (int sig)
1.1.2 by Martin Pitt
Import upstream version 1.5.11+cvs20060403
39
{
40
  curs_set (1);
41
  endwin (); /* just to be safe */
42
#if SYS_SIGLIST_DECLARED
43
  printf(_("%s...  Exiting.\n"), sys_siglist[sig]);
44
#else
45
#if (__sun__ && __svr4__)
46
  printf(_("Caught %s...  Exiting.\n"), _sys_siglist[sig]);
47
#else
48
#if (__alpha && __osf__)
49
  printf(_("Caught %s...  Exiting.\n"), __sys_siglist[sig]);
50
#else
51
  printf(_("Caught signal %d...  Exiting.\n"), sig);
52
#endif
53
#endif
54
#endif
55
  exit (0);
56
}
57
1.1.10 by Bhavani Shankar
Import upstream version 1.5.19
58
static RETSIGTYPE chld_handler (int sig)
1.1.2 by Martin Pitt
Import upstream version 1.5.11+cvs20060403
59
{
60
  /* empty */
61
}
62
1.1.10 by Bhavani Shankar
Import upstream version 1.5.19
63
static RETSIGTYPE sighandler (int sig)
1.1.2 by Martin Pitt
Import upstream version 1.5.11+cvs20060403
64
{
65
  int save_errno = errno;
66
67
  switch (sig)
68
  {
69
    case SIGTSTP: /* user requested a suspend */
70
      if (!option (OPTSUSPEND))
71
        break;
72
      IsEndwin = isendwin ();
73
      curs_set (1);
74
      if (!IsEndwin)
75
	endwin ();
76
      kill (0, SIGSTOP);
77
78
    case SIGCONT:
79
      if (!IsEndwin)
80
	refresh ();
81
      mutt_curs_set (-1);
82
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
83
      /* We don't receive SIGWINCH when suspended; however, no harm is done by
84
       * just assuming we received one, and triggering the 'resize' anyway. */
85
      SigWinch = 1;
86
#endif
87
      break;
88
89
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
90
    case SIGWINCH:
91
      SigWinch = 1;
92
      break;
93
#endif
94
95
    case SIGINT:
96
      SigInt = 1;
97
      break;
98
99
  }
100
  errno = save_errno;
101
}
102
103
#ifdef USE_SLANG_CURSES
104
int mutt_intr_hook (void)
105
{
106
  return (-1);
107
}
108
#endif /* USE_SLANG_CURSES */
109
110
void mutt_signal_init (void)
111
{
112
  struct sigaction act;
113
114
  sigemptyset (&act.sa_mask);
115
  act.sa_flags = 0;
116
  act.sa_handler = SIG_IGN;
117
  sigaction (SIGPIPE, &act, NULL);
118
119
  act.sa_handler = exit_handler;
120
  sigaction (SIGTERM, &act, NULL);
121
  sigaction (SIGHUP, &act, NULL);
122
  sigaction (SIGQUIT, &act, NULL);
123
124
  /* we want to avoid race conditions */
125
  sigaddset (&act.sa_mask, SIGTSTP);
126
127
  act.sa_handler = sighandler;
128
129
  /* we want SIGALRM to abort the current syscall, so we do this before
130
   * setting the SA_RESTART flag below.  currently this is only used to
131
   * timeout on a connect() call in a reasonable amout of time.
132
   */
133
  sigaction (SIGALRM, &act, NULL);
134
135
  /* we also don't want to mess with interrupted system calls */
136
#ifdef SA_RESTART
137
  act.sa_flags = SA_RESTART;
138
#endif
139
140
  sigaction (SIGCONT, &act, NULL);
141
  sigaction (SIGTSTP, &act, NULL);
142
  sigaction (SIGINT, &act, NULL);
143
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
144
  sigaction (SIGWINCH, &act, NULL);
145
#endif
146
147
  /* POSIX doesn't allow us to ignore SIGCHLD,
148
   * so we just install a dummy handler for it
149
   */
150
  act.sa_handler = chld_handler;
151
  /* don't need to block any other signals here */
152
  sigemptyset (&act.sa_mask);
153
  /* we don't want to mess with stopped children */
154
  act.sa_flags |= SA_NOCLDSTOP;
155
  sigaction (SIGCHLD, &act, NULL);
156
157
#ifdef USE_SLANG_CURSES
158
  /* This bit of code is required because of the implementation of
159
   * SLcurses_wgetch().  If a signal is received (like SIGWINCH) when we
160
   * are in blocking mode, SLsys_getkey() will not return an error unless
161
   * a handler function is defined and it returns -1.  This is needed so
162
   * that if the user resizes the screen while at a prompt, it will just
163
   * abort and go back to the main-menu.
164
   */
165
  SLang_getkey_intr_hook = mutt_intr_hook;
166
#endif
167
}
168
169
/* signals which are important to block while doing critical ops */
170
void mutt_block_signals (void)
171
{
172
  if (!option (OPTSIGNALSBLOCKED))
173
  {
174
    sigemptyset (&Sigset);
175
    sigaddset (&Sigset, SIGTERM);
176
    sigaddset (&Sigset, SIGHUP);
177
    sigaddset (&Sigset, SIGTSTP);
178
    sigaddset (&Sigset, SIGINT);
179
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
180
    sigaddset (&Sigset, SIGWINCH);
181
#endif
182
    sigprocmask (SIG_BLOCK, &Sigset, 0);
183
    set_option (OPTSIGNALSBLOCKED);
184
  }
185
}
186
187
/* restore the previous signal mask */
188
void mutt_unblock_signals (void)
189
{
190
  if (option (OPTSIGNALSBLOCKED))
191
  {
192
    sigprocmask (SIG_UNBLOCK, &Sigset, 0);
193
    unset_option (OPTSIGNALSBLOCKED);
194
  }
195
}
196
197
void mutt_block_signals_system (void)
198
{
199
  struct sigaction sa;
200
201
  if (! option (OPTSYSSIGNALSBLOCKED))
202
  {
203
    /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD  before exec */
204
    sa.sa_handler = SIG_IGN;
205
    sa.sa_flags = 0;
206
    sigemptyset (&sa.sa_mask);
207
    sigaction (SIGINT, &sa, &SysOldInt);
208
    sigaction (SIGQUIT, &sa, &SysOldQuit);
209
210
    sigemptyset (&SigsetSys);
211
    sigaddset (&SigsetSys, SIGCHLD);
212
    sigprocmask (SIG_BLOCK, &SigsetSys, 0);
213
    set_option (OPTSYSSIGNALSBLOCKED);
214
  }
215
}
216
217
void mutt_unblock_signals_system (int catch)
218
{
219
  if (option (OPTSYSSIGNALSBLOCKED))
220
  {
221
    sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
222
    if (catch)
223
    {
224
      sigaction (SIGQUIT, &SysOldQuit, NULL);
225
      sigaction (SIGINT, &SysOldInt, NULL);
226
    }
227
    else
228
    {
229
      struct sigaction sa;
230
231
      sa.sa_handler = SIG_DFL;
232
      sigemptyset (&sa.sa_mask);
233
      sa.sa_flags = 0;
234
      sigaction (SIGQUIT, &sa, NULL);
235
      sigaction (SIGINT, &sa, NULL);
236
    }
237
238
    unset_option (OPTSYSSIGNALSBLOCKED);
239
  }
240
}
241
242
void mutt_allow_interrupt (int disposition)
243
{
244
  struct sigaction sa;
245
  
246
  memset (&sa, 0, sizeof sa);
247
  sa.sa_handler = sighandler;
248
#ifdef SA_RESTART
249
  if (disposition == 0)
250
    sa.sa_flags |= SA_RESTART;
251
#endif
252
  sigaction (SIGINT, &sa, NULL);
253
}