From 3e17bfe4f2e5e64f9528c26b38d4241ca46f1082 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 19 Oct 2009 01:30:37 +0200 Subject: Client: Added support for paged output --- src/Client/CMakeLists.txt | 2 +- src/Client/ConsoleUtil.cpp | 88 ++++++++++++++++++++++ src/Client/ConsoleUtil.h | 42 +++++++++++ src/Client/PasswordReader.cpp | 65 ---------------- src/Client/PasswordReader.h | 41 ---------- src/Client/UserCommands.cpp | 6 +- src/Client/UserListCommands.cpp | 75 +++++++++--------- src/Client/UserListCommands.h | 4 +- src/madc.cpp | 6 +- .../SystemBackendPosix/SystemBackendPosix.cpp | 6 +- 10 files changed, 181 insertions(+), 154 deletions(-) create mode 100644 src/Client/ConsoleUtil.cpp create mode 100644 src/Client/ConsoleUtil.h delete mode 100644 src/Client/PasswordReader.cpp delete mode 100644 src/Client/PasswordReader.h diff --git a/src/Client/CMakeLists.txt b/src/Client/CMakeLists.txt index dda77f3..b1f6d1f 100644 --- a/src/Client/CMakeLists.txt +++ b/src/Client/CMakeLists.txt @@ -18,8 +18,8 @@ mad_library(Client Application.cpp Application.h CommandParser.cpp CommandParser.h + ConsoleUtil.cpp ConsoleUtil.h InformationManager.cpp InformationManager.h - PasswordReader.cpp PasswordReader.h SystemCommands.cpp SystemCommands.h UserCommands.cpp UserCommands.h UserListCommands.cpp UserListCommands.h diff --git a/src/Client/ConsoleUtil.cpp b/src/Client/ConsoleUtil.cpp new file mode 100644 index 0000000..1a032d2 --- /dev/null +++ b/src/Client/ConsoleUtil.cpp @@ -0,0 +1,88 @@ +/* + * ConsoleUtil.cpp + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "ConsoleUtil.h" + +#include + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +#else +# include +# include +# include +# include +#endif + +namespace Mad { +namespace Client { + +Core::String ConsoleUtil::readPassword(const Core::String &prompt) { +#ifdef _WIN32 + DWORD mode; + HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(handle, &mode); + SetConsoleMode(handle, mode & ~(ENABLE_ECHO_INPUT)); +#else + struct termios termold, termnew; + + tcgetattr(STDIN_FILENO, &termold); + + termnew = termold; + termnew.c_lflag &= ~ECHO; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &termnew); +#endif + + std::cout << prompt << std::flush; + Core::String password = Core::String::getline(std::cin); + std::cout << std::endl; + +#ifdef _WIN32 + SetConsoleMode(handle, mode); +#else + tcsetattr(STDIN_FILENO, TCSAFLUSH, &termold); +#endif + + return password; +} + +void ConsoleUtil::printPaged(const Core::String &output) { +#ifdef _WIN32 + std::cout << output << std::endl; +#else + // TODO Make pager command configurable + FILE *pipe = popen("pager", "w"); + if(!pipe) + pipe = popen("less", "w"); + if(!pipe) + pipe = popen("more", "w"); + if(!pipe) { + std::cout << output << std::endl; + return; + } + + fputs(output.toLocale().c_str(), pipe); + // TODO Error handling + pclose(pipe); +#endif +} + +} +} diff --git a/src/Client/ConsoleUtil.h b/src/Client/ConsoleUtil.h new file mode 100644 index 0000000..8d011f3 --- /dev/null +++ b/src/Client/ConsoleUtil.h @@ -0,0 +1,42 @@ +/* + * ConsoleUtil.h + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef MAD_CLIENT_CONSOLEUTIL_H_ +#define MAD_CLIENT_CONSOLEUTIL_H_ + +#include "export.h" + +#include + +namespace Mad { +namespace Client { + +class MAD_CLIENT_EXPORT ConsoleUtil { + private: + ConsoleUtil(); + + public: + static Core::String readPassword(const Core::String &prompt); + static void printPaged(const Core::String &output); +}; + +} +} + +#endif /* MAD_CLIENT_CONSOLEUTIL_H_ */ diff --git a/src/Client/PasswordReader.cpp b/src/Client/PasswordReader.cpp deleted file mode 100644 index cb77ad5..0000000 --- a/src/Client/PasswordReader.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * PasswordReader.cpp - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#include "PasswordReader.h" - -#include - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include -#else -# include -# include -#endif - -namespace Mad { -namespace Client { - -Core::String PasswordReader::readPassword(const Core::String &prompt) { -#ifdef _WIN32 - DWORD mode; - HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); - GetConsoleMode(handle, &mode); - SetConsoleMode(handle, mode & ~(ENABLE_ECHO_INPUT)); -#else - struct termios termold, termnew; - - tcgetattr(STDIN_FILENO, &termold); - - termnew = termold; - termnew.c_lflag &= ~ECHO; - tcsetattr(STDIN_FILENO, TCSAFLUSH, &termnew); -#endif - - std::cout << prompt << std::flush; - Core::String password = Core::String::getline(std::cin); - std::cout << std::endl; - -#ifdef _WIN32 - SetConsoleMode(handle, mode); -#else - tcsetattr(STDIN_FILENO, TCSAFLUSH, &termold); -#endif - - return password; -} - -} -} diff --git a/src/Client/PasswordReader.h b/src/Client/PasswordReader.h deleted file mode 100644 index d96c9c1..0000000 --- a/src/Client/PasswordReader.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * PasswordReader.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_CLIENT_PASSWORDREADER_H_ -#define MAD_CLIENT_PASSWORDREADER_H_ - -#include "export.h" - -#include - -namespace Mad { -namespace Client { - -class MAD_CLIENT_EXPORT PasswordReader { - private: - PasswordReader(); - - public: - static Core::String readPassword(const Core::String &prompt); -}; - -} -} - -#endif /* MAD_CLIENT_PASSWORDREADER_H_ */ diff --git a/src/Client/UserCommands.cpp b/src/Client/UserCommands.cpp index fe5343c..2fc33db 100644 --- a/src/Client/UserCommands.cpp +++ b/src/Client/UserCommands.cpp @@ -20,7 +20,7 @@ #include "UserCommands.h" #include "Application.h" #include "CommandParser.h" -#include "PasswordReader.h" +#include "ConsoleUtil.h" #include #include @@ -511,8 +511,8 @@ void UserCommands::setPasswordCommand(CommandParser *commandParser, const std::v return; } - Core::String password = PasswordReader::readPassword("Password: "); - Core::String password2 = PasswordReader::readPassword("Verify password: "); + Core::String password = ConsoleUtil::readPassword("Password: "); + Core::String password2 = ConsoleUtil::readPassword("Verify password: "); if(password != password2) { std::cerr << "Passwords do not match." << std::endl; diff --git a/src/Client/UserListCommands.cpp b/src/Client/UserListCommands.cpp index 1da2d38..7f2a26b 100644 --- a/src/Client/UserListCommands.cpp +++ b/src/Client/UserListCommands.cpp @@ -19,6 +19,7 @@ #include "UserListCommands.h" #include "Application.h" +#include "ConsoleUtil.h" #include "XLSReader.h" #include "XLSSheet.h" #include "Requests/UserLists/UserListListRequest.h" @@ -169,7 +170,7 @@ void UserListCommands::showListCommand(CommandParser *commandParser, const std:: std::cout << "User list '" << args[2]; if(userList->isEmpty()) { - std::cout << " is empty." << std::endl; + std::cout << " is empty." << std::endl << std::endl; } else { std::cout << "' contains " << userList->getLength() << " user"; @@ -179,8 +180,6 @@ void UserListCommands::showListCommand(CommandParser *commandParser, const std:: printUserList(*userList); } - - std::cout << std::endl; } else { std::cerr << args[0] << " " << args[1] << ": Too many arguments." << std::endl; @@ -351,6 +350,7 @@ void UserListCommands::importCommand(CommandParser *commandParser, const std::ve void UserListCommands::printUserList(const Common::UserLists::UserList &list) { + Core::String output; std::map lengths; static const Core::String USER_NAME = "User name"; @@ -381,50 +381,52 @@ void UserListCommands::printUserList(const Common::UserLists::UserList &list) { } } - std::cout << " "; - printPadded(USER_NAME, lengths.find(USER_NAME)->second); - std::cout << " "; - printPadded(GROUP_NAME, lengths.find(GROUP_NAME)->second); + output += " "; + output += makePaddedString(USER_NAME, lengths.find(USER_NAME)->second); + output += " "; + output += makePaddedString(GROUP_NAME, lengths.find(GROUP_NAME)->second); for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { - std::cout << " "; - printPadded(*detail, lengths.find(*detail)->second); + output += " "; + output += makePaddedString(*detail, lengths.find(*detail)->second); } - std::cout << std::endl; + output += "\n"; - std::cout << "-"; - printDelimiter(lengths.find(USER_NAME)->second); - std::cout << "- -"; - printDelimiter(lengths.find(GROUP_NAME)->second); + output += "-"; + output += makeDelimiter(lengths.find(USER_NAME)->second); + output += "- -"; + output += makeDelimiter(lengths.find(GROUP_NAME)->second); for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { - std::cout << "- -"; - printDelimiter(lengths.find(*detail)->second); + output += "- -"; + output += makeDelimiter(lengths.find(*detail)->second); } - std::cout << "-" << std::endl; + output += "-\n"; for(Common::UserLists::UserList::const_iterator user = list.begin(); user != list.end(); ++user) { static const Core::String UNSET(""); - std::cout << " "; + output += " "; if(!user->getName().isEmpty()) - printPadded(user->getName(), lengths.find(USER_NAME)->second); + output += makePaddedString(user->getName(), lengths.find(USER_NAME)->second); else - printPadded(UNSET, lengths.find(USER_NAME)->second); + output += makePaddedString(UNSET, lengths.find(USER_NAME)->second); - std::cout << " "; + output += " "; if(!user->getGroup().isEmpty()) - printPadded(user->getGroup(), lengths.find(GROUP_NAME)->second); + output += makePaddedString(user->getGroup(), lengths.find(GROUP_NAME)->second); else - printPadded(UNSET, lengths.find(GROUP_NAME)->second); + output += makePaddedString(UNSET, lengths.find(GROUP_NAME)->second); for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { - std::cout << " "; - printPadded(user->getDetail(*detail), lengths.find(*detail)->second); + output += " "; + output += makePaddedString(user->getDetail(*detail), lengths.find(*detail)->second); } - std::cout << std::endl; + output += "\n"; } + + ConsoleUtil::printPaged(output); } void UserListCommands::printSheet(const XLSSheet &sheet, unsigned rowCount) { @@ -454,16 +456,16 @@ void UserListCommands::printSheet(const XLSSheet &sheet, unsigned rowCount) { std::cout << " "; if(!sheet.getColumnName(col).isEmpty()) - printPadded(sheet.getColumnName(col), lengths[col]); + std::cout << makePaddedString(sheet.getColumnName(col), lengths[col]); else - printPadded(DELETE, lengths[col]); + std::cout << makePaddedString(DELETE, lengths[col]); } std::cout << std::endl; std::cout << " "; for(unsigned col = 0; col < sheet.getColumnCount(); ++col) { std::cout << " -"; - printDelimiter(lengths[col]); + std::cout << makeDelimiter(lengths[col]); std::cout << "-"; } std::cout << std::endl; @@ -473,7 +475,7 @@ void UserListCommands::printSheet(const XLSSheet &sheet, unsigned rowCount) { for(unsigned col = 0; col < sheet.getColumnCount(); ++col) { std::cout << " "; - printPadded(row[col], lengths[col]); + std::cout << makePaddedString(row[col], lengths[col]); } std::cout << std::endl; @@ -482,21 +484,22 @@ void UserListCommands::printSheet(const XLSSheet &sheet, unsigned rowCount) { if(rowCount > 0 && rows.size() > rowCount) { for(unsigned col = 0; col < sheet.getColumnCount(); ++col) { std::cout << " "; - printPadded("...", lengths[col]); + std::cout << makePaddedString("...", lengths[col]); } std::cout << std::endl; } } -void UserListCommands::printPadded(const Core::String &str, boost::int32_t length) { - std::cout << str; +Core::String UserListCommands::makePaddedString(const Core::String &str, boost::int32_t length) { if(str.length() < length) - std::cout << std::string(length-str.length(), ' '); + return str + Core::String::fromString(std::string(length-str.length(), ' ')); + else + return str; } -void UserListCommands::printDelimiter(boost::int32_t length) { - printPadded(Core::String::fromString(std::string(length, '-')), length); +Core::String UserListCommands::makeDelimiter(boost::int32_t length) { + return Core::String::fromString(std::string(length, '-')); } diff --git a/src/Client/UserListCommands.h b/src/Client/UserListCommands.h index ab20974..79ea621 100644 --- a/src/Client/UserListCommands.h +++ b/src/Client/UserListCommands.h @@ -54,8 +54,8 @@ class MAD_CLIENT_EXPORT UserListCommands { static void printUserList(const Common::UserLists::UserList &list); static void printSheet(const XLSSheet &sheet, unsigned rowCount = 0); - static void printPadded(const Core::String &str, boost::int32_t length); - static void printDelimiter(boost::int32_t length); + static Core::String makePaddedString(const Core::String &str, boost::int32_t length); + static Core::String makeDelimiter(boost::int32_t length); public: static void userListCommand(CommandParser *commandParser, const std::vector &args); diff --git a/src/madc.cpp b/src/madc.cpp index 477dc04..79c446b 100644 --- a/src/madc.cpp +++ b/src/madc.cpp @@ -29,8 +29,8 @@ #include "Client/Application.h" #include "Client/CommandParser.h" +#include "Client/ConsoleUtil.h" #include "Client/InformationManager.h" -#include "Client/PasswordReader.h" #include "Client/Authenticators/ChallengeResponseAuthenticator.h" #include "Client/Authenticators/PasswordAuthenticator.h" @@ -97,7 +97,7 @@ int main(int argc, char *argv[]) { { std::cerr << "Login: " << std::flush; Core::String username = Core::String::getline(std::cin); - Core::String password = Client::PasswordReader::readPassword("Password: "); + Core::String password = Client::ConsoleUtil::readPassword("Password: "); try { Client::Authenticators::ChallengeResponseAuthenticator::authenticate(&application, connection, username, password); @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) { application.getUserManager()->unregisterBackend(networkUserBackend); } catch(Core::Exception &e) { - application.log(Core::Logger::LOG_CRITICAL, Core::Format("Error: %s") % e); + application.log(Core::Logger::LOG_CRITICAL, Core::Format("Error: %1%") % e); } application.getRequestManager()->unregisterConnection(connection); diff --git a/src/modules/SystemBackendPosix/SystemBackendPosix.cpp b/src/modules/SystemBackendPosix/SystemBackendPosix.cpp index 6df087d..b9313e9 100644 --- a/src/modules/SystemBackendPosix/SystemBackendPosix.cpp +++ b/src/modules/SystemBackendPosix/SystemBackendPosix.cpp @@ -31,7 +31,7 @@ namespace SystemBackendPosix { void SystemBackendPosix::getFSInfo(std::vector *fsInfo) throw(Core::Exception) { application->getThreadManager()->detach(); - FILE *pipe = popen("/bin/df -P -k", "r"); + FILE *pipe = popen("df -P -k", "r"); if(!pipe) throw(Core::Exception(Core::Exception::NOT_AVAILABLE)); @@ -80,14 +80,14 @@ void SystemBackendPosix::getFSInfo(std::vector *f void SystemBackendPosix::shutdown() throw(Core::Exception) { application->getThreadManager()->detach(); - if(system("/sbin/halt") != 0) + if(system("halt") != 0) throw(Core::Exception(Core::Exception::NOT_AVAILABLE)); } void SystemBackendPosix::reboot() throw(Core::Exception) { application->getThreadManager()->detach(); - if(system("/sbin/reboot") != 0) + if(system("reboot") != 0) throw(Core::Exception(Core::Exception::NOT_AVAILABLE)); } -- cgit v1.2.3