예제 #1
0
        /// <summary>
        /// Initializes a new instance of a <see cref="TerminalEmulator"/> using the specified font to display text.
        /// </summary>
        public TerminalEmulator()
        {
            var options = new TerminalOptions();

            options.LFlag = PtyConstants.ICANON | PtyConstants.ECHO;
            options.C_cc[PtyConstants.VERASE] = (byte)'\b';
            options.C_cc[PtyConstants.VEOL]   = (byte)'\r';
            options.C_cc[PtyConstants.VEOL2]  = (byte)'\n';

            PseudoTerminal.CreatePair(out _master, out _slave, options);

            _stdout           = new StreamWriter(_master);
            _stdin            = new StreamReader(_master);
            _stdout.AutoFlush = true;


            HasFocusedChanged += (o, a) =>
            {
                if (IsFocused)
                {
                    _cursorOn   = true;
                    _cursorAnim = 0;
                    Invalidate(true);
                }
            };
        }
예제 #2
0
            /// <inheritdoc/>
            public ServerResponseType HandleMessage(Backend backend, ServerMessageType message, string session, BinaryReader datareader, BinaryWriter datawriter)
            {
                PseudoTerminal _master = null;
                PseudoTerminal _slave  = null;

                var options = new TerminalOptions();

                options.LFlag = PtyConstants.ICANON;
                options.C_cc[PtyConstants.VERASE] = (byte)'\b';
                options.C_cc[PtyConstants.VEOL]   = (byte)'\r';
                options.C_cc[PtyConstants.VEOL2]  = (byte)'\n';

                PseudoTerminal.CreatePair(out _master, out _slave, options);



                int slaveRemoteId = _remoteStreams.Create(_slave, session);


                var stdout = new StreamWriter(new BroadcastingStream(backend, session));

                stdout.AutoFlush = true;
                var stdin = new StreamReader(_master);

                string commandname = datareader.ReadString();
                int    argCount    = datareader.ReadInt32();

                string[] argv = new string[argCount];
                for (int i = 0; i < argCount; i++)
                {
                    argv[i] = datareader.ReadString();
                }

                var trmmgr = backend.GetBackendComponent <TerminalManager>();

                Task.Run(() =>
                {
                    try
                    {
                        trmmgr.RunCommand(backend, commandname, argv, session, stdin, stdout);
                    }
                    catch (TerminationRequestException)
                    {
                        Logger.Log("Terminated command.");
                    }
                    finally
                    {
                        stdout.Write((char)0x02);
                    }
                });
                datawriter.Write(slaveRemoteId);

                return(ServerResponseType.REQ_SUCCESS);
            }
예제 #3
0
파일: RunDoor.cs 프로젝트: orf53975/GameSrv
        private void RunDoorDOSEMU(string command, string parameters)
        {
            if (Helpers.Debug)
            {
                _ClientThread.UpdateStatus("DEBUG: DOSEMU launching " + command + " " + parameters);
            }

            PseudoTerminal pty = null;

            Mono.Unix.UnixStream us = null;
            int WaitStatus;

            try {
                bool      DataTransferred = false;
                int       LoopsSinceIO    = 0;
                Exception ReadException   = null;

                // If we're running a batch file, add a CALL to it
                if (command.ToUpper().Contains(".BAT"))
                {
                    command = "call " + command;
                }

                string[] ExternalBat = new string[] { "@echo off", "lredir g: linux\\fs" + ProcessUtils.StartupPath, "set path=%path%;g:\\dosutils", "fossil.com", "share.com", "ansi.com", "g:", command + " " + parameters, "exitemu" };
                FileUtils.FileWriteAllText(StringUtils.PathCombine(ProcessUtils.StartupPath, "node" + _ClientThread.NodeInfo.Node.ToString(), "external.bat"), String.Join("\r\n", ExternalBat), RMEncoding.Ansi);

                string[] Arguments = new string[] { "HOME=" + ProcessUtils.StartupPath, "HOME=" + ProcessUtils.StartupPath, "QUIET=1", "DOSDRIVE_D=" + StringUtils.PathCombine(ProcessUtils.StartupPath, "node" + _ClientThread.NodeInfo.Node.ToString()), "/usr/bin/nice", "-n19", "/usr/bin/dosemu.bin", "-Ivideo { none }", "-Ikeystroke \\r", "-Iserial { virtual com 1 }", "-t", "-Ed:external.bat", "-o" + StringUtils.PathCombine(ProcessUtils.StartupPath, "node" + _ClientThread.NodeInfo.Node.ToString(), "dosemu.log") };//, "2> /gamesrv/NODE" + _CT.NodeInfo.Node.ToString() + "/DOSEMU_BOOT.LOG" }; // TODO add configuration variable so this path is not hardcoded
                if (Helpers.Debug)
                {
                    _ClientThread.UpdateStatus("Executing /usr/bin/env " + string.Join(" ", Arguments));
                }

                lock (Helpers.PrivilegeLock) {
                    try {
                        Helpers.NeedRoot();
                        pty = PseudoTerminal.Open(null, "/usr/bin/env", Arguments, "/tmp", 80, 25, false, false, false);
                        us  = new Mono.Unix.UnixStream(pty.FileDescriptor, false);
                    } finally {
                        Helpers.DropRoot(Config.Instance.UnixUser);
                    }
                }

                new Thread(delegate(object p) {
                    // Send data from door to user
                    try {
                        byte[] Buffer = new byte[10240];
                        int NumRead   = 0;

                        while (!_ClientThread.QuitThread())
                        {
                            NumRead = us.Read(Buffer, 0, Buffer.Length);
                            if (NumRead > 0)
                            {
                                _ClientThread.NodeInfo.Connection.WriteBytes(Buffer, NumRead);
                                DataTransferred = true;
                            }
                        }
                    } catch (Exception ex) {
                        ReadException = ex;
                    }
                }).Start();

                // Check if we need to run cpulimit
                if (File.Exists(StringUtils.PathCombine(ProcessUtils.StartupPath, "cpulimit.sh")))
                {
                    Process.Start(StringUtils.PathCombine(ProcessUtils.StartupPath, "cpulimit.sh"), pty.ChildPid.ToString());
                }

                // Loop until something happens
                while (!_ClientThread.QuitThread()) // NB: Was simply _Stop before
                {
                    DataTransferred = false;

                    // Check for exception in read thread
                    if (ReadException != null)
                    {
                        return;
                    }

                    // Check for dropped carrier
                    if (!_ClientThread.NodeInfo.Connection.Connected)
                    {
                        int Sleeps = 0;

                        _ClientThread.UpdateStatus("User hung-up while in external program");
                        Mono.Unix.Native.Syscall.kill(pty.ChildPid, Mono.Unix.Native.Signum.SIGHUP);
                        while ((Sleeps++ < 5) && (Mono.Unix.Native.Syscall.waitpid(pty.ChildPid, out WaitStatus, Mono.Unix.Native.WaitOptions.WNOHANG) == 0))
                        {
                            Thread.Sleep(1000);
                        }
                        if (Mono.Unix.Native.Syscall.waitpid(pty.ChildPid, out WaitStatus, Mono.Unix.Native.WaitOptions.WNOHANG) == 0)
                        {
                            _ClientThread.UpdateStatus("Process still active after waiting 5 seconds");
                        }
                        return;
                    }

                    // Send data from user to door
                    if (_ClientThread.NodeInfo.Connection.CanRead())
                    {
                        // Write the text to the program
                        byte[] Bytes = _ClientThread.NodeInfo.Connection.ReadBytes();
                        for (int i = 0; i < Bytes.Length; i++)
                        {
                            us.WriteByte((byte)Bytes[i]);
                            us.Flush();
                        }

                        DataTransferred = true;
                    }

                    // Checks to perform when there was no I/O
                    if (!DataTransferred)
                    {
                        LoopsSinceIO++;

                        // Only check process termination after 300 milliseconds of no I/O
                        // to allow for last minute reception of output from DOS programs
                        if (LoopsSinceIO >= 3)
                        {
                            // Check if door terminated
                            if (Mono.Unix.Native.Syscall.waitpid(pty.ChildPid, out WaitStatus, Mono.Unix.Native.WaitOptions.WNOHANG) != 0)
                            {
                                break;
                            }
                        }

                        // Let's make sure the socket is up
                        // Sending will trigger a socket d/c detection
                        if (LoopsSinceIO >= 300)
                        {
                            switch (_ClientThread.NodeInfo.ConnectionType)
                            {
                            case ConnectionType.RLogin:
                                _ClientThread.NodeInfo.Connection.Write("\0");
                                break;

                            case ConnectionType.Telnet:
                                ((TelnetConnection)_ClientThread.NodeInfo.Connection).SendGoAhead();
                                break;

                            case ConnectionType.WebSocket:
                                _ClientThread.NodeInfo.Connection.Write("\0");
                                break;
                            }
                        }

                        // Delay for 100ms (unless the user hits a key, in which case break the delay early)
                        _ClientThread.NodeInfo.Connection.CanRead(100);
                    }
                    else
                    {
                        LoopsSinceIO = 0;
                    }
                }
            } finally {
                // Terminate process if it hasn't closed yet
                if (pty != null)
                {
                    if (Mono.Unix.Native.Syscall.waitpid(pty.ChildPid, out WaitStatus, Mono.Unix.Native.WaitOptions.WNOHANG) == 0)
                    {
                        _ClientThread.UpdateStatus("Terminating process");
                        Mono.Unix.Native.Syscall.kill(pty.ChildPid, Mono.Unix.Native.Signum.SIGKILL);
                    }
                    pty.Dispose();
                }
            }
        }