diff --git a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/utility/utility.h b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/utility/utility.h index 29913011f39..40ad15f3a9b 100644 --- a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/utility/utility.h +++ b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/utility/utility.h @@ -217,6 +217,18 @@ std::string Basename(std::string_view path); */ [[nodiscard]] std::optional GetEnv(const std::string& envname); +/** + * Enables or disables echo for stdin. + * @param enable true to enable, false to disable + */ +void SetStdinEcho(bool enable); + +/** + * Reads a password from stdin up to pressing 'Enter', without echoing the characters typed. + * @return the password read + */ +std::string ReadPasswordFromStdinNoEcho(); + template [[nodiscard]] std::string TypeName(const T& t) { return demangle(typeid(t).name()); diff --git a/cpp-client/deephaven/dhcore/src/utility/utility.cc b/cpp-client/deephaven/dhcore/src/utility/utility.cc index 0c4c648c172..ba0ca75e00c 100644 --- a/cpp-client/deephaven/dhcore/src/utility/utility.cc +++ b/cpp-client/deephaven/dhcore/src/utility/utility.cc @@ -23,6 +23,7 @@ static_assert(FMT_VERSION >= 100000); namespace deephaven::dhcore::utility { namespace { + const char kEncodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const char kPadCharacter = '='; } // namespace @@ -167,4 +168,13 @@ std::string demangle(const char* name) { std::string ObjectId(const std::string &class_short_name, void *this_ptr) { return fmt::format("{}({})", class_short_name, this_ptr); } + +std::string ReadPasswordFromStdinNoEcho() { + SetStdinEcho(false); + std::string password; + std::cin >> password; + SetStdinEcho(true); + return password; +} + } // namespace deephaven::dhcore::utility diff --git a/cpp-client/deephaven/dhcore/src/utility/utility_platform_specific.cc b/cpp-client/deephaven/dhcore/src/utility/utility_platform_specific.cc index 5a834efe04d..6ccf9407dbe 100644 --- a/cpp-client/deephaven/dhcore/src/utility/utility_platform_specific.cc +++ b/cpp-client/deephaven/dhcore/src/utility/utility_platform_specific.cc @@ -8,6 +8,7 @@ #if defined(__unix__) #include +#include #include #include #include @@ -17,6 +18,7 @@ #endif namespace deephaven::dhcore::utility { + std::string GetTidAsString() { #if defined(__linux__) const pid_t tid = syscall(__NR_gettid); // this is more portable than gettid(). @@ -89,4 +91,32 @@ std::optional GetEnv(const std::string& envname) { #error "Unsupported configuration" #endif } + +// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin +void SetStdinEcho(const bool enable) { +#if defined(__unix__) + struct termios tty; + tcgetattr(STDIN_FILENO, &tty); + if( !enable ) + tty.c_lflag &= ~ECHO; + else + tty.c_lflag |= ECHO; + + (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty); +#elif defined(_WIN32) + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode; + GetConsoleMode(hStdin, &mode); + + if( !enable ) + mode &= ~ENABLE_ECHO_INPUT; + else + mode |= ENABLE_ECHO_INPUT; + + SetConsoleMode(hStdin, mode ); +#else +#error "Unsupported configuration" +#endif +} + } // namespace deephaven::dhcore::utility