Guest User

Untitled

a guest
Feb 14th, 2018
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.06 KB | None | 0 0
  1. using System;
  2. using System.Runtime.InteropServices;
  3.  
  4. namespace Microsoft.PowerShell.Internal
  5. {
  6. internal class PlatformUnix
  7. {
  8. // termios
  9. private const int STDIN_FILENO = 0; // File descriptor for Standard Input.
  10. private const int NCCS = 64; // Size of the array c_cc for control characters.
  11.  
  12. // Control Characters (c_cc)
  13. private const uint VTIME = 5; // Timeout in deciseconds.
  14. private const uint VMIN = 6; // Minimum number of characters to expect.
  15.  
  16. // Local Modes (c_lflag)
  17. private const uint ICANON = 0000002; // Canonical input (erase and kill processing).
  18. private const uint ECHO = 0000010; // Enable echo.
  19. private const uint IEXTEN = 0100000; // Enable extended input character processing.
  20.  
  21. // Input Modes (c_iflag)
  22. private const uint IXON = 0002000; // Enable start/stop output control.
  23. private const uint IXOFF = 0010000; // Enable start/stop input control.
  24.  
  25. // Attribute Selection (tcsetattr)
  26. private const int TCSANOW = 0; // Change attributes immediately.
  27.  
  28. // Poll Events
  29. private const ushort POLLIN = 0x0001; // Standard Input is ready.
  30.  
  31. internal static ConsoleKeyInfo ReadKey()
  32. {
  33. BlockUntilKeyAvailable();
  34. return Console.ReadKey(intercept: true);
  35. }
  36.  
  37. [DllImport("libc")]
  38. private static extern uint tcgetattr(int fd, IntPtr termios_p);
  39.  
  40. [DllImport("libc")]
  41. private static extern uint tcsetattr(int fd, int optional_actions, IntPtr termios_p);
  42.  
  43. [DllImport("libc")]
  44. private static extern uint poll(ref pollfd fds, uint nfds, int timeout);
  45.  
  46. private static void BlockUntilKeyAvailable()
  47. {
  48. pollfd fds;
  49. fds.fd = STDIN_FILENO;
  50. fds.events = POLLIN;
  51. fds.revents = 0;
  52.  
  53. termios newTerminal = GetTerminal();
  54. termios previousTerminal = newTerminal;
  55. newTerminal.c_iflag &= ~(IXON | IXOFF);
  56. newTerminal.c_lflag &= ~(ECHO | ICANON | IEXTEN);
  57. newTerminal.c_cc[VMIN] = 1;
  58. newTerminal.c_cc[VTIME] = 0;
  59. SetTerminal(newTerminal);
  60. try
  61. {
  62. poll(ref fds, 1, -1);
  63. }
  64. finally
  65. {
  66. SetTerminal(previousTerminal);
  67. }
  68. }
  69.  
  70. private static termios GetTerminal()
  71. {
  72. IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(termios)));
  73. try
  74. {
  75. if (tcgetattr(STDIN_FILENO, ptr) >= 0)
  76. {
  77. return Marshal.PtrToStructure<termios>(ptr);
  78. }
  79.  
  80. return default(termios);
  81. }
  82. finally
  83. {
  84. Marshal.FreeHGlobal(ptr);
  85. }
  86. }
  87.  
  88. private static bool SetTerminal(termios termios)
  89. {
  90. IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(termios)));
  91. try
  92. {
  93. Marshal.StructureToPtr<termios>(termios, ptr, fDeleteOld: false);
  94. if (tcsetattr(STDIN_FILENO, TCSANOW, ptr) <= 0)
  95. {
  96. return true;
  97. }
  98.  
  99. return false;
  100. }
  101. finally
  102. {
  103. Marshal.FreeHGlobal(ptr);
  104. }
  105. }
  106.  
  107. [StructLayout(LayoutKind.Sequential)]
  108. private struct termios
  109. {
  110. // Input Mode Flags
  111. internal uint c_iflag;
  112.  
  113. // Output Mode Flags
  114. internal uint c_oflag;
  115.  
  116. // Control Mode Flags
  117. internal uint c_cflag;
  118.  
  119. // Local Mode Flags
  120. internal uint c_lflag;
  121.  
  122. internal byte c_line;
  123.  
  124. /// Control Characters
  125. [MarshalAs(UnmanagedType.ByValArray, SizeConst=NCCS)]
  126. internal byte[] c_cc;
  127. }
  128.  
  129. [StructLayout(LayoutKind.Sequential)]
  130. private struct pollfd
  131. {
  132. internal uint fd;
  133.  
  134. internal ushort events;
  135.  
  136. internal ushort revents;
  137. }
  138. }
  139. }
Add Comment
Please, Sign In to add comment