aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpowwow@askgustav.com <powwow@askgustav.com>2017-02-18 22:07:06 (GMT)
committerSteve Slaven <bpk@hoopajoo.net>2018-09-05 17:25:17 (GMT)
commitae9da104acab2274040a66e3e40ee97c2b8c10d9 (patch)
tree13040a50c213afa4c64bceddb07fb147151671f6
parentf660d7f0b6f2e5fcee6f47328a1862d6ae76af07 (diff)
downloadpowwow-ae9da104acab2274040a66e3e40ee97c2b8c10d9.zip
powwow-ae9da104acab2274040a66e3e40ee97c2b8c10d9.tar.gz
powwow-ae9da104acab2274040a66e3e40ee97c2b8c10d9.tar.bz2
fix bugs in carriage return handling
-rw-r--r--tcp.c36
-rw-r--r--tcp.h1
2 files changed, 26 insertions, 11 deletions
diff --git a/tcp.c b/tcp.c
index 5bf09cc..977c6e3 100644
--- a/tcp.c
+++ b/tcp.c
@@ -286,12 +286,20 @@ static int tcp_addIAC __P3 (char *,dest, char *,txt, int,len)
int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
{
char state = CONN_LIST(fd).state;
+ char old_state = CONN_LIST(fd).old_state;
int i;
static byte subopt[MAX_SUBOPT];
static int subchars;
byte *p, *s, *linestart;
- while ((i = read(fd, buffer, maxsize)) < 0 && errno == EINTR)
+ char *ibuffer = buffer;
+ if (state == GOT_R) {
+ /* make room for the leading \r */
+ ++ibuffer;
+ --maxsize;
+ }
+
+ while ((i = read(fd, ibuffer, maxsize)) < 0 && errno == EINTR)
;
if (i == 0) {
@@ -308,7 +316,8 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
* scan through the buffer,
* interpret telnet protocol escapes and MUME MPI messages
*/
- for (s = p = linestart = (byte *)buffer; i; s++, i--) {
+ p = (byte *)buffer;
+ for (s = linestart = (byte *)ibuffer; i; s++, i--) {
switch (state) {
case NORMAL:
case ALTNORMAL:
@@ -320,6 +329,7 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
*/
switch (*s) {
case IAC:
+ old_state = state; /* remember state to return to after IAC processing */
state = GOTIAC;
break;
case '\r':
@@ -386,20 +396,20 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
break;
case IAC:
*p++ = IAC;
- state = NORMAL;
+ state = old_state;
break;
case GA:
/* I should handle GA as end-of-prompt marker one day */
/* one day has come ;) - Max */
prompt_set_iac((char*)p);
- state = NORMAL;
+ state = old_state;
break;
default:
/* ignore the rest of the telnet commands */
#ifdef TELOPTS
tty_printf("[skipped IAC <%d>]\n", *s);
#endif
- state = NORMAL;
+ state = old_state;
break;
}
break;
@@ -430,7 +440,7 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
sendopt(DONT, *s);
break;
}
- state = NORMAL;
+ state = old_state;
break;
case GOTWONT:
@@ -443,7 +453,7 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
}
/* accept any WONT */
sendopt(DONT, *s);
- state = NORMAL;
+ state = old_state;
break;
case GOTDO:
@@ -467,7 +477,7 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
sendopt(WONT, *s);
break;
}
- state = NORMAL;
+ state = old_state;
break;
case GOTDONT:
@@ -479,7 +489,7 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
tty_special_keys();
}
sendopt(WONT, *s);
- state = NORMAL;
+ state = old_state;
break;
case GOTSB:
@@ -499,17 +509,18 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
} else if (*s == SE) {
subopt[subchars] = '\0';
dosubopt(subopt);
- state = NORMAL;
+ state = old_state;
} else {
/* problem! I haven't the foggiest idea of what to do here.
* I'll just ignore it and hope it goes away. */
PRINTF("#telnet: got IAC <%d> instead of IAC SE!\n", (int)*s);
- state = NORMAL;
+ state = old_state;
}
break;
}
}
CONN_LIST(fd).state = state;
+ CONN_LIST(fd).old_state = old_state;
if (!(CONN_LIST(tcp_fd).flags & SPAWN)) {
log_write(buffer, (char *)p - buffer, 0);
@@ -806,6 +817,7 @@ void tcp_open __P4 (char *,id, char *,initstring, char *,host, int,port)
conn_table[newtcp_fd] = i;
CONN_INDEX(i).flags = ACTIVE;
CONN_INDEX(i).state = NORMAL;
+ CONN_INDEX(i).old_state = NORMAL;
CONN_INDEX(i).port = port;
CONN_INDEX(i).fd = newtcp_fd;
@@ -894,6 +906,7 @@ void tcp_close __P1 (char *,id)
tcp_count--;
CONN_LIST(sfd).flags = 0;
CONN_LIST(sfd).state = NORMAL;
+ CONN_LIST(sfd).old_state = NORMAL;
CONN_LIST(sfd).port = 0;
free(CONN_LIST(sfd).host); CONN_LIST(sfd).host = 0;
free(CONN_LIST(sfd).id); CONN_LIST(sfd).id = 0;
@@ -1001,6 +1014,7 @@ void tcp_spawn __P2 (char *,id, char *,cmd)
}
CONN_INDEX(i).flags = ACTIVE | SPAWN;
CONN_INDEX(i).state = NORMAL;
+ CONN_INDEX(i).old_state = NORMAL;
CONN_INDEX(i).port = 0;
CONN_INDEX(i).fd = sockets[0];
diff --git a/tcp.h b/tcp.h
index 8fbec30..5aaecd9 100644
--- a/tcp.h
+++ b/tcp.h
@@ -46,6 +46,7 @@ typedef struct {
char *fragment; /* for SPAWN connections: unprocessed text */
char flags;
char state;
+ char old_state;
} connsess;
extern connsess conn_list[MAX_CONNECTS]; /* connection list */