BBN-Vax-TCP/src/telnet/process.c
#include "stdio.h"
#include "tnio.h"
#include "globdefs.h"
#include "ttyctl.h"
/* -------------------------- P R O C E S S ------------------------- */
/*
* Read from input buffer and put in command buffer cline (contained in
* this routine) or output buffer via telwrite.
* This routine identifies and executes the user's commands.
* If the user types the escape char twice, that sends the escape char.
* If the user types the escape char followed by a newline, the modes are
* changed to normal. If the user types the escape char
* followed by anything else, it is just executed without changing tty modes.
*/
process(buf, cnt, connp)
char * buf;
int cnt;
NETCONN * connp;
{
register char *p; /* Points into inbuf */
static char outbuf[WNETSIZE]; /* Static just to keep stack size down */
register char *op; /* Points into outbuf */
int c; /* Unsigned char */
int tflags;
static TTYMODE *oldmode = NULL;
static int cmdstate = 0;
# define SENDING 0
# define GOTESC 1
# define INCMD 2
static char cline[256];
static char *clinep;
static trunc;
extern int escape;
extern int udone;
extern int termfd;
extern int inputfd;
extern int usercr;
extern int needprompt;
if (cnt == -1 || cnt == 0)
{
udone++;
return(0);
}
op = outbuf;
for (p = buf; cnt > 0; p++, cnt--)
{
int type;
# define ORDINARY 10
# define CMDBEGIN 20
# define CMDEND 30
if (connp == NULL && cmdstate == SENDING)
{
cmdstate = GOTESC;
needprompt = 1;
}
c = *p & 0377;
if ((c&0177) == escape)
type = CMDBEGIN;
else if ((c&0177) == '\n' || (c&0177) == '\r')
type = CMDEND;
else
type = ORDINARY;
switch(type + cmdstate)
{
case SENDING + ORDINARY: /* Send it */
case SENDING + CMDEND: /* Send it */
xmit:
*op++ = c;
if (c == '\r' && usercr) { /* Follow CR with LF */
*op++ = '\n';
tflags = GetFlags(CurMode());
if (tflags&ECHO)
echo('\r');
}
cmdstate = SENDING;
break;
case SENDING + CMDBEGIN: /* Start of command? */
echo(c);
cmdstate = GOTESC;
break;
case GOTESC + CMDBEGIN: /* Doubled command char, send it */
if (connp != NULL)
goto xmit;
break;
case GOTESC + CMDEND: /* Line ended with escape, enter cmd mode */
echo(c);
if (oldmode == NULL)
oldmode = ChgMode(OrigMode());
needprompt = 1;
break;
case GOTESC + ORDINARY: /* Start of command */
clinep = cline;
trunc = 0;
case INCMD + ORDINARY: /* Collect command */
case INCMD + CMDBEGIN: /* Collect command */
echo(c);
if (clinep < &cline[sizeof(cline)])
*clinep++ = c;
else
trunc = 1; /* Remember we are losing chars */
cmdstate = INCMD;
break;
case INCMD + CMDEND:
echo(c);
if (oldmode != NULL)
{
ChgMode(oldmode);
oldmode = NULL;
}
if (trunc)
fprintf(stderr, "Command line too long -- ignored.\r\n");
else
{
/* Flush what we have in case command involves it */
if (connp != 0 && op - outbuf > 0)
telwrite(connp, outbuf, op - outbuf);
op = outbuf;
/* Ignore initial escape char */
if (cline[0] == escape)
cline[0] = ' ';
/* Execute command */
cline[clinep-cline] = '\0';
callcmd(cline);
}
cmdstate = SENDING;
break;
}
}
if (connp != 0 && op - outbuf > 0)
telwrite(connp, outbuf, op - outbuf);
return(0);
}