aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/telnet.c83
1 files changed, 43 insertions, 40 deletions
diff --git a/networking/telnet.c b/networking/telnet.c
index 7f65ff3e6..0ee65c532 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -94,19 +94,19 @@ enum {
94 IACBUFSIZE = 128, 94 IACBUFSIZE = 128,
95 95
96 CHM_TRY = 0, 96 CHM_TRY = 0,
97 CHM_ON = 1, 97 CHM_ON = 1,
98 CHM_OFF = 2, 98 CHM_OFF = 2,
99 99
100 UF_ECHO = 0x01, 100 UF_ECHO = 0x01,
101 UF_SGA = 0x02, 101 UF_SGA = 0x02,
102 102
103 TS_NORMAL = 0, 103 TS_NORMAL = 0,
104 TS_COPY = 1, 104 TS_COPY = 1,
105 TS_IAC = 2, 105 TS_IAC = 2,
106 TS_OPT = 3, 106 TS_OPT = 3,
107 TS_SUB1 = 4, 107 TS_SUB1 = 4,
108 TS_SUB2 = 5, 108 TS_SUB2 = 5,
109 TS_CR = 6, 109 TS_CR = 6,
110}; 110};
111 111
112typedef unsigned char byte; 112typedef unsigned char byte;
@@ -244,25 +244,34 @@ static void handle_net_output(int len)
244 244
245static void handle_net_input(int len) 245static void handle_net_input(int len)
246{ 246{
247 byte c;
247 int i; 248 int i;
248 int cstart = 0; 249 int cstart;
249 250
250 for (i = 0; i < len; i++) { 251 i = 0;
251 byte c = G.buf[i]; 252 //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf);
252 253 if (G.telstate == TS_NORMAL) { /* most typical state */
253 if (G.telstate == TS_NORMAL) { /* most typical state */ 254 while (i < len) {
254 if (c == IAC) { 255 c = G.buf[i];
255 cstart = i; 256 i++;
256 G.telstate = TS_IAC; 257 if (c == IAC) /* unlikely */
257 } 258 goto got_IAC;
258 else if (c == '\r') { 259 if (c != '\r') /* likely */
259 cstart = i + 1; 260 continue;
260 G.telstate = TS_CR; 261 G.telstate = TS_CR;
261 } 262 cstart = i;
262 /* No IACs were seen so far, no need to copy 263 goto got_special;
263 * bytes within G.buf: */
264 continue;
265 } 264 }
265 full_write(STDOUT_FILENO, G.buf, len);
266 return;
267 got_IAC:
268 G.telstate = TS_IAC;
269 cstart = i - 1;
270 got_special: ;
271 }
272
273 for (; i < len; i++) {
274 c = G.buf[i];
266 275
267 switch (G.telstate) { 276 switch (G.telstate) {
268 case TS_CR: 277 case TS_CR:
@@ -278,20 +287,19 @@ static void handle_net_input(int len)
278 /* Similar to NORMAL, but in TS_COPY we need to copy bytes */ 287 /* Similar to NORMAL, but in TS_COPY we need to copy bytes */
279 if (c == IAC) 288 if (c == IAC)
280 G.telstate = TS_IAC; 289 G.telstate = TS_IAC;
281 else 290 else {
282 G.buf[cstart++] = c; 291 G.buf[cstart++] = c;
283 if (c == '\r') 292 if (c == '\r')
284 G.telstate = TS_CR; 293 G.telstate = TS_CR;
294 }
285 break; 295 break;
286 296
287 case TS_IAC: /* Prev char was IAC */ 297 case TS_IAC: /* Prev char was IAC */
288 if (c == IAC) { /* IAC IAC -> one IAC */ 298 switch (c) {
299 case IAC: /* IAC IAC -> one IAC */
289 G.buf[cstart++] = c; 300 G.buf[cstart++] = c;
290 G.telstate = TS_COPY; 301 G.telstate = TS_COPY;
291 break; 302 break;
292 }
293 /* else */
294 switch (c) {
295 case SB: 303 case SB:
296 G.telstate = TS_SUB1; 304 G.telstate = TS_SUB1;
297 break; 305 break;
@@ -320,17 +328,12 @@ static void handle_net_input(int len)
320 } 328 }
321 } 329 }
322 330
323 if (G.telstate != TS_NORMAL) { 331 /* We had some IACs, or CR */
324 /* We had some IACs, or CR */ 332 iac_flush();
325 if (G.iaclen) 333 if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */
326 iac_flush(); 334 G.telstate = TS_NORMAL;
327 if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ 335 if (cstart != 0)
328 G.telstate = TS_NORMAL; 336 full_write(STDOUT_FILENO, G.buf, cstart);
329 len = cstart;
330 }
331
332 if (len)
333 full_write(STDOUT_FILENO, G.buf, len);
334} 337}
335 338
336static void put_iac(int c) 339static void put_iac(int c)