date and time created 87/09/11 15:40:50 by minshall
[unix-history] / usr / src / usr.bin / telnet / terminal.c
#include <arpa/telnet.h>
#include "externs.h"
#include "types.h"
char ttyobuf[2*BUFSIZ], *tfrontp, *tbackp;
char
termEofChar,
termEraseChar,
termFlushChar,
termIntChar,
termKillChar,
termLiteralNextChar,
termQuitChar;
/*
* initialize the terminal data structures.
*/
init_terminal()
{
tfrontp = tbackp = ttyobuf;
autoflush = TerminalAutoFlush();
}
/*
* Send as much data as possible to the terminal.
*
* The return value indicates whether we did any
* useful work.
*/
int
ttyflush()
{
int n;
if ((n = tfrontp - tbackp) > 0) {
if (!(SYNCHing||flushout)) {
n = TerminalWrite(tout, tbackp, n);
} else {
TerminalFlushOutput();
/* we leave 'n' alone! */
}
}
if (n >= 0) {
tbackp += n;
if (tbackp == tfrontp) {
tbackp = tfrontp = ttyobuf;
}
}
return n > 0;
}
#if defined(TN3270)
#if defined(unix)
static void
inputAvailable()
{
HaveInput = 1;
}
#endif /* defined(unix) */
void
outputPurge()
{
int tmp = flushout;
flushout = 1;
ttyflush();
flushout = tmp;
}
#endif /* defined(TN3270) */
\f
#if defined(unix)
/*
* Various signal handling routines.
*/
void
deadpeer()
{
setcommandmode();
longjmp(peerdied, -1);
}
void
intr()
{
if (localchars) {
intp();
return;
}
setcommandmode();
longjmp(toplevel, -1);
}
void
intr2()
{
if (localchars) {
sendbrk();
return;
}
}
void
doescape()
{
command(0);
}
#endif /* defined(unix) */
\f
/*
* These routines decides on what the mode should be (based on the values
* of various global variables).
*/
int
getconnmode()
{
static char newmode[16] =
{ 4, 5, 3, 3, 2, 2, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6 };
int modeindex = 0;
if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
modeindex += 1;
}
if (hisopts[TELOPT_ECHO]) {
modeindex += 2;
}
if (hisopts[TELOPT_SGA]) {
modeindex += 4;
}
if (In3270) {
modeindex += 8;
}
return newmode[modeindex];
}
void
setconnmode()
{
TerminalNewMode(tin, tout, getconnmode());
}
void
setcommandmode()
{
TerminalNewMode(tin, tout, 0);
}
#if defined(TN3270)
/*
* The following routines are places where the various tn3270
* routines make calls into telnet.c.
*/
/* TtyChars() - returns the number of characters in the TTY buffer */
TtyChars()
{
return(tfrontp-tbackp);
}
/*
* DataToNetwork - queue up some data to go to network. If "done" is set,
* then when last byte is queued, we add on an IAC EOR sequence (so,
* don't call us with "done" until you want that done...)
*
* We actually do send all the data to the network buffer, since our
* only client needs for us to do that.
*/
int
DataToNetwork(buffer, count, done)
register char *buffer; /* where the data is */
register int count; /* how much to send */
int done; /* is this the last of a logical block */
{
register int c;
int origCount;
fd_set o;
origCount = count;
FD_ZERO(&o);
while (count) {
if ((netobuf+sizeof netobuf - nfrontp) < 6) {
netflush();
while ((netobuf+sizeof netobuf - nfrontp) < 6) {
FD_SET(net, &o);
(void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
(struct timeval *) 0);
netflush();
}
}
c = *buffer++;
count--;
if (c == IAC) {
*nfrontp++ = IAC;
*nfrontp++ = IAC;
} else {
*nfrontp++ = c;
}
}
if (done && !count) {
*nfrontp++ = IAC;
*nfrontp++ = EOR;
netflush(); /* try to move along as quickly as ... */
}
return(origCount - count);
}
/* DataToTerminal - queue up some data to go to terminal. */
int
DataToTerminal(buffer, count)
register char *buffer; /* where the data is */
register int count; /* how much to send */
{
int origCount;
#if defined(unix)
fd_set o;
FD_ZERO(&o);
#endif /* defined(unix) */
origCount = count;
while (count) {
if (tfrontp >= ttyobuf+sizeof ttyobuf) {
ttyflush();
while (tfrontp >= ttyobuf+sizeof ttyobuf) {
#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
(struct timeval *) 0);
#endif /* defined(unix) */
ttyflush();
}
}
*tfrontp++ = *buffer++;
count--;
}
return(origCount - count);
}
/* EmptyTerminal - called to make sure that the terminal buffer is empty.
* Note that we consider the buffer to run all the
* way to the kernel (thus the select).
*/
void
EmptyTerminal()
{
#if defined(unix)
fd_set o;
FD_ZERO(&o);
#endif /* defined(unix) */
if (tfrontp == tbackp) {
#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (int *) 0, &o, (int *) 0,
(struct timeval *) 0); /* wait for TTLOWAT */
#endif /* defined(unix) */
} else {
while (tfrontp != tbackp) {
ttyflush();
#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (int *) 0, &o, (int *) 0,
(struct timeval *) 0); /* wait for TTLOWAT */
#endif /* defined(unix) */
}
}
}
\f
/*
* Push3270 - Try to send data along the 3270 output (to screen) direction.
*/
static int
Push3270()
{
int save = scc;
if (scc) {
if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
if (Ibackp != Ibuf) {
memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
Ifrontp -= (Ibackp-Ibuf);
Ibackp = Ibuf;
}
}
if (Ifrontp+scc < Ibuf+sizeof Ibuf) {
telrcv();
}
}
return save != scc;
}
/*
* Finish3270 - get the last dregs of 3270 data out to the terminal
* before quitting.
*/
static void
Finish3270()
{
while (Push3270() || !DoTerminalOutput()) {
#if defined(unix)
HaveInput = 0;
#endif /* defined(unix) */
;
}
}
/* StringToTerminal - output a null terminated string to the terminal */
void
StringToTerminal(s)
char *s;
{
int count;
count = strlen(s);
if (count) {
(void) DataToTerminal(s, count); /* we know it always goes... */
}
}
#if ((!defined(NOT43)) || defined(PUTCHAR))
/* _putchar - output a single character to the terminal. This name is so that
* curses(3x) can call us to send out data.
*/
void
_putchar(c)
char c;
{
if (tfrontp >= ttyobuf+sizeof ttyobuf) {
(void) DataToTerminal(&c, 1);
} else {
*tfrontp++ = c; /* optimize if possible. */
}
}
#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
#endif /* defined(TN3270) */