signals.c revision 116535
156165Sru/* signals.c -- install and maintain Info signal handlers.
2114478Sru   $Id: signals.c,v 1.4 2003/01/29 19:23:22 karl Exp $
321495Sjmacd
4114478Sru   Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003 Free Software
5114478Sru   Foundation, Inc.
621495Sjmacd
721495Sjmacd   This program is free software; you can redistribute it and/or modify
821495Sjmacd   it under the terms of the GNU General Public License as published by
921495Sjmacd   the Free Software Foundation; either version 2, or (at your option)
1021495Sjmacd   any later version.
1121495Sjmacd
1221495Sjmacd   This program is distributed in the hope that it will be useful,
1321495Sjmacd   but WITHOUT ANY WARRANTY; without even the implied warranty of
1421495Sjmacd   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1521495Sjmacd   GNU General Public License for more details.
1621495Sjmacd
1721495Sjmacd   You should have received a copy of the GNU General Public License
1821495Sjmacd   along with this program; if not, write to the Free Software
1921495Sjmacd   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2021495Sjmacd
2121495Sjmacd   Written by Brian Fox (bfox@ai.mit.edu). */
2221495Sjmacd
2321495Sjmacd#include "info.h"
2421495Sjmacd#include "signals.h"
2521495Sjmacd
2621495Sjmacd/* **************************************************************** */
2742664Smarkm/*                                                                  */
2842664Smarkm/*              Pretending That We Have POSIX Signals               */
2942664Smarkm/*                                                                  */
3021495Sjmacd/* **************************************************************** */
3121495Sjmacd
3221495Sjmacd#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
3321495Sjmacd/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
3421495Sjmacdstatic void
3521495Sjmacdsigprocmask (operation, newset, oldset)
3621495Sjmacd     int operation, *newset, *oldset;
3721495Sjmacd{
3821495Sjmacd  switch (operation)
3921495Sjmacd    {
4021495Sjmacd    case SIG_UNBLOCK:
4121495Sjmacd      sigsetmask (sigblock (0) & ~(*newset));
4221495Sjmacd      break;
4321495Sjmacd
4421495Sjmacd    case SIG_BLOCK:
4521495Sjmacd      *oldset = sigblock (*newset);
4621495Sjmacd      break;
4721495Sjmacd
4821495Sjmacd    case SIG_SETMASK:
4921495Sjmacd      sigsetmask (*newset);
5021495Sjmacd      break;
5121495Sjmacd
5221495Sjmacd    default:
5321495Sjmacd      abort ();
5421495Sjmacd    }
5521495Sjmacd}
5621495Sjmacd#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
5721495Sjmacd
5821495Sjmacd/* **************************************************************** */
5942664Smarkm/*                                                                  */
6042664Smarkm/*                  Signal Handling for Info                        */
6142664Smarkm/*                                                                  */
6221495Sjmacd/* **************************************************************** */
6321495Sjmacd
64114478Sru#if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
65114478Sru  defined (HAVE_SIGSETMASK)
66114478Srustatic void
67114478Srumask_termsig (set)
68114478Sru  sigset_t *set;
69114478Sru{
70114478Sru# if defined (SIGTSTP)
71114478Sru  sigaddset (set, SIGTSTP);
72114478Sru  sigaddset (set, SIGTTOU);
73114478Sru  sigaddset (set, SIGTTIN);
74114478Sru# endif
75114478Sru# if defined (SIGWINCH)
76114478Sru  sigaddset (set, SIGWINCH);
77114478Sru# endif
78114478Sru#if defined (SIGINT)
79114478Sru  sigaddset (set, SIGINT);
80114478Sru#endif
81114478Sru# if defined (SIGUSR1)
82114478Sru  sigaddset (set, SIGUSR1);
83114478Sru# endif
84114478Sru}
85114478Sru#endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
8621495Sjmacd
87114478Srustatic RETSIGTYPE info_signal_proc ();
88114478Sru#if defined (HAVE_SIGACTION)
89114478Srutypedef struct sigaction signal_info;
90114478Srusignal_info info_signal_handler;
9121495Sjmacd
92114478Srustatic void
93114478Sruset_termsig (sig, old)
94114478Sru  int sig;
95114478Sru  signal_info *old;
96114478Sru{
97114478Sru  sigaction (sig, &info_signal_handler, old);
98114478Sru}
99114478Sru
100114478Srustatic void
101114478Srurestore_termsig (sig, saved)
102114478Sru  int sig;
103114478Sru  const signal_info *saved;
104114478Sru{
105114478Sru  sigaction (sig, saved, NULL);
106114478Sru}
107114478Sru#else /* !HAVE_SIGACTION */
108114478Srutypedef RETSIGTYPE (*signal_info) ();
109114478Sru#define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
110114478Sru#define restore_termsig(sig, saved) (void)signal (sig, *(saved))
111114478Sru#define info_signal_handler info_signal_proc
112114478Srustatic int term_conf_busy = 0;
113114478Sru#endif /* !HAVE_SIGACTION */
114114478Sru
115114478Srustatic signal_info old_TSTP, old_TTOU, old_TTIN;
116116535Srustatic signal_info old_WINCH, old_INT, old_USR1;
117114478Sru
11821495Sjmacdvoid
11921495Sjmacdinitialize_info_signal_handler ()
12021495Sjmacd{
121114478Sru#if defined (HAVE_SIGACTION)
122114478Sru  info_signal_handler.sa_handler = info_signal_proc;
123114478Sru  info_signal_handler.sa_flags = 0;
124114478Sru  mask_termsig (&info_signal_handler.sa_mask);
125114478Sru#endif /* HAVE_SIGACTION */
126114478Sru
12721495Sjmacd#if defined (SIGTSTP)
128114478Sru  set_termsig (SIGTSTP, &old_TSTP);
129114478Sru  set_termsig (SIGTTOU, &old_TTOU);
130114478Sru  set_termsig (SIGTTIN, &old_TTIN);
13121495Sjmacd#endif /* SIGTSTP */
13221495Sjmacd
13321495Sjmacd#if defined (SIGWINCH)
134114478Sru  set_termsig (SIGWINCH, &old_WINCH);
13542664Smarkm#endif
13621495Sjmacd
13721495Sjmacd#if defined (SIGINT)
138114478Sru  set_termsig (SIGINT, &old_INT);
13921495Sjmacd#endif
14056165Sru
14156165Sru#if defined (SIGUSR1)
14256165Sru  /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z.  */
143114478Sru  set_termsig (SIGUSR1, &old_USR1);
14456165Sru#endif
14521495Sjmacd}
14621495Sjmacd
14721495Sjmacdstatic void
14821495Sjmacdredisplay_after_signal ()
14921495Sjmacd{
15021495Sjmacd  terminal_clear_screen ();
15121495Sjmacd  display_clear_display (the_display);
15221495Sjmacd  window_mark_chain (windows, W_UpdateWindow);
15321495Sjmacd  display_update_display (windows);
15421495Sjmacd  display_cursor_at_point (active_window);
15521495Sjmacd  fflush (stdout);
15621495Sjmacd}
15721495Sjmacd
15856165Srustatic void
15956165Srureset_info_window_sizes ()
16056165Sru{
16156165Sru  terminal_goto_xy (0, 0);
16256165Sru  fflush (stdout);
16356165Sru  terminal_unprep_terminal ();
16456165Sru  terminal_get_screen_size ();
16556165Sru  terminal_prep_terminal ();
16656165Sru  display_initialize_display (screenwidth, screenheight);
16756165Sru  window_new_screen_size (screenwidth, screenheight, NULL);
16856165Sru  redisplay_after_signal ();
16956165Sru}
17056165Sru
17142664Smarkmstatic RETSIGTYPE
172114478Sruinfo_signal_proc (sig)
17321495Sjmacd     int sig;
17421495Sjmacd{
175114478Sru  signal_info *old_signal_handler;
17621495Sjmacd
177114478Sru#if !defined (HAVE_SIGACTION)
178114478Sru  /* best effort: first increment this counter and later block signals */
179114478Sru  if (term_conf_busy)
180114478Sru    return;
181114478Sru  term_conf_busy++;
182114478Sru#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
183114478Sru    {
184114478Sru      sigset_t nvar, ovar;
185114478Sru      sigemptyset (&nvar);
186114478Sru      mask_termsig (&nvar);
187114478Sru      sigprocmask (SIG_BLOCK, &nvar, &ovar);
188114478Sru    }
189114478Sru#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
190114478Sru#endif /* !HAVE_SIGACTION */
19121495Sjmacd  switch (sig)
19221495Sjmacd    {
19321495Sjmacd#if defined (SIGTSTP)
19421495Sjmacd    case SIGTSTP:
19521495Sjmacd    case SIGTTOU:
19621495Sjmacd    case SIGTTIN:
19721495Sjmacd#endif
19821495Sjmacd#if defined (SIGINT)
19921495Sjmacd    case SIGINT:
20021495Sjmacd#endif
20121495Sjmacd      {
20221495Sjmacd#if defined (SIGTSTP)
20342664Smarkm        if (sig == SIGTSTP)
20442664Smarkm          old_signal_handler = &old_TSTP;
20542664Smarkm        if (sig == SIGTTOU)
20642664Smarkm          old_signal_handler = &old_TTOU;
20742664Smarkm        if (sig == SIGTTIN)
20842664Smarkm          old_signal_handler = &old_TTIN;
20921495Sjmacd#endif /* SIGTSTP */
210114478Sru#if defined (SIGINT)
21142664Smarkm        if (sig == SIGINT)
21242664Smarkm          old_signal_handler = &old_INT;
213114478Sru#endif /* SIGINT */
21421495Sjmacd
21542664Smarkm        /* For stop signals, restore the terminal IO, leave the cursor
21642664Smarkm           at the bottom of the window, and stop us. */
21742664Smarkm        terminal_goto_xy (0, screenheight - 1);
21842664Smarkm        terminal_clear_to_eol ();
21942664Smarkm        fflush (stdout);
22042664Smarkm        terminal_unprep_terminal ();
221114478Sru	restore_termsig (sig, old_signal_handler);
222114478Sru	UNBLOCK_SIGNAL (sig);
223114478Sru	kill (getpid (), sig);
22421495Sjmacd
22542664Smarkm        /* The program is returning now.  Restore our signal handler,
22642664Smarkm           turn on terminal handling, redraw the screen, and place the
22742664Smarkm           cursor where it belongs. */
22842664Smarkm        terminal_prep_terminal ();
229114478Sru	set_termsig (sig, old_signal_handler);
230114478Sru	/* window size might be changed while sleeping */
231114478Sru	reset_info_window_sizes ();
23221495Sjmacd      }
23321495Sjmacd      break;
23421495Sjmacd
23556165Sru#if defined (SIGWINCH) || defined (SIGUSR1)
23656165Sru#ifdef SIGWINCH
23721495Sjmacd    case SIGWINCH:
23856165Sru#endif
23956165Sru#ifdef SIGUSR1
24056165Sru    case SIGUSR1:
24156165Sru#endif
24221495Sjmacd      {
243114478Sru	/* Turn off terminal IO, tell our parent that the window has changed,
244114478Sru	   then reinitialize the terminal and rebuild our windows. */
24556165Sru#ifdef SIGWINCH
246114478Sru	if (sig == SIGWINCH)
247114478Sru	  old_signal_handler = &old_WINCH;
24856165Sru#endif
24956165Sru#ifdef SIGUSR1
250114478Sru	if (sig == SIGUSR1)
251114478Sru	  old_signal_handler = &old_USR1;
25256165Sru#endif
253114478Sru	terminal_goto_xy (0, 0);
254114478Sru	fflush (stdout);
255114478Sru	terminal_unprep_terminal (); /* needless? */
256114478Sru	restore_termsig (sig, old_signal_handler);
257114478Sru	UNBLOCK_SIGNAL (sig);
258114478Sru	kill (getpid (), sig);
25921495Sjmacd
260114478Sru	/* After our old signal handler returns... */
261114478Sru	set_termsig (sig, old_signal_handler); /* needless? */
262114478Sru	terminal_prep_terminal ();
263114478Sru	reset_info_window_sizes ();
26421495Sjmacd      }
26521495Sjmacd      break;
26656165Sru#endif /* SIGWINCH || SIGUSR1 */
26721495Sjmacd    }
268114478Sru#if !defined (HAVE_SIGACTION)
269114478Sru  /* at this time it is safer to perform unblock after decrement */
270114478Sru  term_conf_busy--;
271114478Sru#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
272114478Sru    {
273114478Sru      sigset_t nvar, ovar;
274114478Sru      sigemptyset (&nvar);
275114478Sru      mask_termsig (&nvar);
276114478Sru      sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
277114478Sru    }
278114478Sru#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
279114478Sru#endif /* !HAVE_SIGACTION */
28021495Sjmacd}
281114478Sru/* vim: set sw=2 cino={1s>2sn-s^-se-s: */
282