mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
RDB's patch:
- `local ldisc' config option now switches between PuTTY's original behaviour when off (aggressively start negotiations, never use local line discipline) and Unix telnet's off-port-25 behaviour when on (wait to be negotiated with, toggle local line discipline when TELOPT_ECHO changes) - SYNCH handling has been improved again, though it may still be broken due to WinSock being irretrievably pants [originally from svn r420]
This commit is contained in:
parent
cfc0852580
commit
0d672df0ed
109
telnet.c
109
telnet.c
@ -133,10 +133,7 @@ static struct Opt *opts[] = {
|
|||||||
&o_we_sga, &o_they_sga, NULL
|
&o_we_sga, &o_they_sga, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
|
||||||
static int in_synch;
|
static int in_synch;
|
||||||
#endif
|
|
||||||
|
|
||||||
static int sb_opt, sb_len;
|
static int sb_opt, sb_len;
|
||||||
static char *sb_buf = NULL;
|
static char *sb_buf = NULL;
|
||||||
static int sb_size = 0;
|
static int sb_size = 0;
|
||||||
@ -216,11 +213,8 @@ static void activate_option (struct Opt *o) {
|
|||||||
*/
|
*/
|
||||||
deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
|
deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
|
||||||
}
|
}
|
||||||
if (o->option == TELOPT_ECHO)
|
if (o->option == TELOPT_ECHO && cfg.ldisc_term)
|
||||||
{
|
|
||||||
cfg.ldisc_term = FALSE;
|
|
||||||
ldisc = &ldisc_simple;
|
ldisc = &ldisc_simple;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refused_option (struct Opt *o) {
|
static void refused_option (struct Opt *o) {
|
||||||
@ -229,11 +223,8 @@ static void refused_option (struct Opt *o) {
|
|||||||
send_opt (WILL, TELOPT_OLD_ENVIRON);
|
send_opt (WILL, TELOPT_OLD_ENVIRON);
|
||||||
o_oenv.state = REQUESTED;
|
o_oenv.state = REQUESTED;
|
||||||
}
|
}
|
||||||
if (o->option == TELOPT_ECHO)
|
if (o->option == TELOPT_ECHO && cfg.ldisc_term)
|
||||||
{
|
|
||||||
cfg.ldisc_term = TRUE;
|
|
||||||
ldisc = &ldisc_term;
|
ldisc = &ldisc_term;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proc_rec_opt (int cmd, int option) {
|
static void proc_rec_opt (int cmd, int option) {
|
||||||
@ -407,10 +398,20 @@ static void do_telnet_read (char *buf, int len) {
|
|||||||
telnet_state = SEENIAC;
|
telnet_state = SEENIAC;
|
||||||
else {
|
else {
|
||||||
b[0] = c;
|
b[0] = c;
|
||||||
#if 0
|
|
||||||
if (!in_synch)
|
if (!in_synch)
|
||||||
#endif
|
|
||||||
c_write (b, 1);
|
c_write (b, 1);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/* I can't get the F***ing winsock to insert the urgent IAC
|
||||||
|
* into the right position! Even with SO_OOBINLINE it gives
|
||||||
|
* it to recv too soon. And of course the DM byte (that
|
||||||
|
* arrives in the same packet!) appears several K later!!
|
||||||
|
*
|
||||||
|
* Oh well, we do get the DM in the right place so I'll
|
||||||
|
* just stop hiding on the next 0xf2 and hope for the best.
|
||||||
|
*/
|
||||||
|
else if (c == DM) in_synch = 0;
|
||||||
|
#endif
|
||||||
if (c == CR)
|
if (c == CR)
|
||||||
telnet_state = SEENCR;
|
telnet_state = SEENCR;
|
||||||
else
|
else
|
||||||
@ -423,6 +424,10 @@ static void do_telnet_read (char *buf, int len) {
|
|||||||
else if (c == WILL) telnet_state = SEENWILL;
|
else if (c == WILL) telnet_state = SEENWILL;
|
||||||
else if (c == WONT) telnet_state = SEENWONT;
|
else if (c == WONT) telnet_state = SEENWONT;
|
||||||
else if (c == SB) telnet_state = SEENSB;
|
else if (c == SB) telnet_state = SEENSB;
|
||||||
|
else if (c == DM) {
|
||||||
|
in_synch = 0;
|
||||||
|
telnet_state = TOPLEVEL;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* ignore everything else; print it if it's IAC */
|
/* ignore everything else; print it if it's IAC */
|
||||||
if (c == IAC) {
|
if (c == IAC) {
|
||||||
@ -532,12 +537,10 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
|
|||||||
default: return "socket(): unknown error";
|
default: return "socket(): unknown error";
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
{
|
||||||
BOOL b = TRUE;
|
BOOL b = TRUE;
|
||||||
setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
|
setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind to local address.
|
* Bind to local address.
|
||||||
@ -592,13 +595,10 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
|
|||||||
send_opt ((*o)->send, (*o)->option);
|
send_opt ((*o)->send, (*o)->option);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
* Set up SYNCH state.
|
* Set up SYNCH state.
|
||||||
*/
|
*/
|
||||||
in_synch = FALSE;
|
in_synch = FALSE;
|
||||||
#endif
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,39 +626,27 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
|
|||||||
switch (WSAGETSELECTEVENT(lParam)) {
|
switch (WSAGETSELECTEVENT(lParam)) {
|
||||||
case FD_READ:
|
case FD_READ:
|
||||||
case FD_CLOSE:
|
case FD_CLOSE:
|
||||||
ret = recv(s, buf, sizeof(buf), 0);
|
{
|
||||||
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
int clear_of_oob = 1;
|
||||||
return 1;
|
if (ioctlsocket (s, SIOCATMARK, &clear_of_oob) < 0 )
|
||||||
if (ret < 0) /* any _other_ error */
|
|
||||||
return -10000-WSAGetLastError();
|
|
||||||
if (ret == 0) {
|
|
||||||
s = INVALID_SOCKET;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
if (in_synch) {
|
|
||||||
BOOL i;
|
|
||||||
if (ioctlsocket (s, SIOCATMARK, &i) < 0) {
|
|
||||||
return -20000-WSAGetLastError();
|
return -20000-WSAGetLastError();
|
||||||
}
|
|
||||||
if (i)
|
in_synch = !clear_of_oob;
|
||||||
in_synch = FALSE;
|
|
||||||
|
do {
|
||||||
|
ret = recv(s, buf, sizeof(buf), 0);
|
||||||
|
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||||
|
return 1;
|
||||||
|
if (ret < 0) /* any _other_ error */
|
||||||
|
return -10000-WSAGetLastError();
|
||||||
|
if (ret == 0) {
|
||||||
|
s = INVALID_SOCKET;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_telnet_read (buf, ret);
|
||||||
|
} while (in_synch);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
do_telnet_read (buf, ret);
|
|
||||||
return 1;
|
|
||||||
case FD_OOB:
|
|
||||||
do {
|
|
||||||
ret = recv(s, buf, sizeof(buf), 0);
|
|
||||||
} while (ret > 0);
|
|
||||||
telnet_state = TOPLEVEL;
|
|
||||||
do {
|
|
||||||
ret = recv(s, buf, 1, MSG_OOB);
|
|
||||||
if (ret > 0)
|
|
||||||
do_telnet_read (buf, ret);
|
|
||||||
} while (ret > 0);
|
|
||||||
if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
|
||||||
return -30000-WSAGetLastError();
|
|
||||||
return 1;
|
return 1;
|
||||||
case FD_WRITE:
|
case FD_WRITE:
|
||||||
if (outbuf_head != outbuf_reap)
|
if (outbuf_head != outbuf_reap)
|
||||||
@ -681,28 +669,7 @@ static void telnet_send (char *buf, int len) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
if (cfg.ldisc_term) {
|
while (p < buf+len) {
|
||||||
while (p < buf+len) {
|
|
||||||
char *q = p;
|
|
||||||
unsigned char * cstr = 0;
|
|
||||||
while (p < buf+len) {
|
|
||||||
if ((unsigned char)*p == IAC) {
|
|
||||||
cstr = iac;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*p == '\r') {
|
|
||||||
if( p+1 >= buf+len || ( p[1] != '\n' && p[1] != '\0'))
|
|
||||||
{
|
|
||||||
cstr = cr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (p!=q) s_write (q, p-q);
|
|
||||||
if (cstr) s_write (cstr,2), p++;
|
|
||||||
}
|
|
||||||
} else while (p < buf+len) {
|
|
||||||
char *q = p;
|
char *q = p;
|
||||||
|
|
||||||
while (iswritable((unsigned char)*p) && p < buf+len) p++;
|
while (iswritable((unsigned char)*p) && p < buf+len) p++;
|
||||||
|
Loading…
Reference in New Issue
Block a user