v16i064: Front end editor program, Part04/05
Rich Salz
rsalz at uunet.uu.net
Fri Nov 11 06:49:09 AEST 1988
Submitted-by: Kazumasa Utashiro <kddlab!sra.junet!utashiro>
Posting-number: Volume 16, Issue 64
Archive-name: fep/part04
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./fep_defs.h`
then
echo "writing ./fep_defs.h"
cat > ./fep_defs.h << '\End\Of\File\'
/* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
#ifndef lint
# define FEP_DEFS \
"$Header: fep_defs.h,v 4.0 88/08/05 20:21:51 utashiro Rel $ (SRA)"
#endif lint
#define MAXCOMLEN 512 /* maximum command length */
#define MAXARGS 64 /* maximum number of arguments */
#define ON 1 /* on switch */
#define OFF 0 /* off switch */
#define DFL_HISTLEN 100 /* default history length */
#define DFL_SHOWHIST 20 /* default show history length */
#define IGNORED 2 /* ignored */
#define PROCESSED 1 /* processed or not by history */
#define NOT_PROCESSED 0 /* built-in functions */
#define BS '\b' /* backspace character */
#define SP ' ' /* space character */
#define DEFAULT_DELIMITERS " \t" /* default delimiter character */
/*
* Pseudo functions
*/
#define eq(a,b) (strcmp(a,b) == 0)
#define abs(a) ((a)>0?(a):-(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#ifdef KANJI
# define isctlchar(c) (c && !iskanji(c) && (!(c&0140) || c=='\177'))
# define iswordchar(c) (c && (iskanji(c) || isalnum(c) || iscntrl(c)))
# define isWordchar(c) ((c) && !isspace((c)))
#else KANJI
# define isctlchar(c) (c && (!(c&0140) || c=='\177'))
# define iswordchar(c) (isalnum(c) || iscntrl(c))
# define isWordchar(c) ((c) && !isspace((c)))
#endif KANJI
#define unctl(c) (((c)=='\177') ? '?' : ((c) >= 040) ? (c) : (c)|0100)
#define toctrl(c) ((c)&~0100)
#define INDIRECTED (1<<(sizeof(char*)*8-1))
/* this is actually 0x80000000 on 32 bit machine,
that addresses kernel address space */
#define isIndirect(f) ((u_int)(f)&(u_int)INDIRECTED)
#define setIndirect(f) (FUNC)((u_int)(f)|(u_int)INDIRECTED)
#define maskIndirect(f) (FUNC *)((u_int)(f)&~(u_int)INDIRECTED)
/*
* Type of character
*/
#ifdef KANJI
# define CHAR unsigned char
# define CHARMASK 0377
#else KANJI
# define CHAR char
# define CHARMASK 0177
#endif KANJI
/*
* Only one machine I know alloca() works is vax.
*/
#ifdef vax
# define ALLOCA
#endif vax
/*
* Typedef's
*/
typedef int (*FUNC)(); /* pointer to funciton */
typedef enum { /* edit status */
EDITING,
NOTEDITING
} EDITSTATUS;
typedef enum { /* edit mode */
NOTYET,
EMACS,
VI
} EDITMODE;
typedef struct { /* bind table entry type */
char *bt_s;
FUNC bt_func;
} BINDENT;
typedef struct _var {
char *v_name;
char *v_value;
char *v_help;
struct _var *v_next;
} VAR;
typedef struct {
char *buf; /* buffer */
char *last_buf; /* last i/o done pointer */
int b_max; /* max size */
int start; /* start point */
int next; /* next read point */
int count; /* count */
int hiwater; /* high water mark */
} BUFFER;
#define buf_count(b) ((b)->count)
#define buf_remain(b) ((b)->size - (b)->count)
/*
char buf_char (b, n)
BUFFER *b;
int n;
{
if (n >= 0) {
if (n >= b->count)
return ((char*)-1);
return (b->buf[(b->start+n)%b->count]);
} else {
if (-n >= b->count)
return (-1);
if (b->next+n >= 0)
return (b->buf[b->next+n]);
else
return (b->buf[b->next+n+b->count]);
}
}
*/
#define buf_char(b,n) \
(((n)>=0) \
?(((n)>=(b)->count) \
? ((char)-1) \
: ((b)->buf[((b)->start+n)%(b)->count])) \
:((-(n) > (b)->count) \
?((char)-1) \
:((((b)->next+n) >= 0) \
? ((b)->buf[(b)->next+(n)]) \
: ((b)->buf[(b)->next+n+(b)->count]))))
\End\Of\File\
else
echo "will not over write ./fep_defs.h"
fi
if `test ! -s ./fep_glob.h`
then
echo "writing ./fep_glob.h"
cat > ./fep_glob.h << '\End\Of\File\'
/* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
#ifndef lint
# define FEP_GLOB \
"$Header: fep_glob.h,v 4.0 88/08/05 20:21:55 utashiro Rel $ (SRA)"
#endif lint
extern FUNC *curFuncTab; /* function table */
extern FUNC *altFuncTab; /* altanative function table */
extern int debug; /* debug flag */
extern char *prompt; /* prompt string */
extern char *delimiters; /* delimiter characters */
extern EDITMODE editmode; /* edit mode */
extern FILE *redirect_fp; /* FILE pointer for I/O redirection */
extern FILE *script_fp; /* FILE pointer for script */
extern int redirect_line; /* number of line for redirecting */
extern int redirect_pid; /* process id redirecting from */
extern int auto_tty_fix; /* fix tty mode automatically */
extern int tty_fix_bell; /* ring bell when tty mode is changed */
extern int Transparency; /* transparent flag */
extern EDITSTATUS editstatus; /* edit status */
extern BUFFER *output_buffer; /* output buffer */
extern int lines, columns; /* terminal sizes */
extern char *term_clear; /* terminal clear code */
/*
* tty control caracters.
* defined in fep_main.c
*/
extern struct tchars tchars_buf;
extern struct ltchars ltchars_buf;
extern struct sgttyb initial_ttymode;
\End\Of\File\
else
echo "will not over write ./fep_glob.h"
fi
if `test ! -s ./fep_funcs.h`
then
echo "writing ./fep_funcs.h"
cat > ./fep_funcs.h << '\End\Of\File\'
/* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
#ifndef lint
# define FEP_FUNCS \
"$Header: fep_funcs.h,v 4.0 88/08/05 20:21:53 utashiro Rel $ (SRA)"
#endif lint
/*
* command line edit functions
*/
int abort();
int backward_character();
int backward_word();
int backward_Word();
int beginning_of_line();
int clear_screen();
int delete_line();
int delete_next_character();
int delete_next_word();
int delete_next_Word();
int delete_previous_character();
int delete_previous_word();
int delete_previous_Word();
int delete_to_kill_buffer();
int terminate();
int end_of_line();
int expand_file_name();
int forward_character();
int forward_to_end_of_word();
int forward_to_end_of_Word();
int forward_word();
int forward_Word();
int ignore();
int insert_and_flush();
int insert_tab();
int kill_to_end_of_line();
int kill_to_top_of_line();
int list_file_name();
int literal_next();
int mark();
int new_line();
int next_history();
int previous_history();
int reprint();
int search_reverse();
int search_forward();
int self_insert();
int send_eof();
int show_bindings();
int show_history();
int toggle_transparency();
int fix_transparency();
int yank_from_kill_buffer();
int invoke_shell();
int show_help();
/*
* Vi mode functions.
*/
int vi_num();
int vi_edit();
int vi_motion();
int vi_c();
int vi_d();
int vi_ins_edit();
int vi_new_line();
/*
* fep builtin command functions.
*/
int suspend();
int bind_to_key();
int alias();
int unalias();
int set();
int unset();
int fep_chdir();
int fep_pwd();
int fep_history();
int show_bindings();
int fep_source();
int fep_command();
int fep_save_history();
int fep_start_script();
int fep_end_script();
int fep_read_history();
int fep_read_from_file();
int fep_read_from_command();
int fep_echo();
int fep_if();
int fep_else();
int fep_endif();
int fep_repaint();
#ifdef STAT
int fep_showstat();
#endif
/*
* FunctionNameTable
*/
typedef struct {
int (*func)();
char *name;
char *help;
} FunctionTableEnt;
extern FunctionTableEnt FunctionNameTable[];
extern FunctionTableEnt BuiltinFuncTable[];
char *look_var();
char *push_condition();
char *pop_condition();
char *change_condition();
\End\Of\File\
else
echo "will not over write ./fep_funcs.h"
fi
if `test ! -s ./fep_stat.h`
then
echo "writing ./fep_stat.h"
cat > ./fep_stat.h << '\End\Of\File\'
/* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
#ifndef lint
# define FEP_STAT \
"$Header: fep_stat.h,v 4.0 88/08/05 20:21:58 utashiro Rel $ (SRA)"
#endif lint
extern long stat_obyte;
extern long stat_ibyte;
extern long stat_rerror;
extern long stat_werror;
extern long stat_nselect;
struct statistics {
char *info_name;
long *info_valp;
};
\End\Of\File\
else
echo "will not over write ./fep_stat.h"
fi
if `test ! -s ./fep_main.c`
then
echo "writing ./fep_main.c"
cat > ./fep_main.c << '\End\Of\File\'
/* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
#ifndef lint
static char rcsid[]=
"$Header: fep_main.c,v 4.0 88/08/05 20:22:17 utashiro Rel $ (SRA)";
#endif lint
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sgtty.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/errno.h>
#include "fep_defs.h"
#include "fep_glob.h"
#include "fep_funcs.h"
#ifdef STAT
#include "fep_stat.h"
#endif
#ifndef lint
static char fep_defsrc[] = FEP_DEFS;
static char fep_globrc[] = FEP_GLOB;
static char fep_funcsrc[] = FEP_FUNCS;
#ifdef STAT
static char fep_statrc[] = FEP_STAT;
#endif
#endif lint
char *myself; /* the command name */
char *prompt = ""; /* prompt string */
char *delimiters = DEFAULT_DELIMITERS;
/* delimiter characters */
int master; /* file discriptor for pty master */
int slave; /* file discriptor for pty slave */
int mastermask; /* 1<<master */
int stdinmask; /* 1<<fileno(stdin) */
int selectmask; /* stdinmask | mastermask */
int selectnfds; /* max (fileno(stdin), master) + 1*/
int child_pid; /* child pid */
int ptyflag = ON; /* flag to use pty or not */
int histlen = -1; /* history length */
int debug = OFF; /* debug switch */
int auto_tty_fix = ON; /* fix tty mode automaticaly */
FILE *script_fp = NULL; /* script file pointer */
int catchsig(); /* function take care SIGCHILD */
struct sgttyb initial_ttymode; /* initial tty mode */
struct sgttyb master_ttymode; /* master tty mode */
struct sgttyb slave_ttymode; /* slave tty mode */
int lines; /* terminal line size */
int columns; /* terminal coulumn size */
char *term_clear; /* terminal clear code */
FUNC sighup, sigchld, sigtstp; /* function buffer for signal */
struct tchars tchars_buf; /* tty characters */
struct ltchars ltchars_buf; /* tty characters */
int lmode_buf; /* local mode */
int line_desc; /* line descipline */
#ifdef KANJI
struct jtchars jtchars_buf; /* kanji tty characters */
int kmode_buf; /* kanji mode */
#endif KANJI
char master_tty[16]; /* master tty name */
char slave_tty[16]; /* slave tty name */
BUFFER iobuffer; /* buffer self */
BUFFER *output_buffer = &iobuffer; /* buffer pointer */
struct cmdinfo {
char *command;
char *prompt;
char *delimiters;
} cmdinfo_tab [] = {
{"/bin/sh", "$ ", " \t()<>{};&|='\""},
{"sh", "$ ", " \t()<>{};&|='\""},
{"jsh", "$ ", " \t()<>{};&|='\""},
{"/bin/csh", "% ", " \t()<>{};&|='\""},
{"csh", "% ", " \t()<>{};&|='\""},
{"jcsh", "% ", " \t()<>{};&|='\""},
{"/usr/ucb/dbx", "(dbx) ", " \t>"},
{"dbx", "(dbx) ", " \t>"},
{"/etc/lpc", "lpc> ", " \t"},
{"lpc", "lpc> ", " \t"},
{"/usr/ucb/mail", "& ", " \t"},
{"mail", "& ", " \t"},
{"/usr/lib/sendmail", "> ", " \t"},
{"sendmail", "> ", " \t"},
{"/usr/sra/calc", "CALC: ", " \t"},
{"calc", "CALC: ", " \t"},
{0, 0}
};
main(argc, argv)
int argc;
char *argv[];
{
int i;
char *cp;
char *getenv();
char **commandv;
char *allocAndCopyThere();
myself = argv[0];
/*
* Initialize binding table
*/
init_bind_table ();
/*
* Set default variables before process arguments.
*/
set_default_vars ();
/*
* Look environment variable first.
*/
/* EDITMODE */
if ((cp=getenv("EDITMODE")) && (eq(cp,"emacs")||eq(cp,"vi")))
set_only_var ("editmode", cp);
/* USER */
if (cp=getenv("USER"))
set_only_var ("user", cp);
/* HOME */
if (cp=getenv("HOME"))
set_only_var ("home", cp);
/* TERM */
if (cp=getenv("TERM"))
set_only_var ("term", cp);
/* SHELL */
if (cp=getenv("SHELL"))
set_only_var ("shell", cp);
/*
* Check arguments.
*/
while (argv[1] && argv[1][0] == '-') {
switch (argv[1][1]) {
case '\0': /* - */
ptyflag = 0;
break;
case 'd': /* -d */
debug = ON;
break;
case 'e': /* -emacs */
if (strcmp (argv[1], "-emacs") == 0)
set_only_var ("editmode", "emacs");
else
goto DEFAULT;
break;
case 'h': /* -h */
if (argv[1][2] == '\0') {
argv++;
argc--;
if (argc == 1)
usageAndExit ();
histlen = atoi (argv[1]);
}
else {
histlen = atoi (&argv[1] + 2);
}
break;
case 'p': /* -p */
if (argv[1][2] == '\0') {
argv++;
argc--;
if (argc == 1)
usageAndExit ();
prompt = allocAndCopyThere (argv[1]);
}
else {
prompt = allocAndCopyThere (argv[1] + 2);
}
break;
case 'v': /* -vi */
if (strcmp (argv[1], "-vi") == 0)
set_only_var ("editmode", "vi");
else
goto DEFAULT;
break;
DEFAULT:
default:
printf ("Unknown option \"%s\"\n", argv[1]);
}
argv++;
argc--;
}
fflush (stdout);
if (argc < 2 && ptyflag) {
usageAndExit ();
}
look_cmdinfo (argv[1]);
/*
* Set variable of command name.
*/
{
char *cp = argv[1], *rindex();
if (any ('/', cp))
cp = rindex (cp, '/') + 1;
set_var (cp, "1");
set_var ("command", cp);
}
commandv = &argv[1];
if (! isatty (0)) {
execvp (*commandv, commandv, 0);
perror (*commandv);
exit (1);
}
get_pty_master ();
fix_tty ();
if (histlen < 0) {
if (getenv ("HISTLEN"))
histlen = atoi (getenv ("HISTLEN"));
else
histlen = DFL_HISTLEN;
}
/*
* Initialize output buffer.
*/
output_buffer->buf = (char *) malloc (5120);
if (output_buffer->buf <= 0) {
fprintf (stderr, "Can't allocate enough momory\n");
kill_process ();
exit (1);
}
output_buffer->b_max = 5120;
output_buffer->hiwater = 4096;
output_buffer->count = output_buffer->next = output_buffer->start = 0;
init_hist (histlen);
init_edit_params ();
if (ptyflag) {
child_pid = fork ();
if (child_pid < 0) {
perror ("fork");
kill_process ();
exit (1);
}
if (child_pid == 0)
exec_to_command (commandv);
}
fix_signal ();
input_handler ();
}
fix_signal ()
{
sighup = signal (SIGHUP, catchsig);
sigchld = signal (SIGCHLD, catchsig);
sigtstp = signal (SIGTSTP, SIG_IGN);
}
recover_signal ()
{
(void) signal (SIGHUP, sighup);
(void) signal (SIGCHLD, sigchld);
(void) signal (SIGTSTP, sigtstp);
}
input_handler()
{
char *inputline;
char *getline ();
/*
* Get slave tty descriptor for auto-tty-fix
*/
if ((slave = open (slave_tty, O_RDONLY)) < 0)
perror ("open");
while (inputline = getline ()) {
register int nbyte = strlen (inputline);
/*
* Write to master pty
*/
write (master, inputline, nbyte);
/*
* NOTE:
* Saving command line to output buffer is done in getline().
* Because inputline here is converted by alias.
*/
#ifdef STAT
stat_ibyte += nbyte;
#endif
/*
* Write to script file.
*/
if (Transparency == OFF && script_fp)
fwrite (inputline, sizeof(CHAR), strlen (inputline), script_fp);
}
terminate ();
}
#define INPUT_BUFFER_SIZE 1024
#ifdef USE_TIMEOUT
/*
* NOTE:
* Now these time mechanism is not used.
* Terminal status is get at every input from stdin.
*/
struct timeval timeout_0s = {0L, 0L};
struct timeval timeout_500ms = {0L, 500000L};
struct timeval timeout_1s = {1L, 0L};
struct timeval timeout_5s = {5L, 0L};
struct timeval timeout_10s = {10L, 0L};
struct timeval timeout_60s = {60L, 0L};
#define TIMEOUT_IMMID &timeout_500ms
#define TIMEOUT_SOON &timeout_1s
#define TIMEOUT_SHORT &timeout_5s
#define TIMEOUT_MID &timeout_10s
#define TIMEOUT_LONG &timeout_60s
#define TIMEOUT_FOREVER (struct timeval *)0
#define TIMEOUT_NOBLOCK &timeout_0s
struct timeval *timeout_list[] = {
TIMEOUT_IMMID,
TIMEOUT_SOON,
TIMEOUT_SHORT,
TIMEOUT_MID,
TIMEOUT_LONG,
TIMEOUT_FOREVER
};
#else
struct timeval timeout_0s = {0L, 0L};
#define TIMEOUT_FOREVER (struct timeval *)0
#define TIMEOUT_NOBLOCK &timeout_0s
#endif
struct timeval *notimeout[] = {
TIMEOUT_FOREVER
};
getcharacter()
{
char c;
int n;
/*
char buf[INPUT_BUFFER_SIZE];
*/
int nfound, readfd, writefd = 0, execptfd = 0;
#ifdef USE_TIMEOUT
struct timeval **timeout = auto_tty_fix ? timeout_list : notimeout;
#else
struct timeval **timeout = notimeout;
#endif
/*
* Sorry, this cording depends to an implementation of getc().
*/
# define CHAR_IN_BUFFER (stdin->_cnt)
if (CHAR_IN_BUFFER)
goto RETURNCHAR;
RETRY:
readfd = selectmask;
#ifdef STAT
stat_nselect++;
#endif
if ((nfound = select (selectnfds, &readfd, 0, 0, *timeout)) < 0)
perror ("select");
/*
* Found output from pty.
*/
if (readfd & mastermask) {
int nbyte;
/*
* Read from pty.
*/
/*
nbyte = read (master, buf, INPUT_BUFFER_SIZE);
*/
nbyte = buf_read (master, output_buffer);
if (nbyte > 0) {
/*
* Write to stdout
*/
/*
write (1, buf, nbyte);
*/
write (1, output_buffer->last_buf, nbyte);
/*
* Write to script file
*/
if (script_fp)
/*
fwrite (buf, sizeof(CHAR), nbyte, script_fp);
*/
fwrite (output_buffer->last_buf,
sizeof(CHAR), nbyte, script_fp);
#ifdef STAT
stat_obyte += nbyte;
#endif
}
else if (nbyte < 0) {
perror ("read");
#ifdef STAT
stat_rerror++;
#endif
}
}
/*
* Found input from terminal
*/
if (CHAR_IN_BUFFER || readfd & stdinmask) {
#ifndef USE_TIMEOUT
/*
* Look slave tty mode before every input.
* This will be done only before real input from stdin, because
* if character remained in FILE buffer, control goes to RETURNCHAR
* label.
*/
if (auto_tty_fix)
(void) fix_transparency ();
#endif
RETURNCHAR:
if ((c = getc (stdin)) == EOF) {
if (debug)
printf ("EOF chatched\n");
terminate ();
}
else
return (c & CHARMASK);
}
#ifdef USE_TIMEOUT
/*
* In the case of timeout.
*/
if (nfound == 0) {
/*
* Only to make sure
*/
if (!auto_tty_fix) {
printf ("Timeout should not happen!!\n");
timeout = notimeout;
goto RETRY;
}
(void) fix_transparency ();
++timeout;
if (debug)
errorBell();
}
#endif
goto RETRY;
}
int buf_read (fd, bp)
int fd; /* file discriptor */
BUFFER *bp; /* buffer pointer */
{
int nbyte;
/*
* save previous next pointer
*/
bp->last_buf = bp->buf + bp->next;
/*
* read from fd as possible
*/
nbyte = read (fd, bp->buf + bp->next, bp->b_max - bp->next);
/*
* move next read pointer
*/
bp->next += nbyte;
/*
* If count has not reached high-water mark, increment count
* by read count, otherwise start pointer should be pushed by
* next pointer.
*/
if (bp->count < bp->hiwater)
bp->count += nbyte;
else
bp->start += nbyte;
/*
* If next pointer goes further than high-water mark, discard contents
* after next pointer, and move start and next pointer to buffer top.
*/
if (bp->next > bp->hiwater) {
bp->count = bp->next;
bp->start = 0;
bp->next = 0;
}
return (nbyte);
}
buf_put (bp, s)
BUFFER *bp; /* buffer pointer */
char *s; /* string pointer */
{
int nbyte;
int slen;
nbyte = strlen (s);
while (nbyte > 0) {
slen = min (bp->b_max - bp->next, nbyte);
strncpy (bp->buf + bp->next, s, slen);
s += slen;
nbyte -= slen;
bp->next += slen;
if (bp->count < bp->hiwater)
bp->count += slen;
else
bp->start += slen;
if (bp->next > bp->hiwater) {
bp->count = bp->next;
bp->start = 0;
bp->next = 0;
}
}
}
swallow_output()
{
/*
char buf[INPUT_BUFFER_SIZE];
*/
int readfd = mastermask;
int r;
int nbyte;
int ncount = 10;
while (
ncount-- &&
select (selectnfds, &readfd, 0, 0, TIMEOUT_NOBLOCK) > 0 &&
readfd & mastermask
) {
/*
nbyte = read (master, buf, INPUT_BUFFER_SIZE);
*/
nbyte = buf_read (master, output_buffer);
if (nbyte > 0) {
/*
write (1, buf, nbyte);
*/
write (1, output_buffer->last_buf, nbyte);
#ifdef STAT
stat_obyte += nbyte;
stat_nselect++;
#endif
/*
* Write to script file
*/
if (script_fp)
/*
fwrite (buf, sizeof(CHAR), nbyte, script_fp);
*/
fwrite (output_buffer->last_buf,
sizeof(CHAR), nbyte, script_fp);
}
else if (nbyte < 0) {
perror ("read");
#ifdef STAT
stat_rerror++;
#endif
}
}
return;
}
#include <sys/wait.h>
catchsig()
{
union wait status;
struct rusage ru;
if (wait3 (&status.w_status, WNOHANG | WUNTRACED, &ru) != child_pid)
return;
if (WIFSTOPPED (status) /* || WIFSIGNALED (status) */) {
if (debug) {
message ("Child has sttoped!!\n");
}
suspend ();
return;
}
terminate ();
}
exec_to_command(argv)
char *argv[];
{
int t;
/*
* Disconnect control terminal
*/
t = open ("/dev/tty", 2);
if (t >= 0) {
ioctl (t, TIOCNOTTY, (char *) 0);
(void) close (t);
}
get_pty_slave ();
(void) close (master);
dup2 (slave, 0);
dup2 (slave, 1);
dup2 (slave, 2);
(void) close (slave);
ioctl (0, TIOCSETN, (char *) & slave_ttymode);
execvp (*argv, argv, 0);
perror (*argv);
exit (1);
}
fix_tty()
{
struct tchars tcbuf;
struct ltchars lcbuf;
master_ttymode = initial_ttymode;
slave_ttymode = initial_ttymode;
tcbuf = tchars_buf;
lcbuf = ltchars_buf;
master_ttymode.sg_flags |= CBREAK;
master_ttymode.sg_flags &= ~ECHO;
slave_ttymode.sg_erase = -1;
slave_ttymode.sg_kill = -1;
slave_ttymode.sg_flags &= ~(ECHO|CRMOD);
tcbuf.t_intrc = -1;
tcbuf.t_quitc = -1;
tcbuf.t_eofc = -1;
tcbuf.t_brkc = -1;
lcbuf.t_suspc = -1;
lcbuf.t_dsuspc = -1;
lcbuf.t_rprntc = -1;
lcbuf.t_flushc = -1;
lcbuf.t_werasc = -1;
lcbuf.t_lnextc = -1;
ioctl (0, TIOCSETN, (char *) & master_ttymode);
ioctl (0, TIOCSETC, (char *) & tcbuf);
ioctl (0, TIOCSLTC, (char *) & lcbuf);
}
kill_process()
{
if (child_pid)
(void) killpg (child_pid, SIGTERM);
}
terminate()
{
extern int errno;
/*
* Save history if 'history-file' is set
*/
{
char *cp, *mk_home_relative(), *look_var();
char buf [256];
int num;
if (look_var ("savehist") && (cp = look_var ("history-file"))) {
num = lookd_var ("savehist");
strcpy (buf, mk_home_relative (cp));
save_history (buf, num);
}
}
/*
* If scripting, close script file.
*/
if (script_fp)
fclose (script_fp);
(void) signal (SIGCHLD, SIG_IGN);
if (killpg (child_pid, SIGTERM) < 0 && errno != ESRCH)
if (killpg (child_pid, SIGHUP) < 0)
if (killpg (child_pid, SIGKILL) < 0)
perror ("kill");
ioctl (0, TIOCSETN, (char *) & initial_ttymode);
ioctl (0, TIOCSETC, (char *) & tchars_buf);
ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
exit (0);
}
get_pty_master()
{
char c;
struct stat stb;
int i;
if (ptyflag == 0) {
master = 1;
return;
}
for (c = 'p'; c <= 's'; c++) {
for (i = 0; i < 16; i++) {
sprintf (master_tty, "/dev/pty%c%x", c, i);
master = open (master_tty, O_RDWR);
if (master >= 0) {
sprintf (slave_tty, "/dev/tty%c%x", c, i);
goto FOUND;
}
}
}
/*
* Can't get master tty
*/
if (master < 0) {
fprintf (stderr, "Couldn't open pseudo tty\n");
kill_process ();
exit (1);
}
FOUND:
ioctl (0, TIOCGETP, (char *) &initial_ttymode);
ioctl (0, TIOCGETC, (char *) &tchars_buf);
ioctl (0, TIOCGETD, (char *) &line_desc);
ioctl (0, TIOCGLTC, (char *) <chars_buf);
ioctl (0, TIOCLGET, (char *) &lmode_buf);
#ifdef TIOCGWINSZ
{
struct winsize win;
if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
lines = win.ws_row;
columns = win.ws_col;
}
}
#endif
#ifdef KANJI
# if defined(TIOCKGET) && defined(TIOCKSET)
ioctl (0, TIOCKGET, (char *) &kmode_buf);
# endif
# if defined(TIOCKGETC) && defined(TIOCKSETC)
ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
# endif
#endif KANJI
stdinmask = 1 << fileno (stdin);
mastermask = 1 << master;
selectmask = stdinmask | mastermask;
selectnfds = max (fileno(stdin), master) + 1;
return;
}
get_pty_slave()
{
slave = open (slave_tty, 2);
if (slave < 0) {
perror (slave_tty);
exit (1);
}
ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
ioctl (slave, TIOCSETC, (char *) &tchars_buf);
ioctl (slave, TIOCSLTC, (char *) <chars_buf);
ioctl (slave, TIOCLSET, (char *) &lmode_buf);
ioctl (slave, TIOCSETD, (char *) &line_desc);
#ifdef KANJI
# if defined(TIOCKGET) && defined(TIOCKSET)
ioctl (slave, TIOCKSET, (char *) &kmode_buf);
# endif
# if defined(TIOCKGETC) && defined(TIOCKSETC)
ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
# endif
#endif KANJI
#ifdef TIOCSWINSZ
{
struct winsize win;
win.ws_row = lines;
win.ws_col = columns;
(void) ioctl (slave, TIOCSWINSZ, &win);
}
#endif
}
recover_tty()
{
ioctl (0, TIOCSETN, (char *) & initial_ttymode);
ioctl (0, TIOCSETC, (char *) & tchars_buf);
ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
}
suspend()
{
long pid;
int (*func) ();
int omask;
extern int errno;
pid = getpid ();
/* reset signal handler so kill below stops us */
func = signal (SIGCHLD, SIG_IGN);
signal (SIGTSTP, SIG_DFL);
recover_tty();
#define mask(s) (1 << ((s)-1))
omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
kill (0, SIGTSTP);
if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
printf ("Where my child has gone?!\n");
terminate ();
}
killpg (child_pid, SIGCONT);
kill (0, SIGCONT);
signal (SIGCHLD, func);
signal (SIGTSTP, SIG_IGN);
sigblock (mask (SIGTSTP));
fix_tty ();
if (look_var ("auto-repaint"))
fep_repaint(0);
}
look_cmdinfo (command)
char *command;
{
struct cmdinfo *p;
char *allocAndCopyThere();
if (strcmp (prompt, "") != 0)
return;
for (p = cmdinfo_tab; p->command; p++) {
if (strcmp (command, p->command) == 0) {
prompt = allocAndCopyThere (p->prompt);
set_var ("prompt", p->prompt);
set_var ("delimiters", p->delimiters);
break;
}
}
}
usageAndExit()
{
printf ("Usage: %s [-emacs|-vi] command\n", myself);
exit (1);
}
\End\Of\File\
else
echo "will not over write ./fep_main.c"
fi
echo "Finished archive 4 of 5"
exit
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list