#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