~ubuntu-branches/debian/stretch/alpine/stretch

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
}