257 lines
7.5 KiB
C#
257 lines
7.5 KiB
C#
|
using System;
|
|||
|
using System.IO;
|
|||
|
using Tamir.SharpSsh.jsch;
|
|||
|
using Tamir.Streams;
|
|||
|
using System.Text;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
|
|||
|
/*
|
|||
|
* SshShell.cs
|
|||
|
*
|
|||
|
* Copyright (c) 2006 Tamir Gal, http://www.tamirgal.com, All rights reserved.
|
|||
|
*
|
|||
|
* Redistribution and use in source and binary forms, with or without
|
|||
|
* modification, are permitted provided that the following conditions are met:
|
|||
|
*
|
|||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|||
|
* this list of conditions and the following disclaimer.
|
|||
|
*
|
|||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|||
|
* notice, this list of conditions and the following disclaimer in
|
|||
|
* the documentation and/or other materials provided with the distribution.
|
|||
|
*
|
|||
|
* 3. The names of the authors may not be used to endorse or promote products
|
|||
|
* derived from this software without specific prior written permission.
|
|||
|
*
|
|||
|
* THIS SOFTWARE IS PROVIDED ``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 THE AUTHOR
|
|||
|
* *OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
|
|||
|
*
|
|||
|
**/
|
|||
|
namespace Tamir.SharpSsh
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Summary description for SshShell.
|
|||
|
/// </summary>
|
|||
|
public class SshShell : SshBase
|
|||
|
{
|
|||
|
private Stream m_sshIO = null;
|
|||
|
private Regex m_expectPattern;
|
|||
|
private bool m_removeTerminalChars = false;
|
|||
|
private bool m_redirectToConsole = false;
|
|||
|
private static string escapeCharsPattern = "\\[[0-9;?]*[^0-9;]";
|
|||
|
|
|||
|
public SshShell(string host, string user, string password)
|
|||
|
: base(host, user, password)
|
|||
|
{
|
|||
|
Init();
|
|||
|
}
|
|||
|
|
|||
|
public SshShell(string host, string user)
|
|||
|
: base(host, user)
|
|||
|
{
|
|||
|
Init();
|
|||
|
}
|
|||
|
|
|||
|
protected void Init()
|
|||
|
{
|
|||
|
ExpectPattern = "";
|
|||
|
m_removeTerminalChars = false;
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnChannelReceived()
|
|||
|
{
|
|||
|
base.OnChannelReceived ();
|
|||
|
if(m_redirectToConsole)
|
|||
|
{
|
|||
|
SetStream(Console.OpenStandardInput(), Console.OpenStandardOutput());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_sshIO = GetStream();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
protected override string ChannelType
|
|||
|
{
|
|||
|
get { return "shell"; }
|
|||
|
}
|
|||
|
|
|||
|
public Stream IO
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
// if(m_sshIO == null)
|
|||
|
// {
|
|||
|
// m_sshIO = GetStream();
|
|||
|
// }
|
|||
|
return m_sshIO;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void WriteLine(string data)
|
|||
|
{
|
|||
|
Write( data+"\r" );
|
|||
|
}
|
|||
|
|
|||
|
public void Write(string data)
|
|||
|
{
|
|||
|
Write( Encoding.Default.GetBytes( data ) );
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
|
|||
|
/// </summary>
|
|||
|
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream. </param>
|
|||
|
public virtual void Write(byte[] buffer)
|
|||
|
{
|
|||
|
Write(buffer, 0, buffer.Length);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
|
|||
|
/// </summary>
|
|||
|
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream. </param>
|
|||
|
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
|
|||
|
/// <param name="count">The number of bytes to be written to the current stream. </param>
|
|||
|
public virtual void Write(byte[] buffer, int offset, int count)
|
|||
|
{
|
|||
|
IO.Write(buffer, offset, count);
|
|||
|
IO.Flush();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a new I/O stream of communication with this SSH shell connection
|
|||
|
/// </summary>
|
|||
|
public Stream GetStream()
|
|||
|
{
|
|||
|
return new CombinedStream(m_channel.getInputStream(), m_channel.getOutputStream());;
|
|||
|
}
|
|||
|
|
|||
|
public void SetStream(Stream inputStream, Stream outputStream)
|
|||
|
{
|
|||
|
m_channel.setInputStream(inputStream);
|
|||
|
m_channel.setOutputStream(outputStream);
|
|||
|
}
|
|||
|
|
|||
|
public void SetStream(Stream s)
|
|||
|
{
|
|||
|
SetStream(s, s);
|
|||
|
}
|
|||
|
|
|||
|
public void RedirectToConsole()
|
|||
|
{
|
|||
|
m_redirectToConsole = true;
|
|||
|
}
|
|||
|
|
|||
|
public virtual bool ShellOpened
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if(m_channel != null)
|
|||
|
{
|
|||
|
return !m_channel.isClosed();
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual bool ShellConnected
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if(m_channel != null)
|
|||
|
{
|
|||
|
return m_channel.isConnected();
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets a value indicating wether this Steam sould remove the terminal emulation's escape sequence characters from the response String.
|
|||
|
/// </summary>
|
|||
|
public bool RemoveTerminalEmulationCharacters
|
|||
|
{
|
|||
|
get{return m_removeTerminalChars;}
|
|||
|
set{m_removeTerminalChars=value;}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A regular expression pattern string to match when reading the resonse using the ReadResponse() method. The default prompt value is "\n" which makes the ReadRespons() method return one line of response.
|
|||
|
/// </summary>
|
|||
|
public string ExpectPattern
|
|||
|
{
|
|||
|
get{return m_expectPattern.ToString();}
|
|||
|
set{m_expectPattern = new Regex(value, RegexOptions.Singleline);}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Reads a response string from the SSH channel. This method will block until the pattern in the 'Prompt' property is matched in the response.
|
|||
|
/// </summary>
|
|||
|
/// <returns>A response string from the SSH server.</returns>
|
|||
|
public string Expect()
|
|||
|
{
|
|||
|
return Expect(m_expectPattern);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Reads a response string from the SSH channel. This method will block until the pattern in the 'Prompt' property is matched in the response.
|
|||
|
/// </summary>
|
|||
|
/// <returns>A response string from the SSH server.</returns>
|
|||
|
public string Expect(string pattern)
|
|||
|
{
|
|||
|
return Expect( new Regex( pattern, RegexOptions.Singleline ));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Reads a response string from the SSH channel. This method will block until the pattern in the 'Prompt' property is matched in the response.
|
|||
|
/// </summary>
|
|||
|
/// <returns>A response string from the SSH server.</returns>
|
|||
|
public string Expect(Regex pattern)
|
|||
|
{
|
|||
|
int readCount;
|
|||
|
StringBuilder resp = new StringBuilder();
|
|||
|
byte[] buff = new byte[1024];
|
|||
|
Match match;
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
readCount = IO.Read(buff, 0, buff.Length);
|
|||
|
if(readCount == -1) break;
|
|||
|
string tmp = System.Text.Encoding.Default.GetString(buff, 0, readCount);
|
|||
|
resp.Append( tmp, 0, readCount);
|
|||
|
string s = resp.ToString();
|
|||
|
match = pattern.Match( s );
|
|||
|
}while(!match.Success);
|
|||
|
|
|||
|
string result = resp.ToString();
|
|||
|
if(RemoveTerminalEmulationCharacters)
|
|||
|
result = HandleTerminalChars(result);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Removes escape sequence characters from the input string.
|
|||
|
/// </summary>
|
|||
|
public static string HandleTerminalChars(string str)
|
|||
|
{
|
|||
|
str = str.Replace("(B)0", "");
|
|||
|
str = Regex.Replace(str, escapeCharsPattern, "");
|
|||
|
str = str.Replace(((char)15).ToString(), "");
|
|||
|
str = Regex.Replace(str, ((char)27)+"=*", "");
|
|||
|
//str = Regex.Replace(str, "\\s*\r\n", "\r\n");
|
|||
|
return str;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|