#define TELOPTS
#define TELCMDS
#include <arpa/telnet.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "structs.h"
#include "db.h" /* to get buf, buf1, buf2 */
#include "comm.h" /* to get SEND_TO_Q etc */
#include "telnet_support.h"
#include "utils.h" /* to get STATE */
/* #define TELNET_DEBUG */
/* external functions */
void log(char *);
void raw_write_to_output(char *,DESCRIPTOR_DATA *,int);
/* file-local global vars */
static DESCRIPTOR_DATA *d;
static int naws_pos;
static unsigned char naws_buf[4];
unsigned char do_sga[]={ IAC, DO, TELOPT_SGA };
unsigned char do_naws[]={ IAC, DO, TELOPT_NAWS };
unsigned char timing_mark[]={ IAC, WILL, TELOPT_TM };
/* code */
void tell_telnet_supported_options(DESCRIPTOR_DATA *d) {
if (d->telnetstate.sga==NOKNOWN)
raw_write_to_output(do_sga,d,3);
if (d->telnetstate.naws==NOKNOWN)
raw_write_to_output(do_naws,d,3);
}
void process_naws(unsigned char c) {
if (naws_pos<4) {
naws_buf[naws_pos++]=c;
}
}
void process_char(unsigned char cmd) {
/* returns 0 if command is completed 1 otherwise */
static cstate_t state=TEXT;
static unsigned char lastcmd;
static unsigned char subopt;
char reply[5];
switch(state) {
case TEXT:
if (cmd==IAC) state=GOT_IAC;
return;
case IN_NAWS:
if (cmd==IAC) state=GOT_IAC;
else process_naws(cmd);
return;
case PTCL:
#ifdef TELNET_DEBUG
sprintf(buf,"TELNET: Received IAC %s %s",TELCMD(lastcmd),TELOPT(cmd));
log(buf);
#endif
switch(lastcmd) {
case DO:
switch(cmd) {
case TELOPT_SGA:
break;
case TELOPT_NAWS:
break;
case TELOPT_ECHO:
break;
case TELOPT_TM:
/* insert WILL TIMING MARK in output stream */
raw_write_to_output(timing_mark,d,3);
#ifdef TELNET_DEBUG
log("TELNET: Sent IAC WILL TIMING MARK");
#endif
break;
default: /* unknown option asked for */
sprintf(reply,"%c%c%c",IAC,WONT,cmd);
raw_write_to_output(reply,d,3);
#ifdef TELNET_DEBUG
sprintf(buf,"TELNET: Sent IAC WONT %s",TELOPT(cmd));
log(buf);
#endif
}
break;
case DONT:
case WILL:
case WONT:
}
state=TEXT;
return;
case GOT_IAC:
switch(cmd) {
case DO:
case DONT:
case WILL:
case WONT:
state=PTCL;
lastcmd=cmd;
return;
case SB:
state=GOT_SB;
break;
case SE:
if (subopt==TELOPT_NAWS) {
d->telnetstate.winx=(naws_buf[0]<<8) + naws_buf[1];
d->telnetstate.winy=(naws_buf[2]<<8) + naws_buf[3];
#ifdef TELNET_DEBUG
sprintf(buf,"TELNET: Client window size=%dx%d",
d->telnetstate.winx,
d->telnetstate.winy);
log(buf);
#endif
if (STATE(d)==CON_PLAYING) {
sprintf(buf,"Resize to
%dx%d\r\n",d->telnetstate.winx,d->telnetstate.winy);
SEND_TO_Q(buf,d);
}
}
state=TEXT;
break;
default:
#ifdef TELNET_DEBUG
sprintf(buf,"TELNET: Received (and ignored) IAC %s",TELCMD(cmd));
log(buf);
#endif
state=TEXT;
return;
}
break;
case GOT_SB:
switch(cmd) {
case TELOPT_NAWS:
state=IN_NAWS;
subopt=TELOPT_NAWS;
#ifdef TELNET_DEBUG
log("TELNET: Start negotiation of NAWS");
#endif
naws_pos=0;
break;
default:
#ifdef TELNET_DEBUG
sprintf(buf,"TELNET: Received (and ignored) IAC SB %s
(#%d)",TELOPT(cmd),cmd);
log(buf);
#endif
state=TEXT;
}
break;
}
}
void telnet_parsing(unsigned char *data,int length, DESCRIPTOR_DATA *desc) {
unsigned char *ptr=data;
d=desc;
for (ptr=data; ptr<data+length; ptr++) {
#ifdef TELNET_DEBUG
fprintf(stderr,"<'%c'=#%d>\r\n",isprint(*ptr)? *ptr : '_',*ptr);
#endif
process_char(*ptr);
}
}
--
+---------------------------------------------------------------+
| FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
| Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
| Newbie List: http://groups.yahoo.com/group/circle-newbies/ |
+---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 06/26/03 PDT