public void WriteLine(string format, params object[] args)
        {
            using (var fd = new PosixFileDescriptor(TtyDeviceName, OpenFlags.O_RDWR))
            {
                if (fd.IsInvalid)
                {
                    Trace.WriteLine("Not a TTY, abandoning write line.");
                    return;
                }

                fd.Write(string.Format(format, args));
                fd.Write("\n");
            }
        }
        private string Prompt(string prompt, bool echo)
        {
            using (var fd = new PosixFileDescriptor(TtyDeviceName, OpenFlags.O_RDWR))
            {
                if (fd.IsInvalid)
                {
                    Trace.WriteLine("Not a TTY, abandoning prompt.");
                    return(null);
                }

                fd.Write($"{prompt}: ");

                var sb = new StringBuilder();

                using (CreateTtyContext(fd, echo))
                {
                    var  readBuf = new byte[1];
                    bool eol     = false;
                    while (!eol)
                    {
                        int nr;
                        // Read one byte at a time
                        if ((nr = fd.Read(readBuf, 1)) != 1)
                        {
                            // Either we reached end of file or an error occured.
                            // We don't care which so let's just trace and terminate further reading.
                            Trace.WriteLine($"Exiting POSIX terminal prompt read-loop unexpectedly (nr={nr})");
                            eol = true;
                            break;
                        }

                        int c = readBuf[0];
                        switch (c)
                        {
                        case 3:     // CTRL + C
                            // Since `read` is a blocking call we must manually raise the SIGINT signal
                            // when the user types CTRL+C into the terminal window.
                            int pid = Unistd.getpid();
                            Trace.WriteLine($"Intercepted SIGINT during terminal prompt read-loop - sending SIGINT to self (pid={pid})");
                            Signal.kill(pid, Signal.SIGINT);
                            break;

                        case '\n':
                            eol = true;
                            // Only need to echo the newline to move the terminal cursor down when
                            // echo is disabled. When echo is enabled the newline is written for us.
                            if (!echo)
                            {
                                fd.Write("\n");
                            }
                            break;

                        case '\b':
                        case DeleteChar:
                            if (sb.Length > 0)
                            {
                                sb.Remove(sb.Length - 1, 1);
                                fd.Write("\b \b");
                            }
                            break;

                        default:
                            sb.Append((char)c);
                            break;
                        }
                    }
                    return(sb.ToString());
                }
            }
        }