gno/bin/less/signal.c
gdr-ftp 784e3de7cd Initial checkin of aroff, binprint, center, less, ls, make, makemake,
passwd, ps, purge, shutdown, stty, upper, and vi.  These sources are
for the versions of the utils shipped with GNO v2.0.4.
1998-03-09 08:30:21 +00:00

243 lines
3.9 KiB
C

/*
* Routines dealing with signals.
*
* A signal usually merely causes a bit to be set in the "signals" word.
* At some convenient time, the mainline code checks to see if any
* signals need processing by calling psignal().
* If we happen to be reading from a file [in iread()] at the time
* the signal is received, we call intread to interrupt the iread.
*/
#pragma noroot
#include "less.h"
#include <signal.h>
#ifdef _ORCAC_
#pragma databank 1
segment "LoadSegONE";
#endif
/*
* "sigs" contains bits indicating signals which need to be processed.
*/
public int sigs;
#define S_INTERRUPT 01
#ifdef SIGTSTP
#define S_STOP 02
#endif
#if defined(SIGWINCH) || defined(SIGWIND)
#define S_WINCH 04
#endif
extern int sc_width, sc_height;
extern int swindow;
extern int screen_trashed;
extern int lnloop;
extern int linenums;
extern int scroll;
extern int reading;
static HANDLER u_interrupt(int type, int code);
static HANDLER stop(int type, int code);
/*
* Interrupt signal handler.
*/
/* ARGSUSED*/
static HANDLER
u_interrupt(type, code)
int type;
int code;
{
SIGNAL(SIGINT, u_interrupt);
sigs |= S_INTERRUPT;
if (reading)
intread();
}
public void
fake_interrupt(void)
{
sigs |= S_INTERRUPT;
}
#ifdef SIGTSTP
/*
* "Stop" (^Z) signal handler.
*/
/* ARGSUSED*/
static HANDLER
stop(type, code)
int type;
int code;
{
SIGNAL(SIGTSTP, stop);
sigs |= S_STOP;
if (reading)
intread();
}
#endif
#ifdef SIGWINCH
/*
* "Window" change handler
*/
/* ARGSUSED*/
public HANDLER
winch(type, code)
int type;
int code;
{
SIGNAL(SIGWINCH, winch);
sigs |= S_WINCH;
if (reading)
intread();
}
#else
#ifdef SIGWIND
/*
* "Window" change handler
*/
/* ARGSUSED*/
public HANDLER
winch(type)
int type;
{
SIGNAL(SIGWIND, winch);
sigs |= S_WINCH;
if (reading)
intread();
}
#endif
#endif
#ifdef __ORCAC__
#pragma databank 0
#endif
/*
* Set up the signal handlers.
*/
public void
init_signals(on)
int on;
{
if (on)
{
/*
* Set signal handlers.
*/
(void) SIGNAL(SIGINT, u_interrupt);
#ifdef SIGTSTP
(void) SIGNAL(SIGTSTP, stop);
#endif
#ifdef SIGWINCH
(void) SIGNAL(SIGWINCH, winch);
#else
#ifdef SIGWIND
(void) SIGNAL(SIGWIND, winch);
#endif
#endif
} else
{
/*
* Restore signals to defaults.
*/
(void) SIGNAL(SIGINT, SIG_DFL);
#ifdef SIGTSTP
(void) SIGNAL(SIGTSTP, SIG_DFL);
#endif
#ifdef SIGWINCH
(void) SIGNAL(SIGWINCH, SIG_IGN);
#endif
#ifdef SIGWIND
(void) SIGNAL(SIGWIND, SIG_IGN);
#endif
}
}
/*
* Process any signals we have received.
* A received signal cause a bit to be set in "sigs".
*/
public void
psignals(void)
{
register int tsignals;
if ((tsignals = sigs) == 0)
return;
sigs = 0;
#ifdef S_WINCH
if (tsignals & S_WINCH)
{
int old_width, old_height;
/*
* Re-execute get_term() to read the new window size.
*/
old_width = sc_width;
old_height = sc_height;
swindow = -1;
get_term();
if (sc_width != old_width || sc_height != old_height)
{
scroll = (sc_height + 1) / 2;
screen_trashed = 1;
}
}
#endif
#ifdef SIGTSTP
if (tsignals & S_STOP)
{
/*
* Clean up the terminal.
*/
#ifdef SIGTTOU
SIGNAL(SIGTTOU, SIG_IGN);
#endif
lower_left();
clear_eol();
deinit();
flush();
raw_mode(0);
#ifdef SIGTTOU
SIGNAL(SIGTTOU, SIG_DFL);
#endif
SIGNAL(SIGTSTP, SIG_DFL);
kill(getpid(), SIGTSTP);
/*
* ... Bye bye. ...
* Hopefully we'll be back later and resume here...
* Reset the terminal and arrange to repaint the
* screen when we get back to the main command loop.
*/
SIGNAL(SIGTSTP, stop);
raw_mode(1);
init();
screen_trashed = 1;
}
#endif
if (tsignals & S_INTERRUPT)
{
bell();
/*
* {{ You may wish to replace the bell() with
* error("Interrupt", NULL_PARG); }}
*/
/*
* If we were interrupted while in the "calculating
* line numbers" loop, turn off line numbers.
*/
if (lnloop)
{
lnloop = 0;
if (linenums == 2)
screen_trashed = 1;
linenums = 0;
error("Line numbers turned off", NULL_PARG);
}
}
}