Operating System

Even if you are an app developer, an inside of the system infrastructure would be very beneficial.

Here is an instructive demo.

The objective is to echo a System.Process output running ssh from Mono on Linux.

this is what you’re trying to do:

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace Echo
{
    class Program
    {
        private static void Read(StreamReader reader)
        {
            new Thread(() =>
            {
                while (true)
                {
                    int current;
                    while ((current = reader.Read()) >= 0)
                        Console.Write((char)current);
                }
            }).Start();
        }

        static void Main(string[] args)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(@"/usr/bin/ssh");
            startInfo.Arguments = "-ttty localhost";
            startInfo.CreateNoWindow = true;
            startInfo.ErrorDialog = false;
            startInfo.RedirectStandardError = true;
            startInfo.RedirectStandardInput = true;
            startInfo.RedirectStandardOutput = true;
            startInfo.UseShellExecute = false;
            startInfo.CreateNoWindow = true;
            Process process = new Process();
            process.StartInfo = startInfo;
            process.Start();
            Thread.Sleep(15000); //time to login
            Read(process.StandardOutput);
            Read(process.StandardError);
            process.StandardInput.WriteLine("echoing your input now");
            while (!process.HasExited)
                try { process.StandardInput.WriteLine(Console.ReadLine()); }
                catch {}
            Console.WriteLine(process.ExitCode.ToString());    
        }
    }
}

You need to redirect the StandardInput in order to echo it, but then the cmd in windows will elaborate it line by line (even if you use Console.ReadKey() => process.StandardInput.Write), so you can’t have shell support while typing. But mono with linux ssh behaves differently from windows cmd, so the following could be acceptable maybe: commands are echoed and even the tab while typing a dir is managed

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace Echo
{
    class Program
    {
        private static Process process;
        private static void Read(StreamReader reader)
        {
            new Thread(() =>
            {
                while (!process.HasExited)
                {
                    int current;
                    while ((current = reader.Read()) >= 0)
                        Console.Write((char)current);
                }
            }).Start();

       }

        static void Main(string[] args)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(@"/usr/bin/ssh");
            startInfo.Arguments = "-ttty localhost";
            startInfo.CreateNoWindow = true;
            startInfo.ErrorDialog = false;
            startInfo.RedirectStandardError = true;
            startInfo.RedirectStandardInput = true;
            startInfo.RedirectStandardOutput = true;
            startInfo.UseShellExecute = false;
            startInfo.CreateNoWindow = true;
            process = new Process();
            process.StartInfo = startInfo;
            process.Start();
            Thread.Sleep(15000); //time to login
            Read(process.StandardOutput);
            Read(process.StandardError);
            process.StandardInput.WriteLine("echo echoing your input now");
            //Console.ReadLine();
            string theLine = "\n";
            while (!process.HasExited)
                try {
                    ConsoleKeyInfo kinfo =  Console.ReadKey(true);
                   char theKey = kinfo.KeyChar;
                    theLine += theKey;
                    process.StandardInput.Write(theKey) ;
                    process.StandardInput.Flush();
                    if (theKey.Equals('\n'))
                    {
                        Console.WriteLine(theLine);
                        theLine = "\n";
                    }

                }
                catch { }
            Console.WriteLine(process.ExitCode.ToString());
        }
    }
}

If you want to also manage the terminal escape sequences for the UpArrow/DownArrow, here is the code (tested on my Ubuntu terminal)

            string theLine = "\n";
            string theEsc = ((char)27).ToString();
            while (!process.HasExited)
                try {
                    //byte[] bytes = new byte[1];
                    ConsoleKeyInfo kinfo =  Console.ReadKey(true);
                    char theKey = kinfo.KeyChar;
                    theLine += theKey;
                    switch (kinfo.Key)
        {

case ConsoleKey.DownArrow:
                            process.StandardInput.Write(theEsc+"[B");
 break;
case ConsoleKey.UpArrow:
                            process.StandardInput.Write(theEsc+"[A");
 break;
default:
                            process.StandardInput.Write(theKey);
 break;
        }
                    process.StandardInput.Flush();
                    if (theKey.Equals('\n'))
                    {
                        Console.Write(theLine);
                        theLine = "\n";

                    }

                }

This is the change to the code:

        process.StandardInput.WriteLine("stty -a");
        process.StandardInput.WriteLine("stty echo"); // or "reset" insted of "stty echo"
        process.StandardInput.WriteLine("echo echoing your input now");

Now you could do something like the following

process_info.Arguments =  "-ttt hostname 'stty echo; '$SHELL' -i'"; // or reset insted of stty echo

In conclusion the source you’re showing – and more specifically c# System.Process – is not supposed to echo anything (unless one intentionally redirects the standard I/O, as I’ve done at the beginning above). Echoing is a behavior of the shell, in Linux as well as in Windows: that can be managed as shown here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s