I have a C# WPF application that is making a Telnet connection to write some content to a file on a Linux system from a Windows system. So say I have some text like this.
Here is a bit\tof text \r\n Followed by a new line.
Here is generally how the code goes:
string ipAddress = "11.11.11.11";
int port = 66;
TelnetConnection tc = new TelnetConnection(ipAddress, port);
string s = tc.Login("root", "password", 100);
string prompt = s.TrimEnd();
if (prompt != "$" && prompt != "#"){
throw new Exception("Connection failed");
}
tc.WriteLine("echo $'Here is a bit\tof text \r\n Followed by a new line.' >> MyFile.txt");
Here is the TelnetConnection class I use:\
enum Verbs
{
WILL = 251,
WONT = 252,
DO = 253,
DONT = 254,
IAC = 255
}
enum Options
{
SGA = 3
}
class TelnetConnection
{
TcpClient tcpSocket;
int TimeOutMs = 10;
public TelnetConnection(string Hostname, int Port)
{
tcpSocket = new TcpClient(Hostname, Port);
}
public string Login(string Username, string Password, int LoginTimeOutMs)
{
int oldTimeOutMs = TimeOutMs;
TimeOutMs = LoginTimeOutMs;
string s = Read();
if (!s.TrimEnd().EndsWith(":"))
throw new Exception("Failed to connect : no login prompt");
WriteLine(Username);
s = Read();
if (!s.TrimEnd().EndsWith(":"))
throw new Exception("Failed to connect : no password prompt");
WriteLine(Password);
s = Read();
TimeOutMs = oldTimeOutMs;
return s;
}
public void WriteLine(string cmd)
{
Write(cmd "\n");
}
public void Write(string cmd)
{
if (!tcpSocket.Connected) return;
byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
tcpSocket.GetStream().Write(buf, 0, buf.Length);
System.Threading.Thread.Sleep(1000);
}
public string Read()
{
if (!tcpSocket.Connected) return null;
StringBuilder sb = new StringBuilder();
do
{
ParseTelnet(sb);
System.Threading.Thread.Sleep(TimeOutMs);
} while (tcpSocket.Available > 0);
return sb.ToString();
}
public bool IsConnected
{
get { return tcpSocket.Connected; }
}
void ParseTelnet(StringBuilder sb)
{
while (tcpSocket.Available > 0)
{
int input = tcpSocket.GetStream().ReadByte();
switch (input)
{
case -1:
break;
case (int)Verbs.IAC:
// interpret as command
int inputverb = tcpSocket.GetStream().ReadByte();
if (inputverb == -1) break;
switch (inputverb)
{
case (int)Verbs.IAC:
//literal IAC = 255 escaped, so append char 255 to string
sb.Append(inputverb);
break;
case (int)Verbs.DO:
case (int)Verbs.DONT:
case (int)Verbs.WILL:
case (int)Verbs.WONT:
// reply to all commands with "WONT", unless it is SGA (suppres go ahead)
int inputoption = tcpSocket.GetStream().ReadByte();
if (inputoption == -1) break;
tcpSocket.GetStream().WriteByte((byte)Verbs.IAC);
if (inputoption == (int)Options.SGA)
tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL : (byte)Verbs.DO);
else
tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT);
tcpSocket.GetStream().WriteByte((byte)inputoption);
break;
default:
break;
}
break;
default:
sb.Append((char)input);
break;
}
}
}
}
When I go to check the file the it is written to like this
Here is a bitof text
Followed by a new line.
So the tab character isn't even read, but the new line is for some reason. Any ideas?
CodePudding user response:
This is actually very simple and is not telnet specific.
Open up Powershell or Cmd and try typing your string and you will see.
command lines interpret tab as either a command complete (auto-complete closest match ex. '>ec\t' will produce '>echo'), move to next field or throws the tab away.
you need to replace '\t' (for this particular use) with spaces.
Tabs CAN generally be sent over telnet. I do it all the time. usually the server interprets it as a request to move to next field.
For example 'MyName\tpassword' will fill in first field with MyName and then move to next field and fill with password
CodePudding user response:
It depends on what system you are connection to and what shell is running there but you probably need to double escape tab so it's not only \t
but \\t
so that a \
and a t
is sent to the shell. But then you need to enable the echo command to interpret the \t
not as string but as escaped thats done with the -e
switch in bash. At least in bash that should look like this.
tc.WriteLine("echo -e \"Here is a bit\\tof text \\r\\n Followed by a new line.\" >> MyFile.txt");