/******************************************************************************
* 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_telproto.c,v 1.2 2001/03/19 14:54:06 mickey Exp $ */
#include <vchat.h>
#include <if_telnet.h>
#include <proto_vchatd.h>
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
/*** Globals ***/
char *topts[NTOPTS+1] =
{
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS",
"TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD",
"NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT",
"BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
"SEND_LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID",
"OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS",
"TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON",
"AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", 0
};
u_char subopt_buf[SUB_BUFSIZE];
u_char *sub_bufptr = &subopt_buf[0];
u_char *sub_endptr = &subopt_buf[0];
u_short tel_option[256];
u_short do_dont_response[256];
u_short will_wont_response[256];
/*** Externals ***/
extern VP vp;
extern VD vd;
/*** Code ***/
void send_do(int opcode, int bypass)
{
if(!bypass)
{
/* Don't send request if already in */
/* requested state and no responses */
/* open, or if we already requested */
/* that state. */
if((!do_dont_response[opcode] && his_state_is_will(opcode))
|| his_want_state_is_will(opcode))
{
return;
}
set_his_want_state_will(opcode);
++do_dont_response[opcode];
}
printf("%c%c%c", IAC, DO, opcode);
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(SND) DO %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(SND) DO %d", opcode);
}
void send_dont(int opcode, int bypass)
{
if(!bypass)
{
/* Don't send request if already in */
/* requested state and no responses */
/* open, or if we already requested */
/* that state. */
if((!do_dont_response[opcode] && his_state_is_wont(opcode))
|| his_want_state_is_wont(opcode))
{
return;
}
set_his_want_state_wont(opcode);
++do_dont_response[opcode];
}
printf("%c%c%c", IAC, DONT, opcode);
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(SND) DONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(SND) DONT %d", opcode);
}
void send_will(int opcode, int bypass)
{
if(!bypass)
{
/* Don't send request if already in */
/* requested state and no responses */
/* open, or if we already requested */
/* that state. */
if((!will_wont_response[opcode] && my_state_is_will(opcode))
|| my_want_state_is_will(opcode))
{
return;
}
set_my_want_state_will(opcode);
++will_wont_response[opcode];
}
printf("%c%c%c", IAC, WILL, opcode);
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(SND) WILL %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(SND) WILL %d", opcode);
}
void send_wont(int opcode, int bypass)
{
if(!bypass)
{
/* Don't send request if already in */
/* requested state and no responses */
/* open, or if we already requested */
/* that state. */
if((!will_wont_response[opcode] && my_state_is_wont(opcode))
|| my_want_state_is_wont(opcode))
{
return;
}
set_my_want_state_wont(opcode);
++will_wont_response[opcode];
}
printf("%c%c%c", IAC, WONT, opcode);
if(TOPT_OK(opcode))
log(VLOG_DEBUG, "(SND) WONT %s", TOPT(opcode));
else
log(VLOG_DEBUG, "(SND) WONT %d", opcode);
}
int request_termtype(void)
{
send_do(TELOPT_TTYPE, 0);
send_do(TELOPT_NAWS, 0);
while(his_will_wont_differs(TELOPT_TTYPE)
|| his_will_wont_differs(TELOPT_NAWS))
{
if(cmd_loop() == -1)
return(-1);
}
if(his_state_is_will(TELOPT_TTYPE))
{
printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);
while(!vd.emu_ok)
{
if(cmd_loop() == -1)
return(-1);
}
}
else
{
strcpy(vd.env_term, DEFAULT_TTYPE);
vp.emulation = (char *)&vd.env_term;
vd.emu_ok = 0xff;
log(VLOG_INFO, "Client side does not support TTYPE option - defaulting to %s.", vp.emulation);
}
#if 0
if(his_state_is_will(TELOPT_NAWS))
{
printf("%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, TELQUAL_SEND, IAC, SE);
}
#endif
return(0);
}
int cmd_loop(void)
{
fd_set rfdset;
int ret, c;
u_char rcvbuf[512];
u_char *bufptr = &rcvbuf[0];
struct timeval tm;
tm.tv_sec = 0;
tm.tv_usec = 350000; /* 0.2 sec */
FD_ZERO(&rfdset);
FD_SET(0, &rfdset);
if((ret = select(1, (fd_set *) &rfdset, (fd_set *) NULL, (fd_set *) NULL,(struct timeval *)&tm)) == -1)
{
log(VLOG_ERR, "cmd_loop(): error in select();");
return(-1);
}
else if(ret)
{
if(FD_ISSET(0, &rfdset))
{
if((ret = read(0, &rcvbuf, 512)) == -1)
{
log(VLOG_ERR, "cmd_loop: read error (%s)", strerror(errno));
return(-1);
}
else if(!ret)
{
log(VLOG_ERR, "cmd_loop: broken pipe");
return(-1);
}
while(ret)
{
if((c = tel_filter(*bufptr++)))
{
log(VLOG_ERR, "cmd_loop(): unwanted user character $%02x", c);
ungetc(c, stdin);
}
--ret;
}
}
}
#ifdef DEBUG
else
{
log(VLOG_DEBUG, "cmd_loop(): Timeout");
}
#endif
return(0);
}
syntax highlighted by Code2HTML, v. 0.9.1