From: Ben Gras Date: Mon, 5 Sep 2005 20:22:06 +0000 (+0000) Subject: window change hack in telnetd X-Git-Tag: v3.1.0~181 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch13.html?a=commitdiff_plain;h=b2bb27eda15d809b04827d61ab6b72885adbaaca;p=minix.git window change hack in telnetd --- diff --git a/commands/telnetd/telnet.c b/commands/telnetd/telnet.c index 90794c3f1..0bbe6552b 100755 --- a/commands/telnetd/telnet.c +++ b/commands/telnetd/telnet.c @@ -12,24 +12,32 @@ #include #include #include +#include #include +#include #include "telnetd.h" #include "telnet.h" #include +#include + #define IN_DATA 0 #define IN_CR 1 #define IN_IAC 2 #define IN_IAC2 3 +#define IN_SB 4 _PROTOTYPE(static void dowill, (int c)); _PROTOTYPE(static void dowont, (int c)); _PROTOTYPE(static void dodo, (int c)); _PROTOTYPE(static void dodont, (int c)); _PROTOTYPE(static void respond, (int ack, int option)); +_PROTOTYPE(static void respond_really, (int ack, int option)); #define LASTTELOPT TELOPT_SGA +static int r_winch = 0; + static int TelROpts[LASTTELOPT+1]; static int TelLOpts[LASTTELOPT+1]; @@ -63,7 +71,7 @@ int len; if(option <= LASTTELOPT) { TelROpts[option] = 1; len = 3; - } + } else if(option == TELOPT_WINCH && !r_winch) { r_winch = 1; len = 3; } break; case DONT: if(option <= LASTTELOPT) { @@ -88,6 +96,15 @@ int len; (void) write(fdout, buf, len); } +int set_winsize(int fd, unsigned int cols, unsigned int rows) +{ + struct winsize w; + memset(&w, 0, sizeof(w)); + w.ws_col = cols; + w.ws_row = rows; + ioctl(fd, TIOCSWINSZ, (char *) &w); +} + int tel_in(fdout, telout, buffer, len) int fdout; int telout; @@ -134,6 +151,9 @@ int c; InState = IN_IAC2; ThisOpt = c; break; + case SB: + InState = IN_SB; + break; case EOR: case SE: case NOP: @@ -144,7 +164,6 @@ int c; case EC: case EL: case GA: - case SB: break; default: break; @@ -164,6 +183,43 @@ int c; case DONT: dodont(c); break; } break; + case IN_SB: + { + static int winchpos = -1; + /* Subnegotiation. */ + if(winchpos >= 0) { + static unsigned int winchbuf[5], iacs = 0; + winchbuf[winchpos] = c; + /* IAC is escaped - unescape it. */ + if(c == IAC) iacs++; else { iacs = 0; winchpos++; } + if(iacs == 2) { winchpos++; iacs = 0; } + if(winchpos >= 4) { + /* End of WINCH data. */ + set_winsize(fdout, + (winchbuf[0] << 8) | winchbuf[1], + (winchbuf[2] << 8) | winchbuf[3]); + winchpos = -1; + } + } else { + static int lastiac = 0; + switch(c) { + case TELOPT_WINCH: + /* Start listening. */ + winchpos = 0; + break; + case SE: + if(lastiac) InState = IN_DATA; + break; + default: + break; + } + if(c == IAC) lastiac = 1; + else lastiac = 0; + + + } + break; + } } } @@ -211,9 +267,16 @@ int ack; TelROpts[c] = 1; ack = DO; break; + case TELOPT_WINCH: + if(r_winch) return; + r_winch = 1; + ack = DO; + respond_really(ack, c); + return; default: ack = DONT; } + respond(ack, c); } @@ -259,5 +322,16 @@ unsigned char c[3]; c[0] = IAC; c[1] = ack; c[2] = option; - /* write(telfdout, c, 3); */ +/* write(telfdout, c, 3); */ +} + +static void respond_really(ack, option) +int ack, option; +{ +unsigned char c[3]; + + c[0] = IAC; + c[1] = ack; + c[2] = option; + write(telfdout, c, 3); } diff --git a/commands/telnetd/telnet.h b/commands/telnetd/telnet.h index 668b282aa..893aad825 100755 --- a/commands/telnetd/telnet.h +++ b/commands/telnetd/telnet.h @@ -61,6 +61,7 @@ #define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_EOR 25 /* end or record */ +#define TELOPT_WINCH 31 /* window size */ #define TELOPT_EXOPL 255 /* extended-options-list */ /* Sub-option qualifiers. */ diff --git a/commands/telnetd/term.c b/commands/telnetd/term.c index 446b6ee84..583f03e83 100755 --- a/commands/telnetd/term.c +++ b/commands/telnetd/term.c @@ -38,6 +38,7 @@ void term_init() telopt(1, WILL, TELOPT_BINARY); telopt(1, DO, TELOPT_BINARY); telopt(1, WILL, TELOPT_ECHO); + telopt(1, DO, TELOPT_WINCH); } static int io_done = 0;