/******************************************************************************
* This file is part of a software distribution, which is furnished under the *
* terms of a license. Use of this software by any means is subject to this *
* license and signifies the acceptance of the licensing terms stated *
* therein. Please see the file LICENSE in the top-level directory of this *
* software distribution for detailed copyright disclaimers and licensing *
* terms. *
******************************************************************************
* Copryight (c) by Andreas S. Wetzel - All rights reserved. *
******************************************************************************/
/* $Id: vd_telopts.c,v 1.2 2001/03/19 14:54:06 mickey Exp $ */
#include <vchat.h>
#include <if_telnet.h>
#include <proto_vchatd.h>
/*** Globals ***/
extern u_char subopt_buf[];
extern u_char *sub_bufptr;
extern u_char *sub_endptr;
extern char *topts[];
extern u_short tel_option[];
extern u_short do_dont_response[];
extern u_short will_wont_response[];
extern VP vp;
extern VD vd;
/*** Code ***/
void dooption(u_char opcode)
{
int ok = 0;
if(will_wont_response[opcode])
{
--will_wont_response[opcode];
if(will_wont_response[opcode] && my_state_is_will(opcode))
--will_wont_response[opcode];
}
if(!will_wont_response[opcode] && my_want_state_is_wont(opcode))
{
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(REQ) DO %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(REQ) DO %d", opcode);
/* In case we are willing to use */
/* the specified option, we set */
/* ok, and reply with WILL option. */
/* Otherwise we will always reject */
/* the request, and reply WONT opt */
switch(opcode)
{
case TELOPT_TTYPE: ok++;
break;
case TELOPT_BINARY: ok++;
break;
case TELOPT_ECHO: ok++;
break;
case TELOPT_SGA: ok++;
break;
default: break;
}
if(ok)
{
set_my_want_state_will(opcode);
send_will(opcode, 1);
}
else
{
will_wont_response[opcode]++;
send_wont(opcode, 1);
}
}
else
{
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(ACK) DO %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(ACK) DO %d", opcode);
}
set_my_state_will(opcode);
}
void dontoption(u_char opcode)
{
if(will_wont_response[opcode])
{
--will_wont_response[opcode];
if(will_wont_response[opcode] && my_state_is_wont(opcode))
--will_wont_response[opcode];
}
if(!will_wont_response[opcode] && my_want_state_is_will(opcode))
{
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(REQ) DONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(REQ) DONT %d", opcode);
/* REMEMBER: It should always be o.k to turn off */
/* some set of options. */
switch(opcode)
{
case TELOPT_BINARY: /* The client wants */
/* us to do only 7 bits ... */
/* tse tse tse ... */
break;
case TELOPT_ECHO: /* We are not willing to turn */
/* off our echo, but let the */
/* client think, we did so. */
break;
default: break;
}
set_my_want_state_wont(opcode);
if(my_state_is_will(opcode))
send_wont(opcode, 1);
}
else
{
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(ACK) DONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(ACK) DONT %d", opcode);
}
set_my_state_wont(opcode);
}
void willoption(u_char opcode)
{
int ok = 0;
if(do_dont_response[opcode])
{
--do_dont_response[opcode];
if(do_dont_response[opcode] && his_state_is_will(opcode))
--do_dont_response[opcode];
}
if(!do_dont_response[opcode])
{
if(his_want_state_is_wont(opcode))
{
/* requests of client side */
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(REQ) WILL %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(REQ) WILL %d", opcode);
switch(opcode)
{
case TELOPT_SGA: ok++;
break;
case TELOPT_BINARY: ok++;
break;
case TELOPT_TTYPE: ok++;
break;
default: break;
}
if(ok)
{
set_his_want_state_will(opcode);
send_do(opcode, 1);
}
else
{
do_dont_response[opcode]++;
send_dont(opcode, 1);
}
}
else
{
/* confirmation of our own requests */
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(ACK) WILL %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(ACK) WILL %d", opcode);
switch(opcode)
{
case TELOPT_ECHO: /* ARGH!! Client responded */
/* with WILL ECHO. Since we */
/* don't want the client to */
/* echo our chars, let us */
/* turn it off right away. */
send_dont(TELOPT_ECHO, 1);
break;
default: break;
}
}
}
set_his_state_will(opcode);
}
void wontoption(u_char opcode)
{
if(do_dont_response[opcode])
{
--do_dont_response[opcode];
if(do_dont_response[opcode] && his_state_is_wont(opcode))
--do_dont_response[opcode];
}
if(!do_dont_response[opcode])
{
if(his_want_state_is_will(opcode))
{
/* requests of client side */
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(REQ) WONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(REQ) WONT %d", opcode);
switch(opcode)
{
case TELOPT_BINARY: break;
default: break;
}
set_his_want_state_wont(opcode);
if(his_state_is_will(opcode))
send_dont(opcode, 1);
}
else
{
/* confirmation of our own requests */
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(ACK) WONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(ACK) WONT %d", opcode);
switch(opcode)
{
default: break;
}
}
}
set_his_state_wont(opcode);
}
void handle_suboption(void)
{
static char lasttype[128];
char tmp[128];
char *fuseltmp = &tmp[0];
u_short x;
u_short y;
u_short cmd;
/*
* This indeed IS --> STRAIGHTFORWARD!
*/
cmd = SUB_GET();
switch(cmd)
{
case TELOPT_NAWS: x = (0x100 * SUB_GET());
x += SUB_GET();
y = (0x100 * SUB_GET());
y += SUB_GET();
log(VLOG_INFO, "Reported screen size: %dx%d", x, y);
sprintf(vd.env_cols, "COLUMNS=%d", x);
putenv(vd.env_cols);
sprintf(vd.env_lines, "LINES=%d", y);
putenv(vd.env_lines);
resize();
log(VLOG_INFO, "Changed screen size to %dx%d", x, y);
break;
case TELOPT_TTYPE: if((x = SUB_GET()) == TELQUAL_SEND)
{
/*
* Terminal type? What terminal type?
* We are cool, so we respond simply
* with 'network' ;-)
*/
printf("%c%c%c%cnetwork%c%c",
IAC, SB, TELOPT_TTYPE,
TELQUAL_IS, IAC, SE);
log(VLOG_DEBUG, "(TTYPE) Reporting terminal type network");
}
else if(x == TELQUAL_IS)
{
while(!(SUB_EOF() || (y = SUB_GET()) == IAC))
{
*fuseltmp++ = y;
}
*fuseltmp = '\0';
str_lower(tmp);
log(VLOG_INFO, "Reported terminaltype is %s", tmp);
if(check_termtype(tmp) == 1)
{
strcpy(vd.env_term, tmp);
vp.emulation = (char *)&vd.env_term;
vd.emu_ok = 0xff;
}
else if(strcmp(lasttype, tmp))
{
strcpy(lasttype, tmp);
printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);
}
else
{
strcpy(vd.env_term, FALLBACK_TTYPE);
vp.emulation = (char *)&vd.env_term;
vd.emu_ok = 0xff;
printf("\r\nUnable to negotiate common terminaltype for this telnet session.\r\n");
printf("Falling back to %s\r\n", FALLBACK_TTYPE);
log(VLOG_INFO, "Could not negotiate common terminal type.");
log(VLOG_INFO, "Falling back to %s", FALLBACK_TTYPE);
}
}
else
{
log(VLOG_INFO, "(TTYPE) Huh?");
}
break;
default: log(VLOG_INFO, "Unknown sub command: $%02x", cmd);
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1