signals.c revision 21496
1219820Sjeff/* signals.c -- Install and maintain Info signal handlers. */
2219820Sjeff
3219820Sjeff/* This file is part of GNU Info, a program for reading online documentation
4219820Sjeff   stored in Info format.
5219820Sjeff
6219820Sjeff   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
7219820Sjeff
8219820Sjeff   This program is free software; you can redistribute it and/or modify
9219820Sjeff   it under the terms of the GNU General Public License as published by
10219820Sjeff   the Free Software Foundation; either version 2, or (at your option)
11219820Sjeff   any later version.
12219820Sjeff
13219820Sjeff   This program is distributed in the hope that it will be useful,
14219820Sjeff   but WITHOUT ANY WARRANTY; without even the implied warranty of
15219820Sjeff   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16219820Sjeff   GNU General Public License for more details.
17219820Sjeff
18219820Sjeff   You should have received a copy of the GNU General Public License
19219820Sjeff   along with this program; if not, write to the Free Software
20219820Sjeff   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21219820Sjeff
22219820Sjeff   Written by Brian Fox (bfox@ai.mit.edu). */
23219820Sjeff
24219820Sjeff#include "info.h"
25219820Sjeff#include "signals.h"
26219820Sjeff
27219820Sjeff/* **************************************************************** */
28219820Sjeff/*								    */
29219820Sjeff/*		Pretending That We Have POSIX Signals		    */
30219820Sjeff/*								    */
31219820Sjeff/* **************************************************************** */
32219820Sjeff
33219820Sjeff#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
34219820Sjeff/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
35219820Sjeffstatic void
36219820Sjeffsigprocmask (operation, newset, oldset)
37219820Sjeff     int operation, *newset, *oldset;
38219820Sjeff{
39219820Sjeff  switch (operation)
40219820Sjeff    {
41219820Sjeff    case SIG_UNBLOCK:
42219820Sjeff      sigsetmask (sigblock (0) & ~(*newset));
43219820Sjeff      break;
44219820Sjeff
45219820Sjeff    case SIG_BLOCK:
46219820Sjeff      *oldset = sigblock (*newset);
47219820Sjeff      break;
48219820Sjeff
49219820Sjeff    case SIG_SETMASK:
50219820Sjeff      sigsetmask (*newset);
51219820Sjeff      break;
52219820Sjeff
53219820Sjeff    default:
54219820Sjeff      abort ();
55219820Sjeff    }
56219820Sjeff}
57219820Sjeff#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
58219820Sjeff
59219820Sjeff/* **************************************************************** */
60219820Sjeff/*								    */
61219820Sjeff/*		    Signal Handling for Info			    */
62219820Sjeff/*								    */
63219820Sjeff/* **************************************************************** */
64219820Sjeff
65219820Sjefftypedef void SigHandlerType;
66219820Sjefftypedef SigHandlerType SigHandler ();
67219820Sjeff
68219820Sjeffstatic SigHandlerType info_signal_handler ();
69219820Sjeffstatic SigHandler *old_TSTP, *old_TTOU, *old_TTIN;
70219820Sjeffstatic SigHandler *old_WINCH, *old_INT;
71219820Sjeff
72219820Sjeffvoid
73219820Sjeffinitialize_info_signal_handler ()
74219820Sjeff{
75219820Sjeff#if defined (SIGTSTP)
76219820Sjeff  old_TSTP = (SigHandler *) signal (SIGTSTP, info_signal_handler);
77219820Sjeff  old_TTOU = (SigHandler *) signal (SIGTTOU, info_signal_handler);
78219820Sjeff  old_TTIN = (SigHandler *) signal (SIGTTIN, info_signal_handler);
79219820Sjeff#endif /* SIGTSTP */
80219820Sjeff
81219820Sjeff#if defined (SIGWINCH)
82219820Sjeff  old_WINCH = (SigHandler *) signal (SIGWINCH, info_signal_handler);
83219820Sjeff#endif
84219820Sjeff
85219820Sjeff#if defined (SIGINT)
86219820Sjeff  old_INT = (SigHandler *) signal (SIGINT, info_signal_handler);
87219820Sjeff#endif
88219820Sjeff}
89219820Sjeff
90219820Sjeffstatic void
91219820Sjeffredisplay_after_signal ()
92219820Sjeff{
93219820Sjeff  terminal_clear_screen ();
94219820Sjeff  display_clear_display (the_display);
95219820Sjeff  window_mark_chain (windows, W_UpdateWindow);
96219820Sjeff  display_update_display (windows);
97219820Sjeff  display_cursor_at_point (active_window);
98219820Sjeff  fflush (stdout);
99219820Sjeff}
100219820Sjeff
101219820Sjeffstatic SigHandlerType
102219820Sjeffinfo_signal_handler (sig)
103219820Sjeff     int sig;
104219820Sjeff{
105219820Sjeff  SigHandler **old_signal_handler;
106219820Sjeff
107219820Sjeff  switch (sig)
108219820Sjeff    {
109219820Sjeff#if defined (SIGTSTP)
110219820Sjeff    case SIGTSTP:
111219820Sjeff    case SIGTTOU:
112219820Sjeff    case SIGTTIN:
113219820Sjeff#endif
114219820Sjeff#if defined (SIGINT)
115219820Sjeff    case SIGINT:
116219820Sjeff#endif
117219820Sjeff      {
118219820Sjeff#if defined (SIGTSTP)
119219820Sjeff	if (sig == SIGTSTP)
120219820Sjeff	  old_signal_handler = &old_TSTP;
121219820Sjeff	if (sig == SIGTTOU)
122219820Sjeff	  old_signal_handler = &old_TTOU;
123219820Sjeff	if (sig == SIGTTIN)
124219820Sjeff	  old_signal_handler = &old_TTIN;
125219820Sjeff#endif /* SIGTSTP */
126219820Sjeff	if (sig == SIGINT)
127219820Sjeff	  old_signal_handler = &old_INT;
128219820Sjeff
129219820Sjeff	/* For stop signals, restore the terminal IO, leave the cursor
130219820Sjeff	   at the bottom of the window, and stop us. */
131219820Sjeff	terminal_goto_xy (0, screenheight - 1);
132219820Sjeff	terminal_clear_to_eol ();
133219820Sjeff	fflush (stdout);
134219820Sjeff	terminal_unprep_terminal ();
135219820Sjeff	signal (sig, *old_signal_handler);
136219820Sjeff 	UNBLOCK_SIGNAL (sig);
137219820Sjeff	kill (getpid (), sig);
138219820Sjeff
139219820Sjeff	/* The program is returning now.  Restore our signal handler,
140219820Sjeff	   turn on terminal handling, redraw the screen, and place the
141219820Sjeff	   cursor where it belongs. */
142219820Sjeff	terminal_prep_terminal ();
143219820Sjeff	*old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
144219820Sjeff	redisplay_after_signal ();
145219820Sjeff	fflush (stdout);
146219820Sjeff      }
147219820Sjeff      break;
148219820Sjeff
149219820Sjeff#if defined (SIGWINCH)
150219820Sjeff    case SIGWINCH:
151219820Sjeff      {
152219820Sjeff	/* Turn off terminal IO, tell our parent that the window has changed,
153219820Sjeff	   then reinitialize the terminal and rebuild our windows. */
154243882Sglebius	old_signal_handler = &old_WINCH;
155219820Sjeff	terminal_goto_xy (0, 0);
156219820Sjeff	fflush (stdout);
157219820Sjeff	terminal_unprep_terminal ();
158219820Sjeff	signal (sig, *old_signal_handler);
159219820Sjeff 	UNBLOCK_SIGNAL (sig);
160219820Sjeff	kill (getpid (), sig);
161219820Sjeff
162219820Sjeff	/* After our old signal handler returns... */
163219820Sjeff	terminal_get_screen_size ();
164219820Sjeff	terminal_prep_terminal ();
165219820Sjeff	display_initialize_display (screenwidth, screenheight);
166219820Sjeff	window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL);
167219820Sjeff	*old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
168219820Sjeff	redisplay_after_signal ();
169219820Sjeff      }
170219820Sjeff      break;
171219820Sjeff#endif /* SIGWINCH */
172219820Sjeff    }
173219820Sjeff}
174219820Sjeff