home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_300
/
313_01
/
unix.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-04-22
|
6KB
|
375 lines
/* $Header: /nw2/tony/src/stevie/src/RCS/unix.c,v 1.9 89/08/31 10:03:09 tony Exp $
*
* System-dependent routines for UNIX System V or Berkeley.
*/
#include "stevie.h"
#ifdef TERMCAP
extern int ospeed;
#endif
#ifdef BSD
/*
* We have to dork around here to avoid name space pollution on some
* systems that define their own version of CTRL within standard
* header files.
*/
#undef CTRL
#include <sgtty.h>
#include <sys/time.h>
#undef CTRL
#define CTRL(x) ((x) & 0x1f)
#else
#include <termio.h>
#endif
#include <signal.h>
#ifdef BSD
bool_t got_stop = FALSE; /* for job control */
#endif
/*
* inchar() - get a character from the keyboard
*/
int
inchar()
{
char c;
#ifdef BSD
void set_tty(), reset_tty(), tsig();
int rv;
int rfds;
#endif
flushbuf(); /* flush any pending output */
do {
#ifdef BSD
/*
* Much of the following deals with job control issues.
* If the editor has received a stop signal, it resets
* tty modes, puts the cursor at the bottom of the screen,
* and suspends itself. When execution resumes, the modes
* are restored and the screen is redrawn.
*
* The select call below is used because an interrupted
* read is restarted after the stop signal is received. To
* avoid this problem, we use select instead which will
* return -1 (with errno == EINTR) if a signal is received.
*/
do {
if (got_stop) {
msg("");
reset_tty();
signal(SIGTSTP, SIG_DFL);
kill(getpid(), SIGTSTP);
/* process stops here */
set_tty();
signal(SIGTSTP, tsig);
screenclear();
updatescreen();
windgoto(Cursrow, Curscol);
flushbuf();
got_stop = FALSE;
}
rfds = 1; /* wait for input from stdin */
rv=select(32,&rfds,(int*)0,(int*)0,(struct timeval*)0);
if (rv == 1 && rfds == 1)
rv = read(0, &c, 1);
} while (rv != 1);
#else
while (read(0, &c, 1) != 1)
;
#endif
} while (c == NUL);
got_int = FALSE;
return c;
}
#define BSIZE 2048
static char outbuf[BSIZE];
static int bpos = 0;
void
flushbuf()
{
if (bpos != 0)
write(1, outbuf, bpos);
bpos = 0;
}
/*
* Macro to output a character. Used within this file for speed.
*/
#define outone(c) outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
/*
* Function version for use outside this file.
*/
void
outchar(c)
char c;
{
outone(c);
}
void
outstr(s)
register char *s;
{
while (*s) {
outone(*s++);
}
}
#ifdef TERMCAP
void
outcstr(s)
char *s;
{
tputs(s, 1, outchar);
}
#endif
void
beep()
{
outone('\007');
}
/*
* remove(file) - remove a file
*/
void
remove(file)
char *file;
{
unlink(file);
}
/*
* rename(of, nf) - rename existing file 'of' to 'nf'
*/
void
rename(of, nf)
char *of, *nf;
{
unlink(nf);
link(of, nf);
unlink(of);
}
void
delay()
{
/* not implemented */
}
#ifdef BSD
static struct sgttyb ostate;
static struct ltchars oltchars;
#else
static struct termio ostate;
#endif
/*
* Go into cbreak mode
*/
void
set_tty()
{
#ifdef BSD
struct sgttyb nstate;
struct ltchars nltchars;
ioctl(0, TIOCGETP, &ostate);
nstate = ostate;
nstate.sg_flags &= ~(XTABS|CRMOD|ECHO);
nstate.sg_flags |= CBREAK;
ioctl(0, TIOCSETN, &nstate);
/*
* If ^Y is being used as the "delayed suspend" character, we
* change it to be whatever the regular suspend character is
* (probably ^Z). Vi needs ^Y as a command character, and the
* delayed suspend isn't needed here.
*/
ioctl(0, TIOCGLTC, &oltchars);
nltchars = oltchars;
if (nltchars.t_dsuspc == CTRL('Y'))
nltchars.t_dsuspc = nltchars.t_suspc;
ioctl(0, TIOCSLTC, &nltchars);
#ifdef TERMCAP
ospeed = nstate.sg_ospeed;
#endif
#else
struct termio nstate;
ioctl(0, TCGETA, &ostate);
nstate = ostate;
nstate.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
nstate.c_cc[VMIN] = 1;
nstate.c_cc[VTIME] = 0;
ioctl(0, TCSETAW, &nstate);
#ifdef TERMCAP
ospeed = nstate.c_cflag & CBAUD;
#endif
#endif
}
/*
* Restore original terminal modes
*/
void
reset_tty()
{
#ifdef BSD
ioctl(0, TIOCSETP, &ostate);
ioctl(0, TIOCSLTC, &oltchars);
#else
ioctl(0, TCSETAW, &ostate);
#endif
}
static void
sig()
{
signal(SIGINT, sig);
signal(SIGQUIT, sig);
got_int = TRUE;
}
#ifdef BSD
static void
tsig()
{
signal(SIGTSTP, tsig);
got_stop = TRUE;
}
#endif
void
windinit()
{
#ifdef TERMCAP
if (t_init() != 1) {
fprintf(stderr, "unknown terminal type\n");
exit(1);
}
#else
Columns = 80;
P(P_LI) = Rows = 24;
#endif
/*
* The code here makes sure that there isn't a window during which
* we could get interrupted and exit with the tty in a weird state.
*/
signal(SIGINT, sig);
signal(SIGQUIT, sig);
#ifdef BSD
signal(SIGTSTP, tsig);
#endif
set_tty();
if (got_int)
windexit(0);
}
void
windexit(r)
int r;
{
reset_tty();
exit(r);
}
void
windgoto(r, c)
register int r, c;
{
#ifdef TERMCAP
char *tgoto();
#else
r += 1;
c += 1;
#endif
/*
* Check for overflow once, to save time.
*/
if (bpos + 8 >= BSIZE)
flushbuf();
#ifdef TERMCAP
outcstr(tgoto(T_CM, c, r));
#else
outbuf[bpos++] = '\033';
outbuf[bpos++] = '[';
if (r >= 10)
outbuf[bpos++] = r/10 + '0';
outbuf[bpos++] = r%10 + '0';
outbuf[bpos++] = ';';
if (c >= 10)
outbuf[bpos++] = c/10 + '0';
outbuf[bpos++] = c%10 + '0';
outbuf[bpos++] = 'H';
#endif
}
FILE *
fopenb(fname, mode)
char *fname;
char *mode;
{
return fopen(fname, mode);
}
char *
fixname(s)
char *s;
{
return s;
}
/*
* doshell() - run a command or an interactive shell
*/
void
doshell(cmd)
char *cmd;
{
char *getenv();
char cline[128];
outstr("\r\n");
flushbuf();
if (cmd == NULL) {
if ((cmd = getenv("SHELL")) == NULL)
cmd = "/bin/sh";
sprintf(cline, "%s -i", cmd);
cmd = cline;
}
reset_tty();
system(cmd);
set_tty();
wait_return();
}