/ src / compat / stdin.cpp
stdin.cpp
 1  // Copyright (c) 2018-present The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #include <compat/stdin.h>
 6  
 7  #include <cstdio>
 8  
 9  #ifdef WIN32
10  #include <windows.h>
11  #include <io.h>
12  #else
13  #include <termios.h>
14  #include <unistd.h>
15  #include <poll.h>
16  #endif
17  
18  // https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin
19  void SetStdinEcho(bool enable)
20  {
21      if (!StdinTerminal()) {
22          return;
23      }
24  #ifdef WIN32
25      HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
26      DWORD mode;
27      if (!GetConsoleMode(hStdin, &mode)) {
28          fputs("GetConsoleMode failed\n", stderr);
29          return;
30      }
31      if (!enable) {
32          mode &= ~ENABLE_ECHO_INPUT;
33      } else {
34          mode |= ENABLE_ECHO_INPUT;
35      }
36      if (!SetConsoleMode(hStdin, mode)) {
37          fputs("SetConsoleMode failed\n", stderr);
38      }
39  #else
40      struct termios tty;
41      if (tcgetattr(STDIN_FILENO, &tty) != 0) {
42          fputs("tcgetattr failed\n", stderr);
43          return;
44      }
45      if (!enable) {
46          tty.c_lflag &= static_cast<decltype(tty.c_lflag)>(~ECHO);
47      } else {
48          tty.c_lflag |= ECHO;
49      }
50      if (tcsetattr(STDIN_FILENO, TCSANOW, &tty) != 0) {
51          fputs("tcsetattr failed\n", stderr);
52      }
53  #endif
54  }
55  
56  bool StdinTerminal()
57  {
58  #ifdef WIN32
59      return _isatty(_fileno(stdin));
60  #else
61      return isatty(fileno(stdin));
62  #endif
63  }
64  
65  bool StdinReady()
66  {
67      if (!StdinTerminal()) {
68          return true;
69      }
70  #ifdef WIN32
71      return false;
72  #else
73      struct pollfd fds;
74      fds.fd = STDIN_FILENO;
75      fds.events = POLLIN;
76      return poll(&fds, 1, 0) == 1;
77  #endif
78  }
79  
80  NoechoInst::NoechoInst() { SetStdinEcho(false); }
81  NoechoInst::~NoechoInst() { SetStdinEcho(true); }