Exemple #1
0
        public static void Run(ClientThread clientThread)
        {
            if (clientThread == null)
            {
                throw new ArgumentNullException("clientThread");
            }

            // Loop through the options, and run the ones we allow here
            bool ExitFor = false;

            string[] Processes = LogOnProcess.GetProcesses();
            for (int i = 0; i < Processes.Length; i++)
            {
                try {
                    LogOnProcess LP = new LogOnProcess(Processes[i]);
                    if ((LP.Loaded) && (!clientThread.QuitThread()))
                    {
                        switch (LP.Action)
                        {
                        case Action.Disconnect:
                        case Action.DisplayFile:
                        case Action.DisplayFileMore:
                        case Action.DisplayFilePause:
                        case Action.MainMenu:
                        case Action.Pause:
                        case Action.RunDoor:
                            MenuOption MO = new MenuOption("", '\0')
                            {
                                Action         = LP.Action,
                                Name           = LP.Name,
                                Parameters     = LP.Parameters,
                                RequiredAccess = LP.RequiredAccess,
                            };
                            ExitFor = clientThread.HandleMenuOption(MO);
                            break;
                        }
                        if (ExitFor)
                        {
                            break;
                        }
                    }
                } catch (Exception ex) {
                    // If there's something wrong with the ini entry (Action is invalid for example), this will throw a System.ArgumentException error, so we just ignore that menu item
                    RMLog.Exception(ex, "Error during logon process '" + Processes[i] + "'");
                }
            }
        }
Exemple #2
0
        public unsafe void Run(string command, string parameters, int forceQuitDelay)
        {
            if (Helpers.Debug)
            {
                _ClientThread.UpdateStatus("DEBUG: SBBSEXECNT launching " + command + " " + parameters);
            }

            _Command        = command;
            _Parameters     = parameters;
            _ForceQuitDelay = forceQuitDelay;

            try {
                // Initialize variables
                if (Initialize())
                {
                    // Start the door
                    if (StartProcess())
                    {
                        // Loop until something happens
                        bool DataTransferred = false;
                        while (!_ClientThread.QuitThread()) // NB: Was simply _Stop before
                        {
                            // Check for dropped carrier
                            if (UserHungUp())
                            {
                                return;
                            }

                            // Send data from user to door
                            DataTransferred = TransmitFromUserToDoor(out bool UserToDoorError);
                            if (UserToDoorError)
                            {
                                return;
                            }

                            // Send data from door to user
                            DataTransferred |= TransmitFromDoorToUser(out bool DoorToUserError);
                            if (DoorToUserError)
                            {
                                return;
                            }

                            // Checks to perform when there was no I/O
                            if (!DataTransferred)
                            {
                                // Numer of loop iterations with no I/O
                                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 is requesting a hangup (dropped DTR)
                                    if (DoorDroppedDTR())
                                    {
                                        return;
                                    }

                                    // Check if door terminated
                                    if (P.HasExited)
                                    {
                                        _ClientThread.UpdateStatus("External terminated with exit code: " + P.ExitCode);
                                        return;
                                    }

                                    // Check if door is trying to launch a native door
                                    CheckForW32DoorRun();
                                }

                                // Let's make sure the socket is up
                                // Sending will trigger a socket d/c detection
                                if (LoopsSinceIO % 300 == 0)
                                {
                                    SendPing();
                                }

                                // 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 {
                // Stop the process, if it's still running
                StopProcess();

                // Free unmanaged resources
                CleanUp();
            }
        }
Exemple #3
0
        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();
                }
            }
        }