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