freebsd-dev/contrib/texinfo/info/signals.c

185 lines
5.7 KiB
C

/* signals.c -- Install and maintain Info signal handlers. */
/* This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Written by Brian Fox (bfox@ai.mit.edu). */
#include "info.h"
#include "signals.h"
/* **************************************************************** */
/* */
/* Pretending That We Have POSIX Signals */
/* */
/* **************************************************************** */
#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
static void
sigprocmask (operation, newset, oldset)
int operation, *newset, *oldset;
{
switch (operation)
{
case SIG_UNBLOCK:
sigsetmask (sigblock (0) & ~(*newset));
break;
case SIG_BLOCK:
*oldset = sigblock (*newset);
break;
case SIG_SETMASK:
sigsetmask (*newset);
break;
default:
abort ();
}
}
#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
/* **************************************************************** */
/* */
/* Signal Handling for Info */
/* */
/* **************************************************************** */
typedef RETSIGTYPE signal_handler ();
static RETSIGTYPE info_signal_handler ();
static signal_handler *old_TSTP, *old_TTOU, *old_TTIN;
static signal_handler *old_WINCH, *old_INT, *old_CONT;
void
initialize_info_signal_handler ()
{
#if defined (SIGTSTP)
old_TSTP = (signal_handler *) signal (SIGTSTP, info_signal_handler);
old_TTOU = (signal_handler *) signal (SIGTTOU, info_signal_handler);
old_TTIN = (signal_handler *) signal (SIGTTIN, info_signal_handler);
#endif /* SIGTSTP */
#if defined (SIGWINCH)
old_WINCH = (signal_handler *) signal (SIGWINCH, info_signal_handler);
#if defined (SIGCONT)
old_CONT = (signal_handler *) signal (SIGCONT, info_signal_handler);
#endif /* SIGCONT */
#endif
#if defined (SIGINT)
old_INT = (signal_handler *) signal (SIGINT, info_signal_handler);
#endif
}
static void
redisplay_after_signal ()
{
terminal_clear_screen ();
display_clear_display (the_display);
window_mark_chain (windows, W_UpdateWindow);
display_update_display (windows);
display_cursor_at_point (active_window);
fflush (stdout);
}
static RETSIGTYPE
info_signal_handler (sig)
int sig;
{
signal_handler **old_signal_handler;
switch (sig)
{
#if defined (SIGTSTP)
case SIGTSTP:
case SIGTTOU:
case SIGTTIN:
#endif
#if defined (SIGINT)
case SIGINT:
#endif
{
#if defined (SIGTSTP)
if (sig == SIGTSTP)
old_signal_handler = &old_TSTP;
if (sig == SIGTTOU)
old_signal_handler = &old_TTOU;
if (sig == SIGTTIN)
old_signal_handler = &old_TTIN;
#endif /* SIGTSTP */
if (sig == SIGINT)
old_signal_handler = &old_INT;
/* For stop signals, restore the terminal IO, leave the cursor
at the bottom of the window, and stop us. */
terminal_goto_xy (0, screenheight - 1);
terminal_clear_to_eol ();
fflush (stdout);
terminal_unprep_terminal ();
signal (sig, *old_signal_handler);
UNBLOCK_SIGNAL (sig);
kill (getpid (), sig);
/* The program is returning now. Restore our signal handler,
turn on terminal handling, redraw the screen, and place the
cursor where it belongs. */
terminal_prep_terminal ();
*old_signal_handler = (signal_handler *) signal (sig, info_signal_handler);
redisplay_after_signal ();
fflush (stdout);
}
break;
#if defined (SIGWINCH)
#if defined(SIGCONT)
case SIGCONT:
if (old_CONT)
(void)(old_CONT)(sig);
/* pretend a SIGWINCH in case the terminal window size has changed
while we've been asleep */
/* FALLTROUGH */
#endif /* defined(SIGCONT) */
case SIGWINCH:
{
/* Turn off terminal IO, tell our parent that the window has changed,
then reinitialize the terminal and rebuild our windows. */
old_signal_handler = &old_WINCH;
terminal_goto_xy (0, 0);
fflush (stdout);
terminal_unprep_terminal ();
signal (sig, *old_signal_handler);
UNBLOCK_SIGNAL (sig);
kill (getpid (), sig);
/* After our old signal handler returns... */
terminal_get_screen_size ();
terminal_prep_terminal ();
display_initialize_display (screenwidth, screenheight);
window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL);
*old_signal_handler = (signal_handler *) signal (sig, info_signal_handler);
redisplay_after_signal ();
}
break;
#endif /* SIGWINCH */
}
}