version 1.5, 1994/07/12 11:30:58
|
version 1.15, 1996/04/17 16:39:41
|
Line 1
|
Line 1
|
/* direct key io driver |
/* direct key io driver; signal handler |
|
|
The following is stolen from the readline library for bash |
Copyright (C) 1995 Free Software Foundation, Inc. |
|
|
|
This file is part of Gforth. |
|
|
|
Gforth 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 |
|
of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
|
|
The following is stolen from the readline library for bash |
*/ |
*/ |
|
|
/* Use -DDOMAINOS for Apollo Domain-OS. |
/* |
Use -D_POSIX_VERSION for POSIX systems. |
Use -D_POSIX_VERSION for POSIX systems. |
*/ |
*/ |
|
|
#ifdef DOMAINOS |
#include "config.h" |
|
#include <unistd.h> |
|
|
|
#ifdef apollo |
#define _POSIX_VERSION |
#define _POSIX_VERSION |
#endif |
#endif |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <signal.h> |
#include <signal.h> |
|
#include <string.h> |
#include <sys/types.h> |
#include <sys/types.h> |
#ifndef DOMAINOS |
#ifndef apollo |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#endif |
#endif |
#include <fcntl.h> |
#include <fcntl.h> |
Line 31
|
Line 53
|
# endif |
# endif |
#endif |
#endif |
|
|
#if defined (HAVE_UNISTD_H) |
|
# include <unistd.h> |
|
#endif |
|
|
|
#define NEW_TTY_DRIVER |
#define NEW_TTY_DRIVER |
#define HAVE_BSD_SIGNALS |
#define HAVE_BSD_SIGNALS |
/* |
/* |
#ifndef DOMAINOS |
#ifndef apollo |
#define USE_XON_XOFF |
#define USE_XON_XOFF |
#endif |
#endif |
*/ |
*/ |
Line 52
|
Line 70
|
|
|
/* System V machines use termio. */ |
/* System V machines use termio. */ |
#if !defined (_POSIX_VERSION) |
#if !defined (_POSIX_VERSION) |
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) |
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) || defined (Solaris) |
# undef NEW_TTY_DRIVER |
# undef NEW_TTY_DRIVER |
# define TERMIO_TTY_DRIVER |
# define TERMIO_TTY_DRIVER |
# include <termio.h> |
# include <termio.h> |
Line 93
|
Line 111
|
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ |
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ |
|
|
#include <errno.h> |
#include <errno.h> |
extern int errno; |
/* extern int errno; */ |
|
|
#if defined (SHELL) |
#if defined (SHELL) |
# include <posixstat.h> |
# include <posixstat.h> |
Line 108 extern int errno;
|
Line 126 extern int errno;
|
# endif /* USGr3 */ |
# endif /* USGr3 */ |
#endif /* USG && hpux */ |
#endif /* USG && hpux */ |
|
|
#if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(DOMAINOS) |
#if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(apollo) |
# include <dirent.h> |
# include <dirent.h> |
# define direct dirent |
# define direct dirent |
# if defined (_POSIX_VERSION) |
# if defined (_POSIX_VERSION) |
Line 165 static int eof_char = CTRL ('D');
|
Line 183 static int eof_char = CTRL ('D');
|
/* **************************************************************** */ |
/* **************************************************************** */ |
|
|
/* Non-zero means that the terminal is in a prepped state. */ |
/* Non-zero means that the terminal is in a prepped state. */ |
static int terminal_prepped = 0; |
int terminal_prepped = 0; |
|
|
#if defined (NEW_TTY_DRIVER) |
#if defined (NEW_TTY_DRIVER) |
|
|
Line 572 long key_avail (stream)
|
Line 590 long key_avail (stream)
|
long chars_avail = pending; |
long chars_avail = pending; |
int result; |
int result; |
|
|
|
if(!terminal_prepped) prep_terminal(); |
|
|
#if defined (FIONREAD) |
#if defined (FIONREAD) |
result = ioctl (tty, FIONREAD, &chars_avail); |
result = ioctl (tty, FIONREAD, &chars_avail); |
#endif |
#endif |
Line 607 unsigned char getkey(stream)
|
Line 627 unsigned char getkey(stream)
|
int result; |
int result; |
unsigned char c; |
unsigned char c; |
|
|
|
if(!terminal_prepped) prep_terminal(); |
|
|
while (pending < 0) |
while (pending < 0) |
{ |
{ |
result = read (fileno (stream), &c, sizeof (char)); |
result = read (fileno (stream), &c, sizeof (char)); |
Line 617 unsigned char getkey(stream)
|
Line 639 unsigned char getkey(stream)
|
/* If zero characters are returned, then the file that we are |
/* If zero characters are returned, then the file that we are |
reading from is empty! Return EOF in that case. */ |
reading from is empty! Return EOF in that case. */ |
if (result == 0) |
if (result == 0) |
return (0); |
return CTRL('D'); |
|
|
/* If the error that we received was SIGINT, then try again, |
/* If the error that we received was SIGINT, then try again, |
this is simply an interrupted system call to read (). |
this is simply an interrupted system call to read (). |
Line 672 int main()
|
Line 694 int main()
|
} |
} |
#endif |
#endif |
|
|
/* signal handling taken from pfe by Dirk Zoller (Copylefted) - anton */ |
|
/* !! needs cleanup */ |
/* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */ |
char * |
|
sigmsg (int sig) |
|
{ |
|
static char buf [25]; |
|
static char *msg [] = |
|
{ |
|
"Hangup", /* These strings are cited from */ |
|
"Interrupt", /* Rochkind: Advanced UNIX programming */ |
|
"Quit", |
|
"Illegal Instruction", |
|
"Trace Trap", |
|
"IOT instruction", |
|
"EMT instruction", |
|
"Floating point exception", |
|
"Kill", |
|
"Bus error", |
|
"Segmentation Violation", |
|
"Bad arg to system call", |
|
"Broken pipe", |
|
"Alarm clock", |
|
"Terminate signal", |
|
"User signal 1", |
|
"User signal 2", |
|
}; |
|
|
|
if ((unsigned)sig <= 17) |
|
return msg [sig - 1]; |
|
sprintf (buf, "signal %d received", sig); |
|
return buf; |
|
} |
|
|
|
static void |
static void |
graceful_exit (int sig) |
graceful_exit (int sig) |
{ |
{ |
deprep_terminal(); |
deprep_terminal(); |
if ((unsigned)sig <= 17) |
fprintf (stderr, "\n\n%s.\n", strsignal (sig)); |
fprintf (stderr, "\n\n%s.\n", sigmsg (sig)); |
|
else |
|
fprintf (stderr, "\n\nSignal %d received, terminated.\n", sig); |
|
exit (0x80|sig); |
exit (0x80|sig); |
} |
} |
|
|
Line 721 jmp_buf throw_jmp_buf;
|
Line 710 jmp_buf throw_jmp_buf;
|
static void |
static void |
signal_throw(int sig) |
signal_throw(int sig) |
{ |
{ |
static int throw_codes[] = { |
int code; |
-256, |
struct { |
-28, |
int signal; |
-257, |
int throwcode; |
-258, |
} *p, throwtable[] = { |
-259, |
{ SIGINT, -28 }, |
-260, |
{ SIGFPE, -55 }, |
-261, |
{ SIGBUS, -23 }, |
-55, |
{ SIGSEGV, -9 }, |
-262, |
|
-23, |
|
-9, |
|
-263, |
|
-264, |
|
-265, |
|
-266, |
|
-267, |
|
-268, |
|
}; |
}; |
signal(sig,signal_throw); |
signal(sig,signal_throw); |
longjmp(throw_jmp_buf,throw_codes[sig-1]); /* or use siglongjmp ? */ |
for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++) |
|
if (sig == p->signal) { |
|
code = p->throwcode; |
|
break; |
|
} |
|
longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ |
} |
} |
|
|
static void |
static void termprep (int sig) |
termprep (int sig) |
|
{ |
{ |
terminal_prepped=0; prep_terminal(); |
|
signal(sig,termprep); |
signal(sig,termprep); |
|
terminal_prepped=0; |
} |
} |
|
|
void |
UCell rows=24; |
install_signal_handlers (void) |
UCell cols=80; |
|
|
|
void get_winsize() |
{ |
{ |
/* !! These definitions seem to be system dependent |
#ifdef TIOCGWINSZ |
We could have them in the machine.h file, |
struct winsize size; |
but I would like something more automatic - anton */ |
|
#define SIGS_TO_IGNORE SIGCHLD |
if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) { |
#define SIGS_TO_ABORT SIGINT, SIGILL, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, \ |
rows = size.ws_row; |
SIGALRM, SIGBUS |
cols = size.ws_col; |
#define SIGS_TO_QUIT SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, \ |
} |
SIGTERM |
#else |
#define SIGS_TO_TERMPREP SIGCONT |
char *s, *ends; |
|
unsigned long ul; |
static short sigs_to_ignore [] = { SIGS_TO_IGNORE }; |
if (s=getenv("LINES")) { |
static short sigs_to_abort [] = { SIGS_TO_ABORT }; |
rows=atoi(s); |
static short sigs_to_quit [] = { SIGS_TO_QUIT }; |
if (rows==0) |
static short sigs_to_termprep [] = { SIGS_TO_TERMPREP }; |
rows=24; |
|
} |
|
if (s=getenv("COLUMNS")) { |
|
rows=atoi(s); |
|
if (rows==0) |
|
cols=80; |
|
} |
|
#endif |
|
} |
|
|
|
static void change_winsize(int sig) |
|
{ |
|
signal(sig,change_winsize); |
|
#ifdef TIOCGWINSZ |
|
get_winsize(); |
|
#endif |
|
} |
|
|
|
void install_signal_handlers (void) |
|
{ |
|
|
|
#if 0 |
|
/* these signals are handled right by default, no need to handle them; |
|
they are listed here just for fun */ |
|
static short sigs_to_default [] = { |
|
#ifdef SIGCHLD |
|
SIGCHLD, |
|
#endif |
|
#ifdef SIGINFO |
|
SIGINFO, |
|
#endif |
|
#ifdef SIGIO |
|
SIGIO, |
|
#endif |
|
#ifdef SIGLOST |
|
SIGLOST, |
|
#endif |
|
#ifdef SIGKILL |
|
SIGKILL, |
|
#endif |
|
#ifdef SIGSTOP |
|
SIGSTOP, |
|
#endif |
|
#ifdef SIGPWR |
|
SIGPWR, |
|
#endif |
|
#ifdef SIGMSG |
|
SIGMSG, |
|
#endif |
|
#ifdef SIGDANGER |
|
SIGDANGER, |
|
#endif |
|
#ifdef SIGMIGRATE |
|
SIGMIGRATE, |
|
#endif |
|
#ifdef SIGPRE |
|
SIGPRE, |
|
#endif |
|
#ifdef SIGVIRT |
|
SIGVIRT, |
|
#endif |
|
#ifdef SIGGRANT |
|
SIGGRANT, |
|
#endif |
|
#ifdef SIGRETRACT |
|
SIGRETRACT, |
|
#endif |
|
#ifdef SIGSOUND |
|
SIGSOUND, |
|
#endif |
|
#ifdef SIGSAK |
|
SIGSAK, |
|
#endif |
|
#ifdef SIGTSTP |
|
SIGTSTP, |
|
#endif |
|
#ifdef SIGTTIN |
|
SIGTTIN, |
|
#endif |
|
#ifdef SIGTTOU |
|
SIGTTOU, |
|
#endif |
|
#ifdef SIGSTKFLT |
|
SIGSTKFLT, |
|
#endif |
|
#ifdef SIGUNUSED |
|
SIGUNUSED, |
|
#endif |
|
}; |
|
#endif |
|
|
|
static short sigs_to_throw [] = { |
|
#ifdef SIGBREAK |
|
SIGBREAK, |
|
#endif |
|
#ifdef SIGINT |
|
SIGINT, |
|
#endif |
|
#ifdef SIGILL |
|
SIGILL, |
|
#endif |
|
#ifdef SIGEMT |
|
SIGEMT, |
|
#endif |
|
#ifdef SIGFPE |
|
SIGFPE, |
|
#endif |
|
#ifdef SIGIOT |
|
SIGIOT, |
|
#endif |
|
#ifdef SIGSEGV |
|
SIGSEGV, |
|
#endif |
|
#ifdef SIGALRM |
|
SIGALRM, |
|
#endif |
|
#ifdef SIGPIPE |
|
SIGPIPE, |
|
#endif |
|
#ifdef SIGPOLL |
|
SIGPOLL, |
|
#endif |
|
#ifdef SIGPROF |
|
SIGPROF, |
|
#endif |
|
#ifdef SIGBUS |
|
SIGBUS, |
|
#endif |
|
#ifdef SIGSYS |
|
SIGSYS, |
|
#endif |
|
#ifdef SIGTRAP |
|
SIGTRAP, |
|
#endif |
|
#ifdef SIGURG |
|
SIGURG, |
|
#endif |
|
#ifdef SIGUSR1 |
|
SIGUSR1, |
|
#endif |
|
#ifdef SIGUSR2 |
|
SIGUSR2, |
|
#endif |
|
#ifdef SIGVTALRM |
|
SIGVTALRM, |
|
#endif |
|
#ifdef SIGXFSZ |
|
SIGXFSZ, |
|
#endif |
|
}; |
|
static short sigs_to_quit [] = { |
|
#ifdef SIGHUP |
|
SIGHUP, |
|
#endif |
|
#ifdef SIGQUIT |
|
SIGQUIT, |
|
#endif |
|
#ifdef SIGABRT |
|
SIGABRT, |
|
#endif |
|
#ifdef SIGTERM |
|
SIGTERM, |
|
#endif |
|
#ifdef SIGXCPU |
|
SIGXCPU, |
|
#endif |
|
}; |
int i; |
int i; |
|
|
#define DIM(X) (sizeof (X) / sizeof *(X)) |
#define DIM(X) (sizeof (X) / sizeof *(X)) |
|
/* |
for (i = 0; i < DIM (sigs_to_ignore); i++) |
for (i = 0; i < DIM (sigs_to_ignore); i++) |
if (sigs_to_ignore [i]) |
signal (sigs_to_ignore [i], SIG_IGN); |
signal (sigs_to_ignore [i], SIG_IGN); |
*/ |
for (i = 0; i < DIM (sigs_to_abort); i++) |
for (i = 0; i < DIM (sigs_to_throw); i++) |
signal (sigs_to_abort [i], signal_throw); /* !! change to throw */ |
signal (sigs_to_throw [i], signal_throw); |
for (i = 0; i < DIM (sigs_to_quit); i++) |
for (i = 0; i < DIM (sigs_to_quit); i++) |
signal (sigs_to_quit [i], graceful_exit); |
signal (sigs_to_quit [i], graceful_exit); |
for (i = 0; i < DIM (sigs_to_termprep); i++) |
#ifdef SIGCONT |
signal (sigs_to_termprep [i], termprep); |
signal (SIGCONT, termprep); |
|
#endif |
|
#ifdef SIGWINCH |
|
signal (SIGWINCH, change_winsize); |
|
#endif |
} |
} |
/* end signal handling */ |
/* end signal handling */ |