Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Runtime.InteropServices;
- namespace Microsoft.PowerShell.Internal
- {
- internal class PlatformUnix
- {
- // termios
- private const int STDIN_FILENO = 0; // File descriptor for Standard Input.
- private const int NCCS = 64; // Size of the array c_cc for control characters.
- // Control Characters (c_cc)
- private const uint VTIME = 5; // Timeout in deciseconds.
- private const uint VMIN = 6; // Minimum number of characters to expect.
- // Local Modes (c_lflag)
- private const uint ICANON = 0000002; // Canonical input (erase and kill processing).
- private const uint ECHO = 0000010; // Enable echo.
- private const uint IEXTEN = 0100000; // Enable extended input character processing.
- // Input Modes (c_iflag)
- private const uint IXON = 0002000; // Enable start/stop output control.
- private const uint IXOFF = 0010000; // Enable start/stop input control.
- // Attribute Selection (tcsetattr)
- private const int TCSANOW = 0; // Change attributes immediately.
- // Poll Events
- private const ushort POLLIN = 0x0001; // Standard Input is ready.
- internal static ConsoleKeyInfo ReadKey()
- {
- BlockUntilKeyAvailable();
- return Console.ReadKey(intercept: true);
- }
- [DllImport("libc")]
- private static extern uint tcgetattr(int fd, IntPtr termios_p);
- [DllImport("libc")]
- private static extern uint tcsetattr(int fd, int optional_actions, IntPtr termios_p);
- [DllImport("libc")]
- private static extern uint poll(ref pollfd fds, uint nfds, int timeout);
- private static void BlockUntilKeyAvailable()
- {
- pollfd fds;
- fds.fd = STDIN_FILENO;
- fds.events = POLLIN;
- fds.revents = 0;
- termios newTerminal = GetTerminal();
- termios previousTerminal = newTerminal;
- newTerminal.c_iflag &= ~(IXON | IXOFF);
- newTerminal.c_lflag &= ~(ECHO | ICANON | IEXTEN);
- newTerminal.c_cc[VMIN] = 1;
- newTerminal.c_cc[VTIME] = 0;
- SetTerminal(newTerminal);
- try
- {
- poll(ref fds, 1, -1);
- }
- finally
- {
- SetTerminal(previousTerminal);
- }
- }
- private static termios GetTerminal()
- {
- IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(termios)));
- try
- {
- if (tcgetattr(STDIN_FILENO, ptr) >= 0)
- {
- return Marshal.PtrToStructure<termios>(ptr);
- }
- return default(termios);
- }
- finally
- {
- Marshal.FreeHGlobal(ptr);
- }
- }
- private static bool SetTerminal(termios termios)
- {
- IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(termios)));
- try
- {
- Marshal.StructureToPtr<termios>(termios, ptr, fDeleteOld: false);
- if (tcsetattr(STDIN_FILENO, TCSANOW, ptr) <= 0)
- {
- return true;
- }
- return false;
- }
- finally
- {
- Marshal.FreeHGlobal(ptr);
- }
- }
- [StructLayout(LayoutKind.Sequential)]
- private struct termios
- {
- // Input Mode Flags
- internal uint c_iflag;
- // Output Mode Flags
- internal uint c_oflag;
- // Control Mode Flags
- internal uint c_cflag;
- // Local Mode Flags
- internal uint c_lflag;
- internal byte c_line;
- /// Control Characters
- [MarshalAs(UnmanagedType.ByValArray, SizeConst=NCCS)]
- internal byte[] c_cc;
- }
- [StructLayout(LayoutKind.Sequential)]
- private struct pollfd
- {
- internal uint fd;
- internal ushort events;
- internal ushort revents;
- }
- }
- }
Add Comment
Please, Sign In to add comment