aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-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 {
IACBUFSIZE = 128,
CHM_TRY = 0,
- CHM_ON = 1,
+ CHM_ON = 1,
CHM_OFF = 2,
UF_ECHO = 0x01,
- UF_SGA = 0x02,
+ UF_SGA = 0x02,
TS_NORMAL = 0,
TS_COPY = 1,
- TS_IAC = 2,
- TS_OPT = 3,
+ TS_IAC = 2,
+ TS_OPT = 3,
TS_SUB1 = 4,
TS_SUB2 = 5,
- TS_CR = 6,
+ TS_CR = 6,
};
typedef unsigned char byte;
@@ -244,25 +244,34 @@ static void handle_net_output(int len)
static void handle_net_input(int len)
{
+ byte c;
int i;
- int cstart = 0;
-
- for (i = 0; i < len; i++) {
- byte c = G.buf[i];
-
- if (G.telstate == TS_NORMAL) { /* most typical state */
- if (c == IAC) {
- cstart = i;
- G.telstate = TS_IAC;
- }
- else if (c == '\r') {
- cstart = i + 1;
- G.telstate = TS_CR;
- }
- /* No IACs were seen so far, no need to copy
- * bytes within G.buf: */
- continue;
+ int cstart;
+
+ i = 0;
+ //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf);
+ if (G.telstate == TS_NORMAL) { /* most typical state */
+ while (i < len) {
+ c = G.buf[i];
+ i++;
+ if (c == IAC) /* unlikely */
+ goto got_IAC;
+ if (c != '\r') /* likely */
+ continue;
+ G.telstate = TS_CR;
+ cstart = i;
+ goto got_special;
}
+ full_write(STDOUT_FILENO, G.buf, len);
+ return;
+ got_IAC:
+ G.telstate = TS_IAC;
+ cstart = i - 1;
+ got_special: ;
+ }
+
+ for (; i < len; i++) {
+ c = G.buf[i];
switch (G.telstate) {
case TS_CR:
@@ -278,20 +287,19 @@ static void handle_net_input(int len)
/* Similar to NORMAL, but in TS_COPY we need to copy bytes */
if (c == IAC)
G.telstate = TS_IAC;
- else
+ else {
G.buf[cstart++] = c;
- if (c == '\r')
- G.telstate = TS_CR;
+ if (c == '\r')
+ G.telstate = TS_CR;
+ }
break;
case TS_IAC: /* Prev char was IAC */
- if (c == IAC) { /* IAC IAC -> one IAC */
+ switch (c) {
+ case IAC: /* IAC IAC -> one IAC */
G.buf[cstart++] = c;
G.telstate = TS_COPY;
break;
- }
- /* else */
- switch (c) {
case SB:
G.telstate = TS_SUB1;
break;
@@ -320,17 +328,12 @@ static void handle_net_input(int len)
}
}
- if (G.telstate != TS_NORMAL) {
- /* We had some IACs, or CR */
- if (G.iaclen)
- iac_flush();
- if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */
- G.telstate = TS_NORMAL;
- len = cstart;
- }
-
- if (len)
- full_write(STDOUT_FILENO, G.buf, len);
+ /* We had some IACs, or CR */
+ iac_flush();
+ if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */
+ G.telstate = TS_NORMAL;
+ if (cstart != 0)
+ full_write(STDOUT_FILENO, G.buf, cstart);
}
static void put_iac(int c)