From 44cd78d647c0d6162ceda1bd2724983047d46b9c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 13 May 2015 10:14:34 +0200 Subject: [PATCH] Improve getpass() usage As can be seen from: http://unixhelp.ed.ac.uk/CGI/man-cgi?getpass+3 getpass() is a deprecated function and it's advised not to use it. What's more all signals are disabled so (SIGINT, SIGQUIT, SIGSTOP, SIGTSTOP) will do nothing and as such if the user wants to quit the program while typing the password in the password loop he is out of luck. With this commit we get a manual version of getpass(), inspired by this SO answer: http://stackoverflow.com/a/1196696/110395 --- libdevcore/CommonIO.cpp | 28 +++++++++++++++++++++++++++- libdevcore/Exceptions.h | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 80ad7ecf9..10c53ddb9 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -24,6 +24,9 @@ #include #include #include "Exceptions.h" +#ifndef _WIN32 +#include +#endif using namespace std; using namespace dev; @@ -126,6 +129,29 @@ std::string dev::getPassword(std::string const& _prompt) std::getline(cin, ret); return ret; #else - return getpass(_prompt.c_str()); + struct termios oflags; + struct termios nflags; + char password[128]; + + // disable echo in the terminal + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("tcsetattr")); + + printf("%s", _prompt.c_str()); + if (!fgets(password, sizeof(password), stdin)) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("fgets")); + password[strlen(password) - 1] = 0; + + // restore terminal + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("tcsetattr")); + } + + return password; #endif } diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index 36c624a71..025568efa 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -54,6 +54,7 @@ struct FileError: virtual Exception {}; struct Overflow: virtual Exception {}; struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} }; struct FailedInvariant: virtual Exception {}; +struct ExternalFunctionFailure: virtual Exception { public: ExternalFunctionFailure(std::string _f): Exception("Function " + _f + "() failed.") {} }; // error information to be added to exceptions using errinfo_invalidSymbol = boost::error_info;