0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-05-12 22:33:25 +00:00
Files
2022-01-04 12:22:53 +02:00

904 lines
26 KiB
C

/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: telnetio.c$
* $Version : 3.8.14.3$
* $Date : May-30-2012$
*
* Comments:
*
* This file contains the implementation of an MQX
* telnet I/O device.
*
*END************************************************************************/
#include <rtcs.h>
#include <fio.h>
#include <serial.h>
#include "telnet.h"
#define CRLF_MODE(io_ptr) (io_ptr->TERMINAL_OPTIONS & TEROPT_CRLF_MODE)
#define RAW_MODE(io_ptr) (io_ptr->TERMINAL_OPTIONS & TEROPT_RAW_MODE)
typedef struct io_telnet {
MQX_FILE_PTR NETWORK_FD;
MQX_FILE_PTR CONSOLE_FD;
uchar REMOTE_OPTIONS[TELNET_MAX_OPTS];
uchar LOCAL_OPTIONS[TELNET_MAX_OPTS];
uint_32 TERMINAL_OPTIONS;
uint_32 FLAGS;
int_32 STATE;
} IO_TELNET, _PTR_ IO_TELNET_PTR;
_mqx_int _io_telnet_open (MQX_FILE_PTR, char _PTR_, char _PTR_);
_mqx_int _io_telnet_close (MQX_FILE_PTR);
_mqx_int _io_telnet_read (MQX_FILE_PTR, char _PTR_, _mqx_int);
_mqx_int _io_telnet_write (MQX_FILE_PTR, char _PTR_, _mqx_int);
_mqx_int _io_telnet_ioctl (MQX_FILE_PTR, _mqx_uint, pointer);
_mqx_int _io_telnet_process_char (char _PTR_, MQX_FILE_PTR);
boolean _io_telnet_echo(IO_TELNET_PTR io_ptr, char c);
/*
** Telnet Response strings
*/
static _mqx_int TELNET_go_ahead(MQX_FILE_PTR fd) {
char buf[] = {TELCMD_IAC, TELCMD_GA};
return _io_write(fd, buf, 2);
}
static _mqx_int TELNET_will(MQX_FILE_PTR fd, char c) {
char buf[3] = {TELCMD_IAC, TELCMD_WILL};
buf[2] = c;
return _io_write(fd, buf, 3);
}
static _mqx_int TELNET_wont(MQX_FILE_PTR fd, char c) {
char buf[3] = {TELCMD_IAC, TELCMD_WONT};
buf[2] = c;
return _io_write(fd, buf, 3);
}
static _mqx_int TELNET_do(MQX_FILE_PTR fd, char c) {
char buf[3] = {TELCMD_IAC, TELCMD_DO};
buf[2] = c;
return _io_write(fd, buf, 3);
}
static _mqx_int TELNET_dont(MQX_FILE_PTR fd, char c) {
char buf[3] = {TELCMD_IAC, TELCMD_DONT};
buf[2] = c;
return _io_write(fd, buf, 3);
}
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_install
* Returned Value : int_32 a task error code or MQX_OK
* Comments : Install the telnet device
*
*END*-----------------------------------------------------------------*/
int_32 _io_telnet_install
(
char_ptr identifier
)
{ /* Body */
return _io_dev_install(identifier,
_io_telnet_open,
_io_telnet_close,
_io_telnet_read,
_io_telnet_write,
#if MQX_VERSION < 250
(int_32(_CODE_PTR_)(MQX_FILE_PTR, uint_32, uint_32_ptr))
#endif
_io_telnet_ioctl,
NULL );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_open
* Returned Value : int_32 a task error code or MQX_OK
* Comments : Open the telnet device
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_open
(
MQX_FILE_PTR fd_ptr,
char _PTR_ open_name_ptr,
char _PTR_ flags_ptr
)
{ /* Body */
IO_TELNET_PTR io_ptr;
io_ptr = RTCS_mem_alloc_zero(sizeof(*io_ptr));
if (io_ptr == NULL) {
return MQX_OUT_OF_MEMORY;
} /* Endif */
_mem_set_type(io_ptr, MEM_TYPE_IO_TELNET);
fd_ptr->DEV_DATA_PTR = io_ptr;
io_ptr->NETWORK_FD = (MQX_FILE_PTR)flags_ptr;
io_ptr->CONSOLE_FD = NULL;
#ifdef __MQX__
fd_ptr->FLAGS = IO_SERIAL_ECHO; /* To work around a bug in fgetline() */
#endif
io_ptr->TERMINAL_OPTIONS = TEROPT_CRLF_MODE;
/*
** Send WILL SGA and DO SGA options
*/
TELNET_will (io_ptr->NETWORK_FD, TELOPT_SGA);
TELNET_do (io_ptr->NETWORK_FD, TELOPT_SGA);
return MQX_OK;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_close
* Returned Value : int_32 Error Code
* Comments : Close the telnet device
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_close
(
MQX_FILE_PTR fd_ptr
)
{ /* Body */
IO_TELNET_PTR io_ptr;
_mqx_uint flags;
io_ptr = fd_ptr->DEV_DATA_PTR;
if (io_ptr != NULL) {
/* Reenable local echo */
if (io_ptr->CONSOLE_FD) {
ioctl(io_ptr->CONSOLE_FD, IO_IOCTL_SERIAL_GET_FLAGS, &flags);
flags |= IO_SERIAL_ECHO;
ioctl(io_ptr->CONSOLE_FD, IO_IOCTL_SERIAL_SET_FLAGS, &flags);
} /* Endif */
_mem_free(io_ptr);
fd_ptr->DEV_DATA_PTR = NULL;
} /* Endif */
return MQX_OK;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_read
* Returned Value : Number of characters read
* Comments : Read data from the Telnet device
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_read
(
MQX_FILE_PTR fd_ptr,
char _PTR_ data_ptr,
_mqx_int num
)
{ /* Body */
IO_TELNET_PTR io_ptr;
_mqx_int count, read_count, write_count, ret;
char_ptr read_ptr, write_ptr;
char c;
io_ptr = fd_ptr->DEV_DATA_PTR;
write_ptr = data_ptr;
write_count = 0;
for (;;) {
read_ptr = write_ptr;
count = _io_read(io_ptr->NETWORK_FD, read_ptr, num-write_count);
if (count == IO_EOF) {
return IO_EOF;
} /* Endif */
for (read_count = 0; read_count < count; read_count++) {
c = *read_ptr++;
if ((ret = _io_telnet_process_char(&c, fd_ptr)) == IO_ERROR) {
return ret;
} else if (ret) {
*write_ptr++ = c;
write_count++;
} /* Endif */
} /* Endfor */
if (write_count >= num) {
break;
} /* Endif */
if (write_count && !_io_fstatus(io_ptr->NETWORK_FD)) {
break;
} /* Endif */
} /* Endfor */
return write_count;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_write
* Returned Value : Number of characters written
* Comments : Writes the data to the Telnet device
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_write
(
MQX_FILE_PTR fd_ptr,
char _PTR_ data_ptr,
_mqx_int num
)
{ /* Body */
IO_TELNET_PTR io_ptr;
_mqx_int count;
_mqx_int towrite = 0;
char_ptr scan_ptr;
io_ptr = fd_ptr->DEV_DATA_PTR;
for (count = 0, scan_ptr = data_ptr; count < num; count++, scan_ptr++) {
//transmitting data in real binary mode and avoiding workarounds
//in handling EOLs (different CR LF combinations) valid only for character based terminals
if (RAW_MODE(io_ptr)) {
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) {
if (*scan_ptr == TELCMD_IAC) {
if (fputc(TELCMD_IAC, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
if (fputc(TELCMD_IAC, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} else {
if (fputc(*scan_ptr, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
}
} else { //sending binary data to ASCII remote end should never happen
return IO_ERROR;
}
continue;
}
//handle transmissions for character based terminals including CR LF workarounds
switch (*scan_ptr) {
case TELCMD_IAC:
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) {
if (fputc(TELCMD_IAC, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
if (fputc(TELCMD_IAC, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} // else character is not valid USASCII so filter it
break;
case TELCC_LF:
if (fputc(TELCC_CR, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) {
if (fputc(TELCC_LF, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} else if (CRLF_MODE(io_ptr)) {//in ascii mode CR should be followed by either NULL or LF
if (fputc(TELCC_LF, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} else {
if (fputc(TELCC_NULL, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
}
break;
case TELCC_CR:
//in character based terminal in CRLF mode is possible to transmit stand-alone CRs
if (CRLF_MODE(io_ptr) && !RAW_MODE(io_ptr)) {
if ((count < num) && (*(scan_ptr + 1) != TELCC_LF)) {
if (fputc(TELCC_CR, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
if (fputc(TELCC_NULL, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
}
}
break;
default:
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) {
if (fputc(*scan_ptr, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} else if (!(*scan_ptr & 0x80)) {
if (fputc(*scan_ptr, io_ptr->NETWORK_FD) == IO_EOF) {
return count;
}
} //else filter it
break;
}
}
return count;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_ioctl
* Returned Value : int_32
* Comments : Returns result of ioctl operation.
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_ioctl
(
MQX_FILE_PTR fd_ptr,
_mqx_uint cmd,
pointer param_ptr
)
{ /* Body */
IO_TELNET_PTR io_ptr;
int_32 result;
_mqx_uint flags;
int_32 rawc;
char c;
result = IO_ERROR;
io_ptr = (IO_TELNET_PTR) fd_ptr->DEV_DATA_PTR;
if (io_ptr == NULL) {
return (_mqx_int)result;
} /* Endif */
switch (cmd) {
case IO_IOCTL_CHAR_AVAIL:
while (1) {
*(boolean _PTR_)param_ptr = fstatus(io_ptr->NETWORK_FD);
if (!*(boolean _PTR_)param_ptr) {
break;
} /* Endif */
rawc = (int_32)fgetc(io_ptr->NETWORK_FD);
if (rawc == IO_EOF) {
break;
} /* Endif */
c = (char)rawc;
result = _io_telnet_process_char(&c, fd_ptr);
if (result == IO_ERROR) {
return result;
} else if (result) {
fungetc(c, fd_ptr);
break;
} /* Endif */
} /* Endwhile */
result = MQX_OK;
break;
case IO_IOCTL_SET_STREAM:
io_ptr->CONSOLE_FD = (MQX_FILE_PTR)param_ptr;
/* Clear or set echoing by server */
if (io_ptr->REMOTE_OPTIONS[TELOPT_ECHO])
{
ioctl(io_ptr->CONSOLE_FD, IO_IOCTL_SERIAL_GET_FLAGS, &flags);
flags &= ~IO_SERIAL_ECHO;
ioctl(io_ptr->CONSOLE_FD, IO_IOCTL_SERIAL_SET_FLAGS, &flags);
} /* Endif */
result = MQX_OK;
break;
case IO_IOCTL_SERIAL_GET_FLAGS:
*(_mqx_uint_ptr)param_ptr = io_ptr->FLAGS;
result = MQX_OK;
break;
case IO_IOCTL_SERIAL_SET_FLAGS:
io_ptr->FLAGS = *(_mqx_uint_ptr)param_ptr;
/* Handle defaults */
/* Echo */
if (!io_ptr->LOCAL_OPTIONS[TELOPT_ECHO] && io_ptr->REMOTE_OPTIONS[TELOPT_ECHO])
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
} /* Endif */
if (io_ptr->FLAGS & IO_SERIAL_ECHO)
{
TELNET_will(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
else
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
/* Binary mode */
if (!io_ptr->LOCAL_OPTIONS[TELOPT_BINARY]) { //inbinary
TELNET_will(io_ptr->NETWORK_FD, TELOPT_BINARY);
}
if (!io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) { //outbinary
TELNET_do(io_ptr->NETWORK_FD, TELOPT_BINARY);
}
result = MQX_OK;
break;
case IO_IOCTL_SET_ECHO:
break;
case IO_IOCTL_GET_ECHO:
break;
case IO_IOCTL_SET_INBINARY:
if (!io_ptr->LOCAL_OPTIONS[TELOPT_BINARY]) { //inbinary
TELNET_will(io_ptr->NETWORK_FD, TELOPT_BINARY);
*(boolean _PTR_)param_ptr = TRUE;
} else {
*(boolean _PTR_)param_ptr = FALSE;
}
result = MQX_OK;
break;
case IO_IOCTL_GET_INBINARY:
*(boolean _PTR_)param_ptr = io_ptr->LOCAL_OPTIONS[TELOPT_BINARY];
result = MQX_OK;
break;
case IO_IOCTL_SET_OUTBINARY:
if (!io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) { //outbinary
TELNET_do(io_ptr->NETWORK_FD, TELOPT_BINARY);
*(boolean _PTR_)param_ptr = TRUE;
} else {
*(boolean _PTR_)param_ptr = FALSE;
}
result = MQX_OK;
break;
case IO_IOCTL_GET_OUTBINARY:
*(boolean _PTR_)param_ptr = io_ptr->REMOTE_OPTIONS[TELOPT_BINARY];
result = MQX_OK;
break;
case IO_IOCTL_SET_BINARY:
*(boolean _PTR_)param_ptr = FALSE;
if (!io_ptr->LOCAL_OPTIONS[TELOPT_BINARY]) { //inbinary
TELNET_will(io_ptr->NETWORK_FD, TELOPT_BINARY);
*(boolean _PTR_)param_ptr = TRUE;
}
if (!io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) { //outbinary
TELNET_do(io_ptr->NETWORK_FD, TELOPT_BINARY);
*(boolean _PTR_)param_ptr = TRUE;
}
result = MQX_OK;
break;
case IO_IOCTL_GET_BINARY:
*(boolean _PTR_)param_ptr = io_ptr->LOCAL_OPTIONS[TELOPT_BINARY] && io_ptr->REMOTE_OPTIONS[TELOPT_BINARY];
result = MQX_OK;
break;
case IO_IOCTL_SET_CRLF:
if (*(boolean _PTR_)param_ptr) {
io_ptr->TERMINAL_OPTIONS |= TEROPT_CRLF_MODE;
} else {
io_ptr->TERMINAL_OPTIONS &= ~TEROPT_CRLF_MODE;
}
result = MQX_OK;
break;
case IO_IOCTL_GET_CRLF:
*(boolean _PTR_)param_ptr = (io_ptr->TERMINAL_OPTIONS & TEROPT_CRLF_MODE) > 0;
result = MQX_OK;
break;
case IO_IOCTL_SET_RAW:
if (*(boolean _PTR_)param_ptr) {
io_ptr->TERMINAL_OPTIONS |= TEROPT_RAW_MODE;
} else {
io_ptr->TERMINAL_OPTIONS &= ~TEROPT_RAW_MODE;
}
result = MQX_OK;
break;
case IO_IOCTL_GET_RAW:
*(boolean _PTR_)param_ptr = (io_ptr->TERMINAL_OPTIONS & TEROPT_RAW_MODE) > 0;
result = MQX_OK;
break;
case IO_IOCTL_FLUSH_OUTPUT:
result =ioctl(io_ptr->NETWORK_FD, IO_IOCTL_FLUSH_OUTPUT, param_ptr);
break;
} /* Endswitch */
return (_mqx_int)result;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_echo
* Returned Value : TRUE when character was successfully echoed, FALSE otherwise
* Comments : Echoes given character if server echo is set
*
*
*END*-----------------------------------------------------------------*/
boolean _io_telnet_echo(IO_TELNET_PTR io_ptr, char c) {
//echoing received character
if (io_ptr->LOCAL_OPTIONS[TELOPT_ECHO]) {
if (c == '\b') {
fputs("\b ", io_ptr->NETWORK_FD);
} /* Endif */
if (fputc(c, io_ptr->NETWORK_FD) != c) {
return FALSE;
}
fflush(io_ptr->NETWORK_FD);
return TRUE;
} /* Endif */
return FALSE;
}
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : _io_telnet_process_char
* Returned Value : IO_ERROR, TRUE or FALSE
* Comments : process the arrived characters, including negotiated options
* TRUE is returned when valid ASCII character has been processed.
* FALSE is returned for either IAC, commands or CR which should be combined
* with next character.
* IO_ERROR is returned when received bytes doesn't follow RFC 854, i.e. CR
* followed neither by LF nor by NULL.
*
*END*-----------------------------------------------------------------*/
_mqx_int _io_telnet_process_char
(
char _PTR_ cp,
MQX_FILE_PTR fd_ptr
)
{ /* Body */
char c = *cp;
_mqx_uint flags;
IO_TELNET_PTR io_ptr;
MQX_FILE_PTR console_stream;
io_ptr = fd_ptr->DEV_DATA_PTR;
console_stream = io_ptr->CONSOLE_FD;
switch (io_ptr->STATE) {
case 0: /* Start state */
//receiving data in real binary mode so avoiding workarounds
//in handling EOLs (different CR LF combinations) valid only for character based terminals
if (RAW_MODE(io_ptr) && io_ptr->LOCAL_OPTIONS[TELOPT_BINARY]) {
switch (c) {
case TELCMD_IAC:
io_ptr->STATE = 1;
return FALSE;
default:
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY] || !(c & 0x80)) {
_io_telnet_echo(io_ptr, c);
return TRUE;
} else {
return FALSE; //filter character
}
}
}
if (io_ptr->LOCAL_OPTIONS[TELOPT_BINARY]) { //receiving in binary mode
switch (c) {
case TELCMD_IAC:
io_ptr->STATE = 1;
return FALSE;
case TELCC_CR:
_io_telnet_echo(io_ptr, c);
_io_telnet_echo(io_ptr, TELCC_LF);
*cp = TELCC_LF; //application character mapping to LF
return TRUE;
default:
if (io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) {
//strip extra LF because in binary mode each CR is echoed as CR LF
if (!CRLF_MODE(io_ptr) || (CRLF_MODE(io_ptr) && (c != TELCC_LF))) {
_io_telnet_echo(io_ptr, c);
} else {
return FALSE;
}
} else if (c & 80) { //remote end is in ASCII mode but we have illegal data to send
return FALSE;
} else {
_io_telnet_echo(io_ptr, c);
}
return TRUE;
}
} else { //ASCII mode
switch (c) {
case TELCMD_IAC:
io_ptr->STATE = 1;
return FALSE;
case TELCC_CR:
_io_telnet_echo(io_ptr, c);
io_ptr->STATE = 6;
return FALSE;
default:
if (c & 0x80) { //in ASCII only USASCII codes could be send
return FALSE;
} else {
_io_telnet_echo(io_ptr, c);
return TRUE;
}
}
}
/* Start SPR P122-0266-33 remove all warnings from RTCS code. */
/* break; */
/* End SPR P122-0266-33. */
case 1: /* IAC */
switch (c) {
case TELCMD_AYT:
/*
** Request to send a string to prove we're alive.
** Send back comforting message.
*/
fputs("\nRTCS Telnet server online.\n", fd_ptr);
io_ptr->STATE = 0;
return FALSE;
case TELCMD_EC:
/*
** Request to erase the last character before this command.
*/
*cp = '\b';
io_ptr->STATE = 0;
return TRUE;
case TELCMD_WILL:
io_ptr->STATE = 2;
return FALSE;
case TELCMD_DO:
io_ptr->STATE = 3;
return FALSE;
case TELCMD_WONT:
io_ptr->STATE = 4;
return FALSE;
case TELCMD_DONT:
io_ptr->STATE = 5;
return FALSE;
case TELCMD_IAC:
/* Second IAC is not interpreted as command, it's data */
if (io_ptr->LOCAL_OPTIONS[TELOPT_BINARY] && io_ptr->REMOTE_OPTIONS[TELOPT_BINARY]) { //BINARY mode
_io_telnet_echo(io_ptr, TELCMD_IAC);
_io_telnet_echo(io_ptr, TELCMD_IAC);
io_ptr->STATE = 0;
return TRUE;
} //else filter it (continue with default state)
default:
/* Ignore all other telnet commands (e.g GA) */
io_ptr->STATE = 0;
return FALSE;
} /* Endswitch */
case 2: /* IAC WILL */
switch (c) {
case TELOPT_ECHO:
if (!io_ptr->REMOTE_OPTIONS[TELOPT_ECHO])
{
if ((io_ptr->LOCAL_OPTIONS[TELOPT_ECHO]) || !(io_ptr->FLAGS & IO_SERIAL_ECHO))
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
else
{
/* Clear the echo bit */
ioctl(console_stream, IO_IOCTL_SERIAL_GET_FLAGS, &flags);
flags &= ~IO_SERIAL_ECHO;
ioctl(console_stream, IO_IOCTL_SERIAL_SET_FLAGS, &flags);
io_ptr->REMOTE_OPTIONS[TELOPT_ECHO] = TRUE;
TELNET_do(io_ptr->NETWORK_FD, TELOPT_ECHO);
} /* Endif */
} /* Endif */
else if (!(io_ptr->FLAGS & IO_SERIAL_ECHO))
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
break;
case TELOPT_SGA:
case TELOPT_BINARY:
/* ACK only */
if (!io_ptr->REMOTE_OPTIONS[c]) {
io_ptr->REMOTE_OPTIONS[c] = TRUE;
TELNET_do(io_ptr->NETWORK_FD, c);
} /* Endif */
break;
default:
TELNET_dont(io_ptr->NETWORK_FD, c);
break;
} /* Endswitch */
io_ptr->STATE = 0;
return FALSE;
case 3: /* IAC DO */
switch (c) {
case TELOPT_ECHO:
/* ACK only */
if (!io_ptr->LOCAL_OPTIONS[TELOPT_ECHO])
{
if (io_ptr->REMOTE_OPTIONS[TELOPT_ECHO])
{
if (io_ptr->FLAGS & IO_SERIAL_ECHO)
{
TELNET_wont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
else
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
}
else
{
if (io_ptr->FLAGS & IO_SERIAL_ECHO)
{
io_ptr->LOCAL_OPTIONS[TELOPT_ECHO] = TRUE;
TELNET_will(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
else
{
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
}
} /* Endif */
} /* Endif */
break;
case TELOPT_SGA:
case TELOPT_BINARY:
/* ACK only */
if (!io_ptr->LOCAL_OPTIONS[c]) {
io_ptr->LOCAL_OPTIONS[c] = TRUE;
TELNET_will(io_ptr->NETWORK_FD, c);
} /* Endif */
break;
default:
TELNET_wont(io_ptr->NETWORK_FD, c);
break;
} /* Endswitch */
io_ptr->STATE = 0;
return FALSE;
case 4: /* IAC WONT */
switch (c) {
case TELOPT_ECHO:
if (io_ptr->REMOTE_OPTIONS[TELOPT_ECHO])
{
if (io_ptr->FLAGS & IO_SERIAL_ECHO)
{
/* Set the echo bit */
ioctl(console_stream, IO_IOCTL_SERIAL_GET_FLAGS, &flags);
flags |= IO_SERIAL_ECHO;
ioctl(console_stream, IO_IOCTL_SERIAL_SET_FLAGS, &flags);
}
io_ptr->REMOTE_OPTIONS[TELOPT_ECHO] = FALSE;
TELNET_dont(io_ptr->NETWORK_FD, TELOPT_ECHO);
} /* Endif */
break;
case TELOPT_BINARY:
default:
if (c < TELNET_MAX_OPTS) {
/* ACK only */
if (io_ptr->REMOTE_OPTIONS[c]) {
TELNET_dont(io_ptr->NETWORK_FD, c);
io_ptr->REMOTE_OPTIONS[c] = FALSE;
} /* Endif */
} /* Endif */
break;
} /* Endswitch */
io_ptr->STATE = 0;
return FALSE;
case 5: /* IAC DONT */
if (c < TELNET_MAX_OPTS) {
/* ACK only */
if (io_ptr->LOCAL_OPTIONS[c]) {
io_ptr->LOCAL_OPTIONS[c] = FALSE;
TELNET_wont(io_ptr->NETWORK_FD, c);
} /* Endif */
} /* Endif */
io_ptr->STATE = 0;
return FALSE;
case 6: /* CR received in ASCII mode */
switch (c) {
case TELCC_NULL:
if (CRLF_MODE(io_ptr)) {
*cp = TELCC_CR; //application character mapping to CR
} else {
*cp = TELCC_LF; //application character mapping to LF
}
_io_telnet_echo(io_ptr, *cp);
break;
case TELCC_LF:
_io_telnet_echo(io_ptr, c);
*cp = TELCC_LF; //application character mapping to LF
break;
default:
return IO_ERROR;
}
io_ptr->STATE = 0;
return TRUE;
} /* Endswitch */
/* Start SPR P122-0266-33 remove all warnings from RTCS code. */
/* Will never reach here, this is just for compiler warning. */
return FALSE;
/* End SPR P122-0266-33. */
} /* Endbody */
/* EOF */