aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/os_utils.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-12-02 16:31:16 -0500
committerJack Lloyd <[email protected]>2018-12-02 16:31:16 -0500
commit163e59f4af51f802c5e77fc0bb8c0901a7fa62ea (patch)
treed6d274f449efea663d236bd293f4e1bebf7fc7c4 /src/lib/utils/os_utils.cpp
parent7bc0745c3ff2824f9a3607db19e7e1a3e563c5bc (diff)
parentc3cbf959aa628ae541e4009894b040ab242dd45e (diff)
Merge GH #1756 Support getting passphrase from the console
Diffstat (limited to 'src/lib/utils/os_utils.cpp')
-rw-r--r--src/lib/utils/os_utils.cpp101
1 files changed, 100 insertions, 1 deletions
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index ab9c73b0c..6bebbab58 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -1,6 +1,6 @@
/*
* OS and machine specific utility functions
-* (C) 2015,2016,2017 Jack Lloyd
+* (C) 2015,2016,2017,2018 Jack Lloyd
* (C) 2016 Daniel Neus
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -26,6 +26,8 @@
#include <setjmp.h>
#include <unistd.h>
#include <errno.h>
+ #include <termios.h>
+ #undef B0
#endif
#if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
@@ -470,4 +472,101 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn)
return probe_result;
}
+std::unique_ptr<OS::Echo_Suppression> OS::suppress_echo_on_terminal()
+ {
+#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
+ class POSIX_Echo_Suppression : public Echo_Suppression
+ {
+ public:
+ POSIX_Echo_Suppression()
+ {
+ m_stdin_fd = fileno(stdin);
+ if(::tcgetattr(m_stdin_fd, &m_old_termios) != 0)
+ throw System_Error("Getting terminal status failed", errno);
+
+ struct termios noecho_flags = m_old_termios;
+ noecho_flags.c_lflag &= ~ECHO;
+ noecho_flags.c_lflag |= ECHONL;
+
+ if(::tcsetattr(m_stdin_fd, TCSANOW, &noecho_flags) != 0)
+ throw System_Error("Clearing terminal echo bit failed", errno);
+ }
+
+ void reenable_echo() override
+ {
+ if(m_stdin_fd > 0)
+ {
+ if(::tcsetattr(m_stdin_fd, TCSANOW, &m_old_termios) != 0)
+ throw System_Error("Restoring terminal echo bit failed", errno);
+ m_stdin_fd = -1;
+ }
+ }
+
+ ~POSIX_Echo_Suppression()
+ {
+ try
+ {
+ reenable_echo();
+ }
+ catch(...)
+ {
+ }
+ }
+
+ private:
+ int m_stdin_fd;
+ struct termios m_old_termios;
+ };
+
+ return std::unique_ptr<Echo_Suppression>(new POSIX_Echo_Suppression);
+
+#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
+
+ class Win32_Echo_Suppression : public Echo_Suppression
+ {
+ public:
+ Win32_Echo_Suppression()
+ {
+ m_input_handle = ::GetStdHandle(STD_INPUT_HANDLE);
+ if(::GetConsoleMode(m_input_handle, &m_console_state) == 0)
+ throw System_Error("Getting console mode failed", ::GetLastError());
+
+ DWORD new_mode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
+ if(::SetConsoleMode(m_input_handle, new_mode) == 0)
+ throw System_Error("Setting console mode failed", ::GetLastError());
+ }
+
+ void reenable_echo() override
+ {
+ if(m_input_handle != INVALID_HANDLE_VALUE)
+ {
+ if(::SetConsoleMode(m_input_handle, m_console_state) == 0)
+ throw System_Error("Setting console mode failed", ::GetLastError());
+ m_input_handle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ ~Win32_Echo_Suppression()
+ {
+ try
+ {
+ reenable_echo();
+ }
+ catch(...)
+ {
+ }
+ }
+
+ private:
+ HANDLE m_input_handle;
+ DWORD m_console_state;
+ };
+
+ return std::unique_ptr<Echo_Suppression>(new Win32_Echo_Suppression);
+#endif
+
+ // Not supported on this platform, return null
+ return std::unique_ptr<Echo_Suppression>();
+ }
+
}