// overhaul to support terminal type negotiation correctly 11-08-2007
static bool read_from_descriptor( DESCRIPTOR_DATA *d ) {
int iStart = 0, iErr = 0;
// Check for overflow.
iStart = strlen(d->inbuf);
if( iStart >= MAX_INBUF_SIZE - 10 ) {
char log_buf[MAX_STRING_LENGTH];
sprintf( log_buf, "%s(%lu) input overflow!", d->host, d->uniqueNumber );
log_string( log_buf );
write_to_descriptor( d, "\n\r*** OMG SNAPS!!! ***\n\r", 0);
return FALSE;
}
for( ; ; ) {
int nRead;
nRead = recv( d->descriptor, d->inbuf + iStart, MAX_INBUF_SIZE - 10 - iStart, 0 );
#ifdef WIN32
iErr = WSAGetLastError();
#else
iErr = errno;
#endif
if( nRead > 0 ) {
iStart += nRead;
if( d->inbuf[iStart-1] == '\n' || d->inbuf[iStart-1] == '\r' )
break;
} else if( nRead == 0 ) {
log_string( "EOF encountered on read." );
return FALSE;
} else if( iErr == EWOULDBLOCK ) {
break; // nothing to read
} else {
perror( "Read_from_descriptor" );
return FALSE;
}
}
d->inbuf[iStart] = '\0';
return TRUE;
}
static int check_telopts(DESCRIPTOR_DATA *d, char *soin, int i) {
unsigned char iac_type, iac_command;
int j = 0;
if( (unsigned char)soin[i++] == IAC ) {
iac_type = soin[i++];
if( iac_type == SE ) {
return i;
}
iac_command = soin[i++];
switch( iac_type ) {
case DO:
if( iac_command == TELOPT_SGA ) {
fprintf(stderr, "DO TELOPT_SGA\n");
write_to_descriptor(d, will_suppress_str, 0);
} else if( iac_command == TELOPT_ECHO ) {
fprintf(stderr, "DO TELOPT_ECHO\n");
// we control the vertical and the horizontal
} else
fprintf(stderr, "Unsupported IAC DO command %uc.\n", iac_command);
break;
case WILL:
if( iac_command == TELOPT_COMPRESS2 ) {
fprintf(stderr, "WILL TELOPT_COMPRESS2\n");
compressStart(d);
} else if( iac_command == TELOPT_NAWS ) {
fprintf(stderr, "WILL TELOPT_NAWS\n");
write_to_descriptor(d, neg_naws_str, 0);
} else if( iac_command == TELOPT_TTYPE ) {
fprintf(stderr, "WILL TELOPT_TTYPE\n");
write_to_descriptor(d, neg_term_type_str, 0);
} else if( iac_command == TELOPT_SGA ) {
fprintf(stderr, "WILL TELOPT_SGA\n");
write_to_descriptor(d, do_suppress_str, 0);
} else if( iac_command == TELOPT_SPEED ) {
fprintf(stderr, "WILL TELOPT_SPEED\n");
// we do nothing as this really is obselete, but GO PUTTY!
} else
fprintf(stderr, "Unsupported IAC WILL command %uc.\n", iac_command);
break;
case DONT:
case WONT:
if( iac_command == TELOPT_COMPRESS2 ) {
fprintf(stderr, "DONT/WONT TELOPT_COMPRESS2\n");
compressEnd(d);
} else if( iac_command == TELOPT_TTYPE ) {
fprintf(stderr, "DONT/WONT TELOPT_TTYPE\n");
write_to_descriptor(d, "Client does not support terminal type negotiation, ANSI color disabled.\n", 0);
d->telOpts &= ~8;
} else if( iac_command == TELOPT_NAWS ) {
fprintf(stderr, "DONT/WONT TELOPT_NAWS\n");
// unsupported negotiation on part of client, Pueblo notiably
} else if( iac_command == TELOPT_LINEMODE ) {
fprintf(stderr, "DONT/WONT TELOPT_LINEMODE\n");
// unsupported negotiation on part of client, Pueblo notiably
} else
fprintf(stderr, "Unsupported IAC %s command %uc.\n", (iac_type == DONT ? "DONT" : "WONT"), iac_command);
break;
case SB:
if( iac_command == TELOPT_TTYPE ) {
// should be implemented without fault
char ttype[24]; // should be well long enough for this
j = 0;
fprintf(stderr, "SB TELOPT_TTYPE\n");
// blitz thru until we find ascii characters
while( !isprint(soin[i]) ) i++;
while( isprint(soin[i]) ) {
ttype[j] = LOWER(soin[i]);
i++; j++;
}
ttype[j] = '\0';
j = 0;
while( supported_ansi[j] != NULL ) {
if( strcmp(ttype, supported_ansi[j]) == 0 ) {
write_to_descriptor(d, "ANSI supported.\n", 0);
d->telOpts |= 8;
break;
}
j++;
}
// asks twice for supported clients, then kills ANSI
if( (d->telOpts & 8) == 0 ) {
if( (d->telOpts & 1) == 0 ) {
write_to_descriptor(d, neg_term_type_str, 0);
d->telOpts |= 1;
} else {
d->telOpts &= ~1;
d->telOpts &= ~8;
}
}
} else if( iac_command == TELOPT_NAWS ) {
unsigned char ca, cb, cc, cd; //should be split into four characters
fprintf(stderr, "SB TELOPT_NAWS\n");
d->max_width = 0;
ca = soin[i++];
if( ca > 0 ) {
if( ca == 255 )
ca = soin[i++];
d->max_width += (ca << 8);
}
cb = soin[i++];
if( cb > 0 ) {
if( cb == 255 )
cb = soin[i++];
}
d->max_width += cb;
d->max_height = 0;
cc = soin[i++];
if( cc > 0 ) {
if( cc == 255 )
cc = soin[i++];
d->max_height += (cc << 8);
}
cd = soin[i++];
if( cd > 0 ) {
if( cd == 255 )
cd = soin[i++];
}
d->max_height += cd;
} else
fprintf(stderr, "Unsupported IAC SB command %uc.\n", iac_command);
break;
case SE:
fprintf(stderr, "Bad shit went down in check_telopts.\n");
break;
default:
fprintf(stderr, "Unsupported IAC type %uc.\n", iac_type);
break;
}
}
return i;
}
|