stdin.cpp raw

   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); }
  82