6285cf0f68
Major changes since 4.3: * Language: . The ' (ASCII apostrophe/right quote) character is finally allowed in node and anchor names. Thus, after installing this texinfo.tex, existing .aux files will cause errors! Remove them and rerun TeX to generate good ones. . @value constructs are now expanded in the filename arguments to @include and @verbatiminclude. * texinfo.tex: . @smallexample and the like now output in a smaller font (9pt) in all paper formats, not just @smallbook and @afourpaper. . new translation txi-tr.tex. * info: . CTRL-H is treated like DEL in incremental search. . arrow keys once again work in isearch contexts under Solaris. * infokey: . use .info key bindings before defaults. . allow prefix keys to be disabled. Bug fixes all around.
284 lines
7.7 KiB
C
284 lines
7.7 KiB
C
/* $NetBSD: signals.c,v 1.1.1.4 2003/02/13 08:50:53 wiz Exp $ */
|
|
|
|
/* signals.c -- install and maintain Info signal handlers.
|
|
Id: signals.c,v 1.4 2003/01/29 19:23:22 karl Exp
|
|
|
|
Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003 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 */
|
|
/* */
|
|
/* **************************************************************** */
|
|
|
|
#if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
|
|
defined (HAVE_SIGSETMASK)
|
|
static void
|
|
mask_termsig (set)
|
|
sigset_t *set;
|
|
{
|
|
# if defined (SIGTSTP)
|
|
sigaddset (set, SIGTSTP);
|
|
sigaddset (set, SIGTTOU);
|
|
sigaddset (set, SIGTTIN);
|
|
# endif
|
|
# if defined (SIGWINCH)
|
|
sigaddset (set, SIGWINCH);
|
|
# endif
|
|
#if defined (SIGINT)
|
|
sigaddset (set, SIGINT);
|
|
#endif
|
|
# if defined (SIGUSR1)
|
|
sigaddset (set, SIGUSR1);
|
|
# endif
|
|
}
|
|
#endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
|
|
|
|
static RETSIGTYPE info_signal_proc ();
|
|
#if defined (HAVE_SIGACTION)
|
|
typedef struct sigaction signal_info;
|
|
signal_info info_signal_handler;
|
|
|
|
static void
|
|
set_termsig (sig, old)
|
|
int sig;
|
|
signal_info *old;
|
|
{
|
|
sigaction (sig, &info_signal_handler, old);
|
|
}
|
|
|
|
static void
|
|
restore_termsig (sig, saved)
|
|
int sig;
|
|
const signal_info *saved;
|
|
{
|
|
sigaction (sig, saved, NULL);
|
|
}
|
|
#else /* !HAVE_SIGACTION */
|
|
typedef RETSIGTYPE (*signal_info) ();
|
|
#define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
|
|
#define restore_termsig(sig, saved) (void)signal (sig, *(saved))
|
|
#define info_signal_handler info_signal_proc
|
|
static int term_conf_busy = 0;
|
|
#endif /* !HAVE_SIGACTION */
|
|
|
|
static signal_info old_TSTP, old_TTOU, old_TTIN;
|
|
static signal_info old_WINCH, old_INT, old_USR1;
|
|
|
|
void
|
|
initialize_info_signal_handler ()
|
|
{
|
|
#if defined (HAVE_SIGACTION)
|
|
info_signal_handler.sa_handler = info_signal_proc;
|
|
info_signal_handler.sa_flags = 0;
|
|
mask_termsig (&info_signal_handler.sa_mask);
|
|
#endif /* HAVE_SIGACTION */
|
|
|
|
#if defined (SIGTSTP)
|
|
set_termsig (SIGTSTP, &old_TSTP);
|
|
set_termsig (SIGTTOU, &old_TTOU);
|
|
set_termsig (SIGTTIN, &old_TTIN);
|
|
#endif /* SIGTSTP */
|
|
|
|
#if defined (SIGWINCH)
|
|
set_termsig (SIGWINCH, &old_WINCH);
|
|
#endif
|
|
|
|
#if defined (SIGINT)
|
|
set_termsig (SIGINT, &old_INT);
|
|
#endif
|
|
|
|
#if defined (SIGUSR1)
|
|
/* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */
|
|
set_termsig (SIGUSR1, &old_USR1);
|
|
#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 void
|
|
reset_info_window_sizes ()
|
|
{
|
|
terminal_goto_xy (0, 0);
|
|
fflush (stdout);
|
|
terminal_unprep_terminal ();
|
|
terminal_get_screen_size ();
|
|
terminal_prep_terminal ();
|
|
display_initialize_display (screenwidth, screenheight);
|
|
window_new_screen_size (screenwidth, screenheight, NULL);
|
|
redisplay_after_signal ();
|
|
}
|
|
|
|
static RETSIGTYPE
|
|
info_signal_proc (sig)
|
|
int sig;
|
|
{
|
|
signal_info *old_signal_handler;
|
|
|
|
#if !defined (HAVE_SIGACTION)
|
|
/* best effort: first increment this counter and later block signals */
|
|
if (term_conf_busy)
|
|
return;
|
|
term_conf_busy++;
|
|
#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
|
|
{
|
|
sigset_t nvar, ovar;
|
|
sigemptyset (&nvar);
|
|
mask_termsig (&nvar);
|
|
sigprocmask (SIG_BLOCK, &nvar, &ovar);
|
|
}
|
|
#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
|
|
#endif /* !HAVE_SIGACTION */
|
|
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 defined (SIGINT)
|
|
if (sig == SIGINT)
|
|
old_signal_handler = &old_INT;
|
|
#endif /* SIGINT */
|
|
|
|
/* 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 ();
|
|
restore_termsig (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 ();
|
|
set_termsig (sig, old_signal_handler);
|
|
/* window size might be changed while sleeping */
|
|
reset_info_window_sizes ();
|
|
}
|
|
break;
|
|
|
|
#if defined (SIGWINCH) || defined (SIGUSR1)
|
|
#ifdef SIGWINCH
|
|
case SIGWINCH:
|
|
#endif
|
|
#ifdef SIGUSR1
|
|
case SIGUSR1:
|
|
#endif
|
|
{
|
|
/* Turn off terminal IO, tell our parent that the window has changed,
|
|
then reinitialize the terminal and rebuild our windows. */
|
|
#ifdef SIGWINCH
|
|
if (sig == SIGWINCH)
|
|
old_signal_handler = &old_WINCH;
|
|
#endif
|
|
#ifdef SIGUSR1
|
|
if (sig == SIGUSR1)
|
|
old_signal_handler = &old_USR1;
|
|
#endif
|
|
terminal_goto_xy (0, 0);
|
|
fflush (stdout);
|
|
terminal_unprep_terminal (); /* needless? */
|
|
restore_termsig (sig, old_signal_handler);
|
|
UNBLOCK_SIGNAL (sig);
|
|
kill (getpid (), sig);
|
|
|
|
/* After our old signal handler returns... */
|
|
set_termsig (sig, old_signal_handler); /* needless? */
|
|
terminal_prep_terminal ();
|
|
reset_info_window_sizes ();
|
|
}
|
|
break;
|
|
#endif /* SIGWINCH || SIGUSR1 */
|
|
}
|
|
#if !defined (HAVE_SIGACTION)
|
|
/* at this time it is safer to perform unblock after decrement */
|
|
term_conf_busy--;
|
|
#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
|
|
{
|
|
sigset_t nvar, ovar;
|
|
sigemptyset (&nvar);
|
|
mask_termsig (&nvar);
|
|
sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
|
|
}
|
|
#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
|
|
#endif /* !HAVE_SIGACTION */
|
|
}
|
|
/* vim: set sw=2 cino={1s>2sn-s^-se-s: */
|