/* * CommandParser.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 "CommandParser.h" #include "Application.h" #include "InformationManager.h" #include "SystemCommands.h" #include "UserCommands.h" #include #include #include #include #include #include namespace Mad { namespace Client { const CommandParser::Command CommandParser::commands[] = { {{"fsinfo", 0}, "fsinfo [host]", "Display file system usage information", "Display file system usage information of a host or the server (if no host is given).", &SystemCommands::fsinfoCommand}, {{"help", "?", 0}, "help [command]", "Display usage information about commands", "Display usage information about a command. If no command is given, display a list of all available commands.", &CommandParser::helpCommand}, {{"list_hosts", "hosts", 0}, "list_hosts [-a]", "List the currently active hosts", "List the currently active hosts.\n\n -a\tAlso list inactive hosts", &CommandParser::listHostsCommand}, {{"reboot", 0}, "reboot *|host...", "Reboot host", "Reboot hosts. * will reboot all hosts.", &SystemCommands::rebootCommand}, {{"shutdown", "halt", 0}, "shutdown *|host...", "Shut hosts down", "Shut hosts down. * will shut down all hosts.", &SystemCommands::shutdownCommand}, {{"status", "st", 0}, "status [host]", "Display status information", "Display host status information. If no host is given, display server status information.", &SystemCommands::statusCommand}, {{"list_users", "users", 0}, "list_users", "Show the user account database", "Show the user account database.", &UserCommands::listUsersCommand}, {{"user_info", "user", 0}, "user_info uid|name", "Search for a user id", "Search for a user.", &UserCommands::userInfoCommand}, {{"list_groups", "groups", 0}, "list_groups", "Show the user group database", "Show the user group database.", &UserCommands::listGroupsCommand}, {{"group_info", "group", 0}, "group_info gid|name", "Search for a group id", "Search for a group.", &UserCommands::groupInfoCommand}, {{"add_user", 0}, "add_user uid gid username full_name", "Add a new user", "Add a new user with the given information to the account database.", &UserCommands::addUserCommand}, {{"update_user", 0}, "update_user uid new_uid gid username full_name", "Update a user", "Update user data in the account database.", &UserCommands::updateUserCommand}, {{"delete_user", 0}, "delete_user uid", "Delete user", "Delete a user from the account database.", &UserCommands::deleteUserCommand}, {{"add_group", 0}, "add_group gid name", "Add a new group", "Add a new user group with the given name to the account database.", &UserCommands::addGroupCommand}, {{"update_group", 0}, "update_group gid new_gid name", "Update a group", "Update group data in the account database.", &UserCommands::updateGroupCommand}, {{"delete_group", 0}, "delete_group did", "Delete group", "Delete a user group from the account database.", &UserCommands::deleteGroupCommand}, {{"add_user_to_group", 0}, "add_user_to_group uid gid", "Add a user to a group", "Add a user to a group.", &UserCommands::addUserToGroupCommand}, {{"delete_user_from_group", 0}, "delete_user_from_group uid gid", "Remove a user from a group", "Remove a user from a group.", &UserCommands::deleteUserFromGroupCommand}, {{"exit", "quit", 0}, "exit", "Close the connection and quit the client", "Close the connection and quit the client.", &CommandParser::exitCommand}, {{0}, 0, 0, 0, 0} }; const CommandParser::Command* CommandParser::findCommand(const std::string& command) { for(int i = 0; commands[i].commands[0] != 0; ++i) { for(int j = 0; commands[i].commands[j] != 0; ++j) { if(command == commands[i].commands[j]) { return &commands[i]; } } } return 0; } void CommandParser::printUsage(const std::string& command) { const CommandParser::Command *cmd = findCommand(command); if(cmd) std::cerr << "Usage: " << cmd->cmdline << std::endl; } std::map CommandParser::parseHostList(const std::vector &args, bool mustBeActive) { const std::map& hosts = application->getInformationManager()->getDaemons(); std::map ret; for(std::vector::const_iterator arg = args.begin(); arg != args.end(); ++arg) { if(*arg == "*") { if(mustBeActive) { for(std::map::const_iterator host = hosts.begin(); host != hosts.end(); ++host) { if(host->second.getState() != Common::HostInfo::INACTIVE) ret.insert(*host); } if(ret.empty()) std::cerr << "No hosts active." << std::endl; } else { ret = hosts; } } else { std::map::const_iterator host = hosts.find(*arg); if(host == hosts.end()) std::cerr << "Host '" << *arg << "' doesn't exist." << std::endl; else if(mustBeActive && host->second.getState() == Common::HostInfo::INACTIVE) std::cerr << "Host '" << *arg << "' is inactive." << std::endl; else ret.insert(*host); } } return ret; } void CommandParser::helpCommand(const std::vector &args) { if(args.size() == 1) { std::cout << "Available commands:" << std::endl << std::endl; for(int i = 0; commands[i].commands[0] != 0; ++i) { std::cout << commands[i].commands[0]; for(int j = 1; commands[i].commands[j] != 0; ++j) std::cout << ", " << commands[i].commands[j]; std::cout << std::endl << "\t" << commands[i].desc << std::endl; } } else if(args.size() == 2) { const Command* command = findCommand(args[1]); if(command) { std::cout << "Usage: " << command->cmdline << std::endl << std::endl; std::cout << command->longdesc << std::endl << std::endl; } else std::cerr << args[0] << ": Command '" << args[1] << "' doesn't exist." << std::endl; } else { std::cerr << args[0] << ": Too many arguments." << std::endl; printUsage("help"); } } void CommandParser::listHostsCommand(const std::vector &args) { const std::map& hosts = application->getInformationManager()->getDaemons(); if(args.size() == 1) { if(hosts.empty()) { std::cout << "The host list is empty." << std::endl << std::endl; return; } bool output = false; for(std::map::const_iterator host = hosts.begin(); host != hosts.end(); ++host) { if(host->second.getState() == Common::HostInfo::INACTIVE) continue; if(!output) { std::cout << "Active hosts:" << std::endl; output = true; } std::cout << " " << host->first << std::endl; } if(!output) std::cout << "No active hosts." << std::endl; std::cout << std::endl; } else if(args.size() > 2) { std::cerr << args[0] << ": Too many arguments." << std::endl; printUsage("list_hosts"); } else if(args[1] == "-a") { if(hosts.empty()) { std::cout << "The host list is empty." << std::endl << std::endl; return; } std::cout << "Host list:" << std::endl; for(std::map::const_iterator host = hosts.begin(); host != hosts.end(); ++host) { std::cout << " " << host->first << " (" << (host->second.getState() == Common::HostInfo::RUNNING ? "running" : "inactive") << ")" << std::endl; } std::cout << std::endl; } else { std::cerr << args[0] << ": Don't understand argument '" << args[1] << "'." << std::endl; printUsage("list_hosts"); } } void CommandParser::exitCommand(const std::vector &/*args*/) { boost::shared_ptr request(new Common::Requests::DisconnectRequest(application)); application->getRequestManager()->sendRequest(connection, request); request->wait(); std::pair, Core::Exception> result = request->getResult(); if(result.second) std::cerr << "An error occurred during your request: " << result.second.strerror() << "." << std::endl; else disconnect = true; } bool CommandParser::parse(const std::string &cmd) { std::vector splitCmd; Core::Tokenizer::tokenize(cmd, splitCmd); if(splitCmd.empty()) return true; const Command* command = findCommand(splitCmd[0]); if(command) command->function(this, splitCmd); else std::cerr << "Unknown command '" << splitCmd[0] << "'." << std::endl; return true; } CommandParser::CommandParser(Application *application0, Common::Connection *connection0) : application(application0), connection(connection0), disconnect(false) {} } }