1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
1 |
#if !defined(lint) && !defined(DOS)
|
1.1.8
by Asheesh Laroia
Import upstream version 2.02 |
2 |
static char rcsid[] = "$Id: signal.c 1025 2008-04-08 22:59:38Z hubert@u.washington.edu $"; |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
3 |
#endif
|
4 |
||
5 |
/* ========================================================================
|
|
1.2.1
by Asheesh Laroia
Import upstream version 1.10+dfsg |
6 |
* Copyright 2006-2008 University of Washington
|
1.1.10
by Asheesh Laroia
Import upstream version 2.10+dfsg |
7 |
* Copyright 2013 Eduardo Chappa
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
8 |
*
|
9 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
10 |
* you may not use this file except in compliance with the License.
|
|
11 |
* You may obtain a copy of the License at
|
|
12 |
*
|
|
13 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14 |
*
|
|
15 |
* ========================================================================
|
|
16 |
*/
|
|
17 |
||
18 |
/*======================================================================
|
|
19 |
Different signal handlers for different signals
|
|
20 |
- Catches all the abort signals, cleans up tty modes and then coredumps
|
|
21 |
- Not much to do for SIGHUP
|
|
22 |
- Not much to do for SIGTERM
|
|
23 |
- turn SIGWINCH into a KEY_RESIZE command
|
|
24 |
- No signals for ^Z/suspend, but do it here anyway
|
|
25 |
- Also set up the signal handlers, and hold signals for
|
|
26 |
critical imap sections of code.
|
|
27 |
====*/
|
|
28 |
||
29 |
||
30 |
#include "headers.h" |
|
31 |
#include "alpine.h" |
|
32 |
#include "signal.h" |
|
33 |
#include "status.h" |
|
34 |
#include "dispfilt.h" |
|
35 |
#include "keymenu.h" |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
36 |
#include "titlebar.h" |
37 |
#include "mailcmd.h" |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
38 |
#include "../pith/state.h" |
39 |
#include "../pith/conf.h" |
|
40 |
#include "../pith/detach.h" |
|
41 |
#include "../pith/pipe.h" |
|
42 |
#include "../pith/util.h" |
|
43 |
#include "../pith/icache.h" |
|
44 |
#include "../pith/newmail.h" |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
45 |
#include "../pith/imap.h" |
46 |
#include "../pith/adrbklib.h" |
|
47 |
#include "../pith/remote.h" |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
48 |
#include "../pith/osdep/pipe.h" |
49 |
||
50 |
||
51 |
/*
|
|
52 |
* Internal Prototypes
|
|
53 |
*/
|
|
54 |
static RETSIGTYPE auger_in_signal(int); |
|
55 |
void init_sighup(void); |
|
56 |
void end_sighup(void); |
|
57 |
RETSIGTYPE term_signal(void); |
|
58 |
void fast_clean_up(void); |
|
59 |
static RETSIGTYPE usr2_signal(int); |
|
60 |
static RETSIGTYPE winch_signal(int); |
|
61 |
static RETSIGTYPE intr_signal(int); |
|
62 |
void suspend_notice(char *); |
|
63 |
void suspend_warning(void); |
|
64 |
||
65 |
||
66 |
||
67 |
static int cleanup_called_from_sig_handler; |
|
68 |
||
69 |
||
70 |
||
71 |
/*----------------------------------------------------------------------
|
|
72 |
Install handlers for all the signals we care to catch
|
|
73 |
----------------------------------------------------------------------*/
|
|
74 |
void
|
|
75 |
init_signals(void) |
|
76 |
{
|
|
77 |
dprint((9, "init_signals()\n")); |
|
78 |
init_sighup(); |
|
79 |
||
80 |
#ifdef _WINDOWS
|
|
81 |
#else
|
|
82 |
# ifdef DEBUG
|
|
83 |
# define CUSHION_SIG (debug < 7)
|
|
84 |
# else
|
|
85 |
# define CUSHION_SIG (1)
|
|
86 |
# endif
|
|
87 |
||
88 |
if(CUSHION_SIG){ |
|
89 |
signal(SIGILL, auger_in_signal); |
|
90 |
signal(SIGTRAP, auger_in_signal); |
|
91 |
# ifdef SIGEMT
|
|
92 |
signal(SIGEMT, auger_in_signal); |
|
93 |
# endif
|
|
94 |
signal(SIGBUS, auger_in_signal); |
|
95 |
signal(SIGSEGV, auger_in_signal); |
|
96 |
signal(SIGSYS, auger_in_signal); |
|
97 |
signal(SIGQUIT, auger_in_signal); |
|
98 |
/* Don't catch SIGFPE cause it's rare and we use it in a hack below*/
|
|
99 |
}
|
|
100 |
||
101 |
init_sigwinch(); |
|
102 |
||
103 |
/*
|
|
104 |
* Set up SIGUSR2 to catch signal from other software using the
|
|
105 |
* c-client to tell us that other access to the folder is being
|
|
106 |
* attempted. THIS IS A TEST: if it turns out that simply
|
|
107 |
* going R/O when another pine is started or the same folder is opened,
|
|
108 |
* then we may want to install a smarter handler that uses idle time
|
|
109 |
* or even prompts the user to see if it's ok to give up R/O access...
|
|
110 |
*/
|
|
111 |
signal(SIGUSR2, usr2_signal); |
|
112 |
||
113 |
signal(SIGPIPE, SIG_IGN); |
|
114 |
signal(SIGINT, SIG_IGN); |
|
115 |
||
116 |
# ifdef SIGTSTP
|
|
117 |
/* Some unexplained behaviour on Ultrix 4.2 (Hardy) seems to be
|
|
118 |
resulting in Pine getting sent a SIGTSTP. Ignore it here.
|
|
119 |
probably better to ignore it than let it happen in any case
|
|
120 |
*/
|
|
121 |
signal(SIGTSTP, SIG_IGN); |
|
122 |
# endif /* SIGTSTP */ |
|
123 |
||
124 |
# ifdef SIGCHLD
|
|
125 |
signal(SIGCHLD, child_signal); |
|
126 |
# endif
|
|
127 |
#endif /* !_WINDOWS */ |
|
128 |
}
|
|
129 |
||
130 |
||
131 |
/*----------------------------------------------------------------------
|
|
132 |
Return all signal handling back to normal
|
|
133 |
----------------------------------------------------------------------*/
|
|
134 |
void
|
|
135 |
end_signals(int blockem) |
|
136 |
{
|
|
137 |
#ifdef _WINDOWS
|
|
138 |
||
139 |
signal(SIGHUP, blockem ? SIG_IGN : SIG_DFL); |
|
140 |
||
141 |
#else
|
|
142 |
#ifndef SIG_ERR
|
|
143 |
#define SIG_ERR (RETSIGTYPE (*)())-1
|
|
144 |
#endif
|
|
145 |
||
146 |
dprint((5, "end_signals(%d)\n", blockem)); |
|
147 |
if(signal(SIGILL, blockem ? SIG_IGN : SIG_DFL) == SIG_ERR){ |
|
148 |
fprintf(stderr, "Error resetting signals: %s\n", |
|
149 |
error_description(errno)); |
|
150 |
exit(-1); |
|
151 |
}
|
|
152 |
||
153 |
signal(SIGTRAP, blockem ? SIG_IGN : SIG_DFL); |
|
154 |
#ifdef SIGEMT
|
|
155 |
signal(SIGEMT, blockem ? SIG_IGN : SIG_DFL); |
|
156 |
#endif
|
|
157 |
signal(SIGBUS, blockem ? SIG_IGN : SIG_DFL); |
|
158 |
signal(SIGSEGV, blockem ? SIG_IGN : SIG_DFL); |
|
159 |
signal(SIGSYS, blockem ? SIG_IGN : SIG_DFL); |
|
160 |
#if defined(SIGWINCH) && defined(TIOCGWINSZ)
|
|
161 |
signal(SIGWINCH, blockem ? SIG_IGN : SIG_DFL); |
|
162 |
#endif
|
|
163 |
signal(SIGQUIT, blockem ? SIG_IGN : SIG_DFL); |
|
164 |
#ifdef SIGTSTP
|
|
165 |
signal(SIGTSTP, blockem ? SIG_IGN : SIG_DFL); |
|
166 |
#endif /* SIGTSTP */ |
|
167 |
signal(SIGHUP, blockem ? SIG_IGN : SIG_DFL); |
|
168 |
signal(SIGTERM, blockem ? SIG_IGN : SIG_DFL); |
|
169 |
signal(SIGINT, blockem ? SIG_IGN : SIG_DFL); |
|
170 |
||
171 |
#endif /* !_WINDOWS */ |
|
172 |
}
|
|
173 |
||
174 |
||
175 |
/*----------------------------------------------------------------------
|
|
176 |
Handle signals caused by aborts -- SIGSEGV, SIGILL, etc
|
|
177 |
||
178 |
Call panic which cleans up tty modes and then core dumps
|
|
179 |
----------------------------------------------------------------------*/
|
|
180 |
static RETSIGTYPE |
|
181 |
auger_in_signal(int sig) |
|
182 |
{
|
|
1.1.5
by Asheesh Laroia
Import upstream version 1.0+dfsg |
183 |
char buf[100]; |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
184 |
|
185 |
end_signals(1); /* don't catch any more signals */ |
|
186 |
imap_flush_passwd_cache(FALSE); |
|
187 |
||
1.1.5
by Asheesh Laroia
Import upstream version 1.0+dfsg |
188 |
snprintf(buf, sizeof(buf), "Received abort signal(sig=%d)", sig); |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
189 |
buf[sizeof(buf)-1] = '\0'; |
190 |
||
191 |
panic(buf); /* clean up and get out */ |
|
192 |
||
193 |
exit(-1); /* in case panic doesn't kill us */ |
|
194 |
}
|
|
195 |
||
196 |
||
197 |
/*----------------------------------------------------------------------
|
|
198 |
Install signal handler to deal with hang up signals -- SIGHUP, SIGTERM
|
|
199 |
|
|
200 |
----------------------------------------------------------------------*/
|
|
201 |
void
|
|
202 |
init_sighup(void) |
|
203 |
{
|
|
204 |
#if !(defined(DOS) && !defined(_WINDOWS))
|
|
205 |
#if defined(_WINDOWS) || defined(OS2)
|
|
206 |
signal(SIGHUP, (void *) hup_signal); |
|
207 |
#else
|
|
208 |
signal(SIGHUP, hup_signal); |
|
209 |
#endif
|
|
210 |
#endif
|
|
211 |
#if !(defined(DOS) || defined(OS2))
|
|
212 |
signal(SIGTERM, term_signal); |
|
213 |
#endif
|
|
214 |
}
|
|
215 |
||
216 |
||
217 |
/*----------------------------------------------------------------------
|
|
218 |
De-Install signal handler to deal with hang up signals -- SIGHUP, SIGTERM
|
|
219 |
|
|
220 |
----------------------------------------------------------------------*/
|
|
221 |
void
|
|
222 |
end_sighup(void) |
|
223 |
{
|
|
224 |
#if !(defined(DOS) && !defined(_WINDOWS))
|
|
225 |
signal(SIGHUP, SIG_IGN); |
|
226 |
#endif
|
|
227 |
#if !(defined(DOS) || defined(OS2))
|
|
228 |
signal(SIGTERM, SIG_IGN); |
|
229 |
#endif
|
|
230 |
}
|
|
231 |
||
232 |
||
233 |
/*----------------------------------------------------------------------
|
|
234 |
handle hang up signal -- SIGHUP
|
|
235 |
||
236 |
Not much to do. Rely on periodic mail file check pointing.
|
|
237 |
----------------------------------------------------------------------*/
|
|
238 |
RETSIGTYPE
|
|
239 |
hup_signal(void) |
|
240 |
{
|
|
241 |
end_signals(1); /* don't catch any more signals */ |
|
242 |
dprint((1, "\n\n** Received SIGHUP **\n\n\n\n")); |
|
243 |
cleanup_called_from_sig_handler = 1; |
|
244 |
fast_clean_up(); |
|
245 |
#if defined(DEBUG)
|
|
246 |
if(debugfile) |
|
247 |
fclose(debugfile); |
|
248 |
#endif
|
|
249 |
||
250 |
_exit(0); /* cleaning up can crash */ |
|
251 |
}
|
|
252 |
||
253 |
||
254 |
/*----------------------------------------------------------------------
|
|
255 |
Timeout when no user input for a long, long time.
|
|
256 |
Treat it pretty much the same as if we got a HUP.
|
|
257 |
Only difference is we sometimes turns the timeout off (when composing).
|
|
258 |
----------------------------------------------------------------------*/
|
|
259 |
void
|
|
260 |
user_input_timeout_exit(int to_hours) |
|
261 |
{
|
|
262 |
char msg[80]; |
|
263 |
||
264 |
dprint((1, |
|
265 |
"\n\n** Exiting: user input timeout (%d hours) **\n\n\n\n", |
|
266 |
to_hours)); |
|
267 |
snprintf(msg, sizeof(msg), _("\n\nAlpine timed out (No user input for %d %s)\n"), to_hours, |
|
268 |
to_hours > 1 ? "hours" : "hour"); |
|
269 |
msg[sizeof(msg)-1] = '\0'; |
|
270 |
fast_clean_up(); |
|
271 |
end_screen(msg, 0); |
|
272 |
end_titlebar(); |
|
273 |
end_keymenu(); |
|
274 |
end_keyboard(F_ON(F_USE_FK,ps_global)); |
|
275 |
end_tty_driver(ps_global); |
|
276 |
end_signals(0); |
|
277 |
#if defined(DEBUG) && (!defined(DOS) || defined(_WINDOWS))
|
|
278 |
if(debugfile) |
|
279 |
fclose(debugfile); |
|
280 |
#endif
|
|
281 |
exit(0); |
|
282 |
}
|
|
283 |
||
284 |
||
285 |
/*----------------------------------------------------------------------
|
|
286 |
handle terminate signal -- SIGTERM
|
|
287 |
||
288 |
Not much to do. Rely on periodic mail file check pointing.
|
|
289 |
----------------------------------------------------------------------*/
|
|
290 |
RETSIGTYPE
|
|
291 |
term_signal(void) |
|
292 |
{
|
|
293 |
#if !defined(DOS) && !defined(OS2)
|
|
294 |
end_signals(1); /* don't catch any more signals */ |
|
295 |
dprint((1, "\n\n** Received SIGTERM **\n\n\n\n")); |
|
296 |
cleanup_called_from_sig_handler = 1; |
|
297 |
fast_clean_up(); |
|
298 |
#if defined(DEBUG) && (!defined(DOS) || defined(_WINDOWS))
|
|
299 |
if(debugfile) |
|
300 |
fclose(debugfile); |
|
301 |
#endif
|
|
302 |
printf(_("\n\nAlpine finished. Received terminate signal\n\n")); |
|
303 |
#endif /* !DOS */ |
|
304 |
exit(0); |
|
305 |
}
|
|
306 |
||
307 |
||
308 |
/*----------------------------------------------------------------------
|
|
309 |
Handle cleaning up mail streams and tty modes...
|
|
310 |
Not much to do. Rely on periodic mail file check pointing. Don't try
|
|
311 |
cleaning up screen or flushing output since stdout is likely already
|
|
312 |
gone. To be safe, though, we'll at least restore the original tty mode.
|
|
313 |
Also delete any remnant _DATAFILE_ from sending-filters.
|
|
314 |
----------------------------------------------------------------------*/
|
|
315 |
void
|
|
316 |
fast_clean_up(void) |
|
317 |
{
|
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
318 |
#if !defined(DOS) && !defined(OS2)
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
319 |
int i; |
320 |
MAILSTREAM *m; |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
321 |
#endif
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
322 |
|
323 |
dprint((1, "fast_clean_up()\n")); |
|
324 |
||
325 |
if(ps_global->expunge_in_progress){ |
|
326 |
PineRaw(0); |
|
327 |
return; |
|
328 |
}
|
|
329 |
||
330 |
/*
|
|
331 |
* This gets rid of temporary cache files for remote addrbooks.
|
|
332 |
*/
|
|
333 |
completely_done_with_adrbks(); |
|
334 |
||
335 |
/*
|
|
336 |
* This flushes out deferred changes and gets rid of temporary cache
|
|
337 |
* files for remote config files.
|
|
338 |
*/
|
|
339 |
if(ps_global->prc){ |
|
340 |
if(ps_global->prc->outstanding_pinerc_changes) |
|
341 |
write_pinerc(ps_global, Main, |
|
342 |
cleanup_called_from_sig_handler ? WRP_NOUSER : WRP_NONE); |
|
343 |
||
344 |
if(ps_global->prc->rd) |
|
345 |
rd_close_remdata(&ps_global->prc->rd); |
|
346 |
||
347 |
free_pinerc_s(&ps_global->prc); |
|
348 |
}
|
|
349 |
||
350 |
/* as does this */
|
|
351 |
if(ps_global->post_prc){ |
|
352 |
if(ps_global->post_prc->outstanding_pinerc_changes) |
|
353 |
write_pinerc(ps_global, Post, |
|
354 |
cleanup_called_from_sig_handler ? WRP_NOUSER : WRP_NONE); |
|
355 |
||
356 |
if(ps_global->post_prc->rd) |
|
357 |
rd_close_remdata(&ps_global->post_prc->rd); |
|
358 |
||
359 |
free_pinerc_s(&ps_global->post_prc); |
|
360 |
}
|
|
361 |
||
362 |
/*
|
|
363 |
* Can't figure out why this section is inside the ifdef, but no
|
|
364 |
* harm leaving it that way, I guess.
|
|
365 |
*/
|
|
366 |
#if !defined(DOS) && !defined(OS2)
|
|
367 |
for(i = 0; i < ps_global->s_pool.nstream; i++){ |
|
368 |
m = ps_global->s_pool.streams[i]; |
|
369 |
if(m && !m->lock) |
|
370 |
pine_mail_actually_close(m); |
|
371 |
}
|
|
372 |
||
373 |
PineRaw(0); |
|
374 |
||
375 |
#endif /* !DOS */ |
|
376 |
||
377 |
imap_flush_passwd_cache(TRUE); |
|
378 |
||
379 |
dprint((1, "done with fast_clean_up\n")); |
|
380 |
}
|
|
381 |
||
382 |
||
383 |
#if !defined(DOS) && !defined(OS2)
|
|
384 |
/*----------------------------------------------------------------------
|
|
385 |
handle hang up signal -- SIGUSR2
|
|
386 |
||
387 |
Not much to do. Rely on periodic mail file check pointing.
|
|
388 |
----------------------------------------------------------------------*/
|
|
389 |
static RETSIGTYPE |
|
390 |
usr2_signal(int sig) |
|
391 |
{
|
|
392 |
char c, *mbox, mboxbuf[20]; |
|
393 |
int i; |
|
394 |
MAILSTREAM *stream; |
|
395 |
NETMBX mb; |
|
396 |
||
397 |
for(i = 0; i < ps_global->s_pool.nstream; i++){ |
|
398 |
stream = ps_global->s_pool.streams[i]; |
|
399 |
if(stream |
|
400 |
&& sp_flagged(stream, SP_LOCKED) |
|
401 |
&& !sp_dead_stream(stream) |
|
402 |
&& !stream->lock |
|
403 |
&& !stream->rdonly |
|
404 |
&& stream->mailbox |
|
405 |
&& (c = *stream->mailbox) != '{' && c != '*'){ |
|
406 |
pine_mail_check(stream); /* write latest state */ |
|
407 |
stream->rdonly = 1; /* and become read-only */ |
|
408 |
(void) pine_mail_ping(stream); |
|
409 |
mbox = stream->mailbox; |
|
410 |
if(!strucmp(stream->mailbox, ps_global->inbox_name) |
|
411 |
|| !strcmp(stream->mailbox, ps_global->VAR_INBOX_PATH) |
|
412 |
|| !strucmp(stream->original_mailbox, ps_global->inbox_name) |
|
413 |
|| !strcmp(stream->original_mailbox, ps_global->VAR_INBOX_PATH)) |
|
414 |
mbox = "INBOX"; |
|
415 |
else if(mail_valid_net_parse(stream->mailbox, &mb) && mb.mailbox) |
|
416 |
mbox = mb.mailbox; |
|
417 |
||
418 |
q_status_message1(SM_ASYNC, 3, 7, |
|
419 |
_("Another email program is accessing %s. Session now Read-Only."), |
|
420 |
short_str((mbox && *mbox) ? mbox : "folder", |
|
421 |
mboxbuf, sizeof(mboxbuf), 19, FrontDots)); |
|
422 |
dprint((1, "** folder %s went read-only **\n\n", |
|
423 |
stream->mailbox)); |
|
424 |
}
|
|
425 |
}
|
|
426 |
}
|
|
427 |
#endif
|
|
428 |
||
429 |
||
430 |
/*----------------------------------------------------------------------
|
|
431 |
Install signal handler to deal with window resize signal -- SIGWINCH
|
|
432 |
|
|
433 |
----------------------------------------------------------------------*/
|
|
434 |
void
|
|
435 |
init_sigwinch (void) |
|
436 |
{
|
|
437 |
#if defined(SIGWINCH) && defined(TIOCGWINSZ)
|
|
438 |
signal(SIGWINCH, winch_signal); |
|
439 |
#endif
|
|
440 |
}
|
|
441 |
||
442 |
||
443 |
#if defined(SIGWINCH) && defined(TIOCGWINSZ)
|
|
444 |
/*----------------------------------------------------------------------
|
|
445 |
Handle window resize signal -- SIGWINCH
|
|
446 |
|
|
447 |
The planned strategy is just force a redraw command. This is similar
|
|
448 |
to new mail handling which forces a noop command. The signals are
|
|
449 |
help until pine reads input. Then a KEY_RESIZE is forced into the command
|
|
450 |
stream .
|
|
451 |
Note that ready_for_winch is only non-zero inside the read_char function,
|
|
452 |
so the longjmp only ever happens there, and it is really just a jump
|
|
453 |
from lower down in the function up to the top of that function. Its
|
|
454 |
purpose is to return a KEY_RESIZE from read_char when interrupted
|
|
455 |
out of the select lower down in read_char.
|
|
456 |
----------------------------------------------------------------------*/
|
|
457 |
extern jmp_buf winch_state; |
|
458 |
extern int ready_for_winch, winch_occured; |
|
459 |
||
460 |
static RETSIGTYPE |
|
461 |
winch_signal(int sig) |
|
462 |
{
|
|
463 |
clear_cursor_pos(); |
|
464 |
init_sigwinch(); |
|
465 |
winch_cleanup(); |
|
466 |
}
|
|
467 |
#endif
|
|
468 |
||
469 |
||
470 |
/*
|
|
471 |
* winch_cleanup -
|
|
472 |
*/
|
|
473 |
void
|
|
474 |
winch_cleanup(void) |
|
475 |
{
|
|
476 |
#if defined(SIGWINCH) && defined(TIOCGWINSZ)
|
|
477 |
if(ready_for_winch) |
|
478 |
longjmp(winch_state, 1); |
|
479 |
else
|
|
480 |
winch_occured = 1; |
|
481 |
#endif
|
|
482 |
}
|
|
483 |
||
484 |
||
485 |
#ifdef SIGCHLD
|
|
486 |
/*----------------------------------------------------------------------
|
|
487 |
Handle child status change -- SIGCHLD
|
|
488 |
|
|
489 |
The strategy here is to install the handler when we spawn a child, and
|
|
490 |
to let the system tell us when the child's state has changed. In the
|
|
491 |
mean time, we can do whatever. Typically, "whatever" is spinning in a
|
|
492 |
loop alternating between sleep and new_mail calls intended to keep the
|
|
493 |
IMAP stream alive.
|
|
494 |
||
495 |
----------------------------------------------------------------------*/
|
|
1.2.1
by Asheesh Laroia
Import upstream version 1.10+dfsg |
496 |
static short child_signalled, child_jump; |
497 |
static jmp_buf child_state; |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
498 |
|
499 |
RETSIGTYPE
|
|
500 |
child_signal(int sig) |
|
501 |
{
|
|
502 |
#ifdef BACKGROUND_POST
|
|
503 |
/*
|
|
504 |
* reap background posting process
|
|
505 |
*/
|
|
506 |
if(ps_global->post && ps_global->post->pid){ |
|
507 |
pid_t pid; |
|
508 |
int es; |
|
509 |
||
510 |
pid = process_reap(ps_global->post->pid, &es, PR_NOHANG); |
|
511 |
if(pid == ps_global->post->pid){ |
|
512 |
ps_global->post->status = es; |
|
513 |
ps_global->post->pid = 0; |
|
514 |
return; |
|
515 |
}
|
|
516 |
else if(pid < 0 && errno != EINTR){ |
|
517 |
fs_give((void **) &ps_global->post); |
|
518 |
}
|
|
519 |
}
|
|
520 |
#endif /* BACKGROUND_POST */ |
|
521 |
||
522 |
child_signalled = 1; |
|
523 |
if(child_jump) |
|
524 |
longjmp(child_state, 1); |
|
525 |
}
|
|
526 |
#endif /* SIGCHLD */ |
|
527 |
||
528 |
||
529 |
/*
|
|
530 |
* pipe_callback - handle pine-specific pipe setup like child
|
|
531 |
* signal handler and possibly any display stuff
|
|
532 |
* BUG: this function should probably be in a "alpine/pipe.c"
|
|
533 |
*/
|
|
534 |
void
|
|
535 |
pipe_callback(PIPE_S *syspipe, int flags, void *data) |
|
536 |
{
|
|
537 |
#ifdef _WINDOWS
|
|
538 |
bitmap_t bitmap; |
|
539 |
#endif
|
|
540 |
if(flags & OSB_PRE_OPEN){ |
|
541 |
dprint((5, "Opening pipe: (%s%s%s%s%s%s)\n", |
|
542 |
(syspipe->mode & PIPE_WRITE) ? "W":"", (syspipe->mode & PIPE_READ) ? "R":"", |
|
543 |
(syspipe->mode & PIPE_NOSHELL) ? "N":"", (syspipe->mode & PIPE_PROT) ? "P":"", |
|
544 |
(syspipe->mode & PIPE_USER) ? "U":"", (syspipe->mode & PIPE_RESET) ? "T":"")); |
|
545 |
||
546 |
#ifdef _WINDOWS
|
|
547 |
q_status_message(SM_ORDER, 0, 0, |
|
548 |
"Waiting for called program to finish..."); |
|
549 |
||
550 |
flush_status_messages(1); |
|
551 |
setbitmap(bitmap); |
|
552 |
draw_keymenu(&pipe_cancel_keymenu, bitmap, ps_global->ttyo->screen_cols, |
|
553 |
1-FOOTER_ROWS(ps_global), 0, FirstMenu); |
|
554 |
#else /* UNIX */ |
|
555 |
||
556 |
if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ)) && !(syspipe->mode & PIPE_SILENT)){ |
|
557 |
flush_status_messages(0); /* just clean up display */ |
|
558 |
ClearScreen(); |
|
559 |
fflush(stdout); |
|
560 |
}
|
|
561 |
||
562 |
if(syspipe->mode & PIPE_RESET) |
|
563 |
ttyfix(0); |
|
564 |
||
565 |
#ifdef SIGCHLD
|
|
566 |
/*
|
|
567 |
* Prepare for demise of child. Use SIGCHLD if it's available so
|
|
568 |
* we can do useful things, like keep the IMAP stream alive, while
|
|
569 |
* we're waiting on the child. The handler may have been changed by
|
|
570 |
* something in the composer, in particular, by an alt_editor call.
|
|
571 |
* So we need to re-set it to child_signal and then set it back
|
|
572 |
* when we're done.
|
|
573 |
*/
|
|
574 |
child_signalled = child_jump = 0; |
|
575 |
syspipe->chld = signal(SIGCHLD, child_signal); |
|
576 |
#endif
|
|
577 |
#endif /* UNIX */ |
|
578 |
}
|
|
579 |
else if(flags & OSB_POST_OPEN){ |
|
580 |
#ifdef _WINDOWS
|
|
581 |
||
582 |
clearfooter(ps_global); |
|
583 |
ps_global->mangled_footer = 1; |
|
584 |
||
585 |
if((int) data == -2) |
|
586 |
q_status_message1(SM_ORDER, 2, 3, "Ignoring completion of %s", syspipe->command); |
|
587 |
||
588 |
#else /* UNIX */ |
|
589 |
if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ)) && !(syspipe->mode & PIPE_SILENT)){ |
|
590 |
ClearScreen(); |
|
591 |
ps_global->mangled_screen = 1; |
|
592 |
}
|
|
593 |
||
594 |
if(syspipe->mode & PIPE_RESET) |
|
595 |
ttyfix(1); |
|
596 |
||
597 |
#ifdef SIGCHLD
|
|
598 |
(void) signal(SIGCHLD, SIG_DFL); |
|
599 |
#endif
|
|
600 |
#endif /* UNIX */ |
|
601 |
}
|
|
602 |
else if(flags & OSB_PRE_CLOSE){ |
|
603 |
#ifdef SIGCHLD
|
|
604 |
/*
|
|
605 |
* this is here so close_system_pipe so it has something
|
|
606 |
* to do while we're waiting on the other end of the
|
|
607 |
* pipe to complete. When we're in the background for
|
|
608 |
* a shell, the the side effect is pinging
|
|
609 |
*/
|
|
610 |
RETSIGTYPE (*alarm_sig)(); |
|
611 |
int old_cue = F_ON(F_SHOW_DELAY_CUE, ps_global); |
|
612 |
||
613 |
/*
|
|
614 |
* remember the current SIGALRM handler, and make sure it's
|
|
615 |
* installed when we're finished just in case the longjmp
|
|
616 |
* out of the SIGCHLD handler caused sleep() to lose it.
|
|
617 |
* Don't pay any attention to that man behind the curtain.
|
|
618 |
*/
|
|
619 |
alarm_sig = signal(SIGALRM, SIG_IGN); |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
620 |
(void) F_SET(F_SHOW_DELAY_CUE, ps_global, 0); |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
621 |
ps_global->noshow_timeout = 1; |
622 |
while(!child_signalled){ |
|
623 |
/* wake up and prod server */
|
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
624 |
if(!(syspipe->mode & PIPE_NONEWMAIL)) |
625 |
new_mail(0, 2, |
|
626 |
(syspipe->mode & PIPE_RESET) ? NM_NONE : NM_DEFER_SORT); |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
627 |
|
628 |
if(!child_signalled){ |
|
629 |
if(setjmp(child_state) == 0){ |
|
630 |
child_jump = 1; /* prepare to wake up */ |
|
631 |
sleep(600); /* give it 5mins to happend */ |
|
632 |
}
|
|
633 |
else
|
|
634 |
our_sigunblock(SIGCHLD); |
|
635 |
}
|
|
636 |
||
637 |
child_jump = 0; |
|
638 |
}
|
|
639 |
||
640 |
ps_global->noshow_timeout = 0; |
|
641 |
F_SET(F_SHOW_DELAY_CUE, ps_global, old_cue); |
|
642 |
(void) signal(SIGALRM, alarm_sig); |
|
643 |
(void) signal(SIGCHLD, syspipe->chld); |
|
644 |
#endif
|
|
645 |
}
|
|
646 |
else if(flags & OSB_POST_CLOSE){ |
|
647 |
if(syspipe->mode & PIPE_RESET) /* restore our tty modes */ |
|
648 |
ttyfix(1); |
|
649 |
||
650 |
if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ | PIPE_SILENT))){ |
|
651 |
ClearScreen(); /* No I/O to forked child */ |
|
652 |
ps_global->mangled_screen = 1; |
|
653 |
}
|
|
654 |
}
|
|
655 |
}
|
|
656 |
||
657 |
||
658 |
/*
|
|
659 |
* Command interrupt support.
|
|
660 |
*/
|
|
661 |
||
662 |
static RETSIGTYPE |
|
663 |
intr_signal(int sig) |
|
664 |
{
|
|
665 |
ps_global->intr_pending = 1; |
|
666 |
}
|
|
667 |
||
668 |
||
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
669 |
int
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
670 |
intr_handling_on(void) |
671 |
{
|
|
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
672 |
#ifdef _WINDOWS
|
673 |
return 0; /* No interrupts in Windows */ |
|
674 |
#else /* UNIX */ |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
675 |
if(signal(SIGINT, intr_signal) == intr_signal) |
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
676 |
return 0; /* already installed */ |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
677 |
|
678 |
intr_proc(1); |
|
679 |
if(ps_global && ps_global->ttyo) |
|
680 |
draw_cancel_keymenu(); |
|
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
681 |
|
682 |
return 1; |
|
683 |
#endif /* UNIX */ |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
684 |
}
|
685 |
||
686 |
||
687 |
void
|
|
688 |
intr_handling_off(void) |
|
689 |
{
|
|
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
690 |
#ifdef _WINDOWS
|
691 |
#else /* UNIX */ |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
692 |
if(signal(SIGINT, SIG_IGN) == SIG_IGN) /* already off! */ |
693 |
return; |
|
694 |
||
695 |
ps_global->intr_pending = 0; |
|
696 |
intr_proc(0); |
|
697 |
if(ps_global && ps_global->ttyo) |
|
698 |
blank_keymenu(ps_global->ttyo->screen_rows - 2, 0); |
|
699 |
||
700 |
ps_global->mangled_footer = 1; |
|
1.1.7
by Asheesh Laroia
Import upstream version 2.00+dfsg |
701 |
#endif /* UNIX */ |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
702 |
}
|
703 |
||
704 |
||
705 |
/*----------------------------------------------------------------------
|
|
706 |
Set or reset what needs to be set when coming out of pico to run
|
|
707 |
an alternate editor.
|
|
708 |
||
709 |
Args: come_back -- If come_back is 0 we're going out of our environment
|
|
710 |
to set up for an external editor.
|
|
711 |
If come_back is 1 we're coming back into pine.
|
|
712 |
----------------------------------------------------------------------*/
|
|
713 |
int
|
|
714 |
ttyfix(int come_back) |
|
715 |
{
|
|
716 |
#if defined(DEBUG) && (!defined(DOS) || defined(_WINDOWS))
|
|
717 |
if(debugfile) |
|
718 |
fflush(debugfile); |
|
719 |
#endif
|
|
720 |
||
721 |
if(come_back){ |
|
722 |
#ifdef OS2
|
|
723 |
enter_text_mode(NULL); |
|
724 |
#endif
|
|
725 |
init_screen(); |
|
726 |
init_tty_driver(ps_global); |
|
727 |
init_keyboard(F_ON(F_USE_FK,ps_global)); |
|
728 |
#ifdef OS2
|
|
729 |
dont_interrupt(); |
|
730 |
#endif
|
|
731 |
fix_windsize(ps_global); |
|
732 |
}
|
|
733 |
else{ |
|
734 |
EndInverse(); |
|
735 |
end_keyboard(F_ON(F_USE_FK,ps_global)); |
|
736 |
end_tty_driver(ps_global); |
|
737 |
end_screen(NULL, 0); |
|
738 |
#ifdef OS2
|
|
739 |
interrupt_ok(); |
|
740 |
#endif
|
|
741 |
}
|
|
742 |
||
743 |
return(0); |
|
744 |
}
|
|
745 |
||
746 |
||
747 |
/*----------------------------------------------------------------------
|
|
748 |
Suspend Pine. Reset tty and suspend. Suspend is finished when this returns
|
|
749 |
||
750 |
Args: The pine structure
|
|
751 |
||
752 |
Result: Execution suspended for a while. Screen will need redrawing
|
|
753 |
after this is done.
|
|
754 |
||
755 |
Instead of the usual handling of ^Z by catching a signal, we actually read
|
|
756 |
the ^Z and then clean up the tty driver, then kill ourself to stop, and
|
|
757 |
pick up where we left off when execution resumes.
|
|
758 |
----------------------------------------------------------------------*/
|
|
759 |
UCS
|
|
760 |
do_suspend(void) |
|
761 |
{
|
|
762 |
struct pine *pine = ps_global; |
|
763 |
time_t now; |
|
764 |
UCS retval; |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
765 |
#if defined(DOS) || defined(OS2)
|
766 |
int result, orig_cols, orig_rows; |
|
767 |
#else
|
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
768 |
int isremote; |
769 |
#endif
|
|
770 |
#ifdef DOS
|
|
771 |
static char *shell = NULL; |
|
772 |
#define STD_SHELL "COMMAND.COM"
|
|
773 |
#else
|
|
774 |
#ifdef OS2
|
|
775 |
static char *shell = NULL; |
|
776 |
#define STD_SHELL "CMD.EXE"
|
|
777 |
#endif
|
|
778 |
#endif
|
|
779 |
||
780 |
if(!have_job_control()){ |
|
781 |
bogus_command(ctrl('Z'), F_ON(F_USE_FK, pine) ? "F1" : "?"); |
|
782 |
return(NO_OP_COMMAND); |
|
783 |
}
|
|
784 |
||
785 |
if(F_OFF(F_CAN_SUSPEND, pine)){ |
|
786 |
q_status_message(SM_ORDER | SM_DING, 3, 3, |
|
787 |
_("Alpine suspension not enabled - see help text")); |
|
788 |
return(NO_OP_COMMAND); |
|
789 |
}
|
|
790 |
||
791 |
#ifdef _WINDOWS
|
|
792 |
mswin_minimize(); |
|
793 |
return(NO_OP_COMMAND); |
|
794 |
#else
|
|
795 |
||
796 |
isremote = (ps_global->mail_stream && ps_global->mail_stream->mailbox |
|
797 |
&& (*ps_global->mail_stream->mailbox == '{' |
|
798 |
|| (*ps_global->mail_stream->mailbox == '*' |
|
799 |
&& *(ps_global->mail_stream->mailbox + 1) == '{'))); |
|
800 |
||
801 |
now = time((time_t *)0); |
|
802 |
dprint((1, "\n\n --- %s - SUSPEND ---- %s", |
|
803 |
isremote ? "REMOTE" : "LOCAL", ctime(&now))); |
|
804 |
ttyfix(0); |
|
805 |
||
806 |
#if defined(DOS) || defined(OS2)
|
|
807 |
suspend_notice("exit"); |
|
808 |
if (!shell){ |
|
809 |
char *p; |
|
810 |
||
811 |
if (!((shell = getenv("SHELL")) || (shell = getenv("COMSPEC")))) |
|
812 |
shell = STD_SHELL; |
|
813 |
||
814 |
shell = cpystr(shell); /* copy in free storage */ |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
815 |
for(p = shell; (p = strchr(p, '/')); p++) |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
816 |
*p = '\\'; |
817 |
}
|
|
818 |
||
819 |
result = system(shell); |
|
820 |
#else
|
|
821 |
if(F_ON(F_SUSPEND_SPAWNS, ps_global)){ |
|
822 |
PIPE_S *syspipe; |
|
1.1.10
by Asheesh Laroia
Import upstream version 2.10+dfsg |
823 |
int flag = some_stream_is_locked() ? PIPE_NONEWMAIL : 0; |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
824 |
|
1.1.10
by Asheesh Laroia
Import upstream version 2.10+dfsg |
825 |
flag |= PIPE_USER|PIPE_RESET; |
826 |
if((syspipe = open_system_pipe(NULL, NULL, NULL, flag, |
|
1.1.3
by Asheesh Laroia
Import upstream version 0.9999+dfsg |
827 |
0, pipe_callback, pipe_report_error)) != NULL){ |
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
828 |
suspend_notice("exit"); |
829 |
#ifndef SIGCHLD
|
|
830 |
if(isremote) |
|
831 |
suspend_warning(); |
|
832 |
#endif
|
|
833 |
(void) close_system_pipe(&syspipe, NULL, pipe_callback); |
|
834 |
}
|
|
835 |
}
|
|
836 |
else{ |
|
837 |
suspend_notice("fg"); |
|
838 |
||
839 |
if(isremote) |
|
840 |
suspend_warning(); |
|
841 |
||
842 |
stop_process(); |
|
843 |
}
|
|
844 |
#endif /* DOS */ |
|
845 |
||
846 |
now = time((time_t *)0); |
|
847 |
dprint((1, "\n\n ---- RETURN FROM SUSPEND ---- %s", |
|
848 |
ctime(&now))); |
|
849 |
||
850 |
ttyfix(1); |
|
851 |
||
852 |
#if defined(DOS) || defined(OS2)
|
|
853 |
orig_cols = pine->ttyo->screen_cols; |
|
854 |
orig_rows = pine->ttyo->screen_rows; |
|
855 |
#endif
|
|
856 |
||
857 |
fix_windsize(pine); |
|
858 |
||
859 |
#if defined(DOS) || defined(OS2)
|
|
860 |
if(orig_cols != pine->ttyo->screen_cols || |
|
861 |
orig_rows != pine->ttyo->screen_rows) |
|
862 |
retval = KEY_RESIZE; |
|
863 |
else
|
|
864 |
#endif
|
|
865 |
retval = ctrl('L');; |
|
866 |
||
867 |
#if defined(DOS) || defined(OS2)
|
|
868 |
if(result == -1) |
|
869 |
q_status_message1(SM_ORDER | SM_DING, 3, 4, |
|
870 |
_("Error loading \"%s\""), shell); |
|
871 |
#endif
|
|
872 |
||
1.1.10
by Asheesh Laroia
Import upstream version 2.10+dfsg |
873 |
if(isremote && !ps_global->mail_stream->lock |
874 |
&& !pine_mail_ping(ps_global->mail_stream)) |
|
1
by Asheesh Laroia
Import upstream version 0.82+dfsg |
875 |
q_status_message(SM_ORDER | SM_DING, 4, 9, |
876 |
_("Suspended for too long, IMAP connection broken")); |
|
877 |
||
878 |
return(retval); |
|
879 |
#endif /* !_WINDOWS */ |
|
880 |
}
|
|
881 |
||
882 |
||
883 |
||
884 |
/*----------------------------------------------------------------------
|
|
885 |
----*/
|
|
886 |
void
|
|
887 |
suspend_notice(char *s) |
|
888 |
{
|
|
889 |
printf(_("\nAlpine suspended. Give the \"%s\" command to come back.\n"), s); |
|
890 |
fflush(stdout); |
|
891 |
}
|
|
892 |
||
893 |
||
894 |
/*----------------------------------------------------------------------
|
|
895 |
----*/
|
|
896 |
void
|
|
897 |
suspend_warning(void) |
|
898 |
{
|
|
899 |
puts(_("Warning: Your IMAP connection will be closed if Alpine")); |
|
900 |
puts(_("is suspended for more than 30 minutes\n")); |
|
901 |
fflush(stdout); |
|
902 |
}
|
|
903 |
||
904 |
||
905 |
/*----------------------------------------------------------------------
|
|
906 |
----*/
|
|
907 |
void
|
|
908 |
fix_windsize(struct pine *pine) |
|
909 |
{
|
|
910 |
int old_width = pine->ttyo->screen_cols; |
|
911 |
||
912 |
dprint((9, "fix_windsize()\n")); |
|
913 |
mark_keymenu_dirty(); |
|
914 |
mark_status_dirty(); |
|
915 |
mark_titlebar_dirty(); |
|
916 |
clear_cursor_pos(); |
|
917 |
get_windsize(pine->ttyo); |
|
918 |
||
919 |
if(old_width != pine->ttyo->screen_cols) |
|
920 |
clear_index_cache(pine->mail_stream, 0); |
|
921 |
}
|