LocalShell.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:6k
源码类别:

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: LocalShell.cs,v 1.2 2005/04/20 08:45:46 okajima Exp $
  4. */
  5. using System;
  6. using System.Drawing;
  7. using System.Windows.Forms;
  8. using System.Net;
  9. using System.Net.Sockets;
  10. using System.Threading;
  11. using System.Diagnostics;
  12. using Microsoft.Win32;
  13. using Poderosa.Connection;
  14. using Poderosa.ConnectionParam;
  15. using Poderosa.Config;
  16. using Poderosa.Communication;
  17. using Poderosa.Toolkit;
  18. namespace Poderosa.LocalShell
  19. {
  20. public abstract class LocalShellUtil {
  21. public static EncodingType DefaultEncoding {
  22. get {
  23. return GEnv.Options.Language==Language.Japanese? EncodingType.SHIFT_JIS : EncodingType.ISO8859_1;
  24. }
  25. }
  26. //愙懕梡僜働僢僩偺僒億乕僩
  27. protected static Socket _listener;
  28. protected static int _localPort;
  29. //摨婜
  30. protected static object _lockObject = new object();
  31. //愙懕愭偺Socket傪弨旛偟偰曉偡丅幐攕偡傟偽parent傪恊偵偟偰僄儔乕傪昞帵偟丄null傪曉偡丅
  32. public static ConnectionTag PrepareSocket(IWin32Window parent, LocalShellTerminalParam param) {
  33. try {
  34. return new Connector(param).Connect();
  35. }
  36. catch(Exception ex) {
  37. string key = IsCygwin(param)? "Message.CygwinUtil.FailedToConnect" : "Message.SFUUtil.FailedToConnect";
  38. GUtil.Warning(parent, GEnv.Strings.GetString(key)+ex.Message);
  39. return null;
  40. }
  41. }
  42. public static Connector AsyncPrepareSocket(ISocketWithTimeoutClient client, LocalShellTerminalParam param) {
  43. Connector c = new Connector(param, client);
  44. GUtil.CreateThread(new ThreadStart(c.AsyncConnect)).Start();
  45. return c;
  46. }
  47. public class Connector {
  48. private LocalShellTerminalParam _param;
  49. private Process _process;
  50. private ISocketWithTimeoutClient _client;
  51. private Thread _asyncThread;
  52. private bool _interrupted;
  53. public Connector(LocalShellTerminalParam param) {
  54. _param = param;
  55. }
  56. public Connector(LocalShellTerminalParam param, ISocketWithTimeoutClient client) {
  57. _param = param;
  58. _client = client;
  59. }
  60. public void AsyncConnect() {
  61. bool success = false;
  62. _asyncThread = Thread.CurrentThread;
  63. try {
  64. ConnectionTag result = Connect();
  65. result.ChildProcess = _process;
  66. success = true;
  67. if(!_interrupted) _client.SuccessfullyExit(result);
  68. }
  69. catch(Exception ex) {
  70. if(!_interrupted) _client.ConnectionFailed(ex.Message);
  71. }
  72. finally {
  73. if(!success && _process!=null)
  74. _process.Kill();
  75. }
  76. }
  77. public void Interrupt() {
  78. _interrupted = true;
  79. }
  80. public ConnectionTag Connect() {
  81. lock(_lockObject) {
  82. if(_localPort==0)
  83. PrepareListener();
  84. PrepareEnv(_param);
  85. }
  86. string cygtermPath = "cygterm\"+(IsCygwin(_param)? "cygterm.exe" : "sfuterm.exe");
  87. string connectionName = IsCygwin(_param)? "Cygwin" : "SFU";
  88. string args = String.Format("-p {0} -v HOME="{1}" -s "{2}"", _localPort, _param.Home, _param.Shell);
  89. ProcessStartInfo psi = new ProcessStartInfo(cygtermPath, args);
  90. psi.CreateNoWindow = true;
  91. psi.ErrorDialog = true;
  92. psi.UseShellExecute = false;
  93. psi.WindowStyle = ProcessWindowStyle.Hidden;
  94. _process = Process.Start(psi);
  95. if(_interrupted) return null;
  96. Socket sock = _listener.Accept();
  97. if(_interrupted) return null;
  98. Size sz = GEnv.Frame.TerminalSizeForNextConnection;
  99. TelnetNegotiator neg = new TelnetNegotiator(_param, sz.Width, sz.Height);
  100. TelnetTerminalConnection r = new TelnetTerminalConnection(_param, neg, new PlainGuevaraSocket(sock), sz.Width, sz.Height);
  101. r.UsingSocks = false;
  102. r.SetServerInfo(connectionName, null);
  103. return new ConnectionTag(r);
  104. }
  105. }
  106. protected static void PrepareListener() {
  107. _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  108. _localPort = 20345;
  109. do {
  110. try {
  111. _listener.Bind(new IPEndPoint(IPAddress.Loopback, _localPort));
  112. _listener.Listen(1);
  113. break;
  114. }
  115. catch(Exception) {
  116. if(_localPort++==20360) throw new Exception("port overflow!!"); //偝偡偑偵偙傟偼傔偭偨偵側偄偼偢
  117. }
  118. } while(true);
  119. }
  120. private static bool _cygwinDLL_loaded;
  121. protected static void PrepareEnv(LocalShellTerminalParam p) {
  122. if(!_cygwinDLL_loaded && IsCygwin(p)) {
  123. //弶夞偺傒丄cygwin.dll偑儘乕僪偱偒傞傛偆偵娐嫬曄悢傪捛壛 SFU偺偲偒偼梋寁偩偑
  124. char[] buf = new char[1024];
  125. int n = Win32.GetEnvironmentVariable("PATH", buf, buf.Length);
  126. string newval = new string(buf, 0, n) + ";" + CygwinUtil.GuessRootDirectory() + "\bin";
  127. Win32.SetEnvironmentVariable("PATH", newval);
  128. _cygwinDLL_loaded = true;
  129. }
  130. }
  131. public static void Terminate() {
  132. if(_listener!=null) _listener.Close();
  133. }
  134. private static bool IsCygwin(LocalShellTerminalParam tp) {
  135. return tp is CygwinTerminalParam;
  136. }
  137. }
  138. public class SFUUtil : LocalShellUtil
  139. {
  140. public static string DefaultHome {
  141. get {
  142. string a = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 
  143. //嵟屻偺偺屻偵Application Data偑偁傞偺偱
  144. int t = a.LastIndexOf('\');
  145. char drive = a[0];
  146. return "/dev/fs/"+Char.ToUpper(drive)+a.Substring(2, t-2).Replace('\','/');
  147. }
  148. }
  149. public static string DefaultShell {
  150. get {
  151. return "/bin/csh -l";
  152. }
  153. }
  154. public static string GuessRootDirectory() {
  155. RegistryKey reg = null;
  156. string keyname = "SOFTWARE\Microsoft\Services for UNIX";
  157. reg = Registry.LocalMachine.OpenSubKey(keyname);
  158. if(reg==null) {
  159. GUtil.Warning(GEnv.Frame, String.Format(GEnv.Strings.GetString("Message.SFUUtil.KeyNotFound"), keyname));
  160. return "";
  161. }
  162. string t = (string)reg.GetValue("InstallPath");
  163. reg.Close();
  164. return t;
  165. }
  166. }
  167. public class CygwinUtil : LocalShellUtil {
  168. public static string DefaultHome {
  169. get {
  170. return "/home/"+Environment.UserName;
  171. }
  172. }
  173. public static string DefaultShell {
  174. get {
  175. return "/bin/bash -i -l";
  176. }
  177. }
  178. public static string GuessRootDirectory() {
  179. RegistryKey reg = null;
  180. string keyname = "SOFTWARE\Cygnus Solutions\Cygwin\mounts v2\/";
  181. //HKCU -> HKLM偺弴偱僒乕僠
  182. reg = Registry.CurrentUser.OpenSubKey(keyname);
  183. if(reg==null) {
  184. reg = Registry.LocalMachine.OpenSubKey(keyname);
  185. if(reg==null) {
  186. GUtil.Warning(GEnv.Frame, String.Format(GEnv.Strings.GetString("Message.CygwinUtil.KeyNotFound"), keyname));
  187. return "";
  188. }
  189. }
  190. string t = (string)reg.GetValue("native");
  191. reg.Close();
  192. return t;
  193. }
  194. }
  195. }