X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/d625e80d62fc8b98c18a95c65e6fa329b7fcc85b..20d884ddac6b8cacedb2701e282efe3ff9785cbf:/projects/sgconf/main.cpp?ds=sidebyside diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp index a1c8df8f..babfd86f 100644 --- a/projects/sgconf/main.cpp +++ b/projects/sgconf/main.cpp @@ -23,6 +23,8 @@ #include "common_sg.h" #include "sg_error_codes.h" +#include "xml.h" +#include "admins.h" #include "options.h" #include "actions.h" #include "config.h" @@ -134,6 +136,16 @@ array[pos] = value; return true; } +void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/) +{ +if (!result) + { + std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl; + return; + } +SGCONF::PrintXML(response); +} + void Usage(); void UsageAll(); void UsageImpl(bool full); @@ -146,6 +158,28 @@ void UsageCorporations(bool full); void Version(); +void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block) +{ +std::vector paths; +const char * configHome = getenv("XDG_CONFIG_HOME"); +if (configHome == NULL) + { + const char * home = getenv("HOME"); + if (home == NULL) + return; + paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf"); + paths.push_back(std::string(home) + "/.sgconf/sgconf.conf"); + } +else + paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf"); +for (std::vector::const_iterator it = paths.begin(); it != paths.end(); ++it) + if (access(it->c_str(), R_OK) == 0) + { + block.ParseFile(*it); + return; + } +} + } // namespace anonymous namespace SGCONF @@ -154,7 +188,7 @@ namespace SGCONF class CONFIG_ACTION : public ACTION { public: - CONFIG_ACTION(CONFIG & config, + CONFIG_ACTION(SGCONF::CONFIG & config, const std::string & paramDescription) : m_config(config), m_description(paramDescription) @@ -168,7 +202,7 @@ class CONFIG_ACTION : public ACTION virtual PARSER_STATE Parse(int argc, char ** argv); private: - CONFIG & m_config; + SGCONF::CONFIG & m_config; std::string m_description; OPTION_BLOCK m_suboptions; @@ -176,8 +210,114 @@ class CONFIG_ACTION : public ACTION void ParseHostAndPort(const std::string & hostAndPort); }; +typedef bool (* API_FUNCTION) (const SGCONF::CONFIG &, + const std::string &, + const std::map &); + +class COMMAND +{ + public: + COMMAND(API_FUNCTION funPtr, + const std::string & arg, + const std::map & options) + : m_funPtr(funPtr), + m_arg(arg), + m_options(options) + {} + bool Execute(const SGCONF::CONFIG & config) const + { + return m_funPtr(config, m_arg, m_options); + } + + private: + API_FUNCTION m_funPtr; + std::string m_arg; + std::map m_options; +}; + +class COMMANDS +{ + public: + void Add(API_FUNCTION funPtr, + const std::string & arg, + const std::map & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); } + bool Execute(const SGCONF::CONFIG & config) const + { + std::list::const_iterator it(m_commands.begin()); + bool res = true; + while (it != m_commands.end() && res) + { + res = res && it->Execute(config); + ++it; + } + return res; + } + private: + std::list m_commands; +}; + +class API_ACTION : public ACTION +{ + public: + API_ACTION(COMMANDS & commands, + const std::string & paramDescription, + bool needArgument, + const OPTION_BLOCK& suboptions, + API_FUNCTION funPtr) + : m_commands(commands), + m_description(paramDescription), + m_argument(needArgument ? "1" : ""), // Hack + m_suboptions(suboptions), + m_funPtr(funPtr) + {} + API_ACTION(COMMANDS & commands, + const std::string & paramDescription, + bool needArgument, + API_FUNCTION funPtr) + : m_commands(commands), + m_description(paramDescription), + m_argument(needArgument ? "1" : ""), // Hack + m_funPtr(funPtr) + {} + + virtual ACTION * Clone() const { return new API_ACTION(*this); } + + virtual std::string ParamDescription() const { return m_description; } + virtual std::string DefaultDescription() const { return ""; } + virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } + virtual PARSER_STATE Parse(int argc, char ** argv) + { + PARSER_STATE state(false, argc, argv); + if (!m_argument.empty()) + { + if (argc == 0 || + argv == NULL || + *argv == NULL) + throw ERROR("Missing argument."); + m_argument = *argv; + --state.argc; + ++state.argv; + } + m_suboptions.Parse(state.argc, state.argv); + m_commands.Add(m_funPtr, m_argument, m_params); + return state; + } + + private: + COMMANDS & m_commands; + std::string m_description; + std::string m_argument; + OPTION_BLOCK m_suboptions; + std::map m_params; + API_FUNCTION m_funPtr; +}; + PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv) { +if (argc == 0 || + argv == NULL || + *argv == NULL) + throw ERROR("Missing argument."); char * pos = strchr(*argv, '@'); if (pos != NULL) { @@ -223,12 +363,39 @@ else } inline -CONFIG_ACTION * MakeParamAction(CONFIG & config, +CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config, const std::string & paramDescription) { return new CONFIG_ACTION(config, paramDescription); } +inline +ACTION * MakeAPIAction(COMMANDS & commands, + const std::string & paramDescription, + bool needArgument, + API_FUNCTION funPtr) +{ +return new API_ACTION(commands, paramDescription, needArgument, funPtr); +} + +inline +ACTION * MakeAPIAction(COMMANDS & commands, + API_FUNCTION funPtr) +{ +return new API_ACTION(commands, "", false, funPtr); +} + +bool RawXMLFunction(const SGCONF::CONFIG & config, + const std::string & arg, + const std::map & /*options*/) +{ + STG::SERVCONF proto(config.server.data(), + config.port.data(), + config.userName.data(), + config.userPass.data()); + return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok; +} + } // namespace SGCONF time_t stgTime; @@ -1200,6 +1367,7 @@ return ProcessSetUser(req.server.data(), req.port.data(), req.admLogin.data(), r int main(int argc, char **argv) { SGCONF::CONFIG config; +SGCONF::COMMANDS commands; SGCONF::OPTION_BLOCKS blocks; blocks.Add("General options") @@ -1207,14 +1375,33 @@ blocks.Add("General options") .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit") .Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit") .Add("v", "version", SGCONF::MakeFunc0Action(Version), "\t\tshow version information and exit"); -blocks.Add("Connection options") +SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options") .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "
"), "\t\thost to connect") .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), ""), "\t\tport to connect") .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), ""), "\tadministrative login") .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, ""), "\tpassword for the administrative login") .Add("a", "address", SGCONF::MakeParamAction(config, ""), "connection params as a single string in format: :@:"); +blocks.Add("Raw XML") + .Add("r", "raw", SGCONF::MakeAPIAction(commands, "", true, SGCONF::RawXMLFunction), "\tmake raw XML request"); +blocks.Add("Admins management options") + .Add("get-admins", SGCONF::MakeAPIAction(commands, SGCONF::GetAdminsFunction), "\tget admin list") + .Add("get-admin", SGCONF::MakeAPIAction(commands, "", true, SGCONF::GetAdminFunction), "\tget admin") + .Add("add-admin", SGCONF::MakeAPIAction(commands, "", true, SGCONF::AddAdminFunction), "\tadd admin") + .Add("del-admin", SGCONF::MakeAPIAction(commands, "", true, SGCONF::DelAdminFunction), "\tdel admin") + .Add("chg-admin", SGCONF::MakeAPIAction(commands, "", true, SGCONF::ChgAdminFunction), "\tchange admin"); + -SGCONF::PARSER_STATE state(blocks.Parse(--argc, ++argv)); // Skipping self name +SGCONF::PARSER_STATE state(false, argc, argv); + +try +{ +state = blocks.Parse(--argc, ++argv); // Skipping self name +} +catch (const SGCONF::OPTION::ERROR& ex) +{ +std::cerr << ex.what() << "\n"; +return -1; +} if (state.stop) return 0; @@ -1225,7 +1412,34 @@ if (state.argc > 0) return -1; } -return 0; +try +{ +SGCONF::CONFIG configOverride(config); + +if (config.configFile.empty()) + { + const char * mainConfigFile = "/etc/sgconf/sgconf.conf"; + if (access(mainConfigFile, R_OK) == 0) + block.ParseFile(mainConfigFile); + ReadUserConfigFile(block); + } +else + { + block.ParseFile(config.configFile.data()); + } + +config = configOverride; +} +catch (const std::exception& ex) +{ +std::cerr << ex.what() << "\n"; +return -1; +} + +std::cerr << "Config: " << config.Serialize() << std::endl; +return commands.Execute(config) ? 0 : -1; + +/*return 0; if (argc < 2) { @@ -1256,7 +1470,7 @@ else UsageConf(); exit(PARAMETER_PARSING_ERR_CODE); } -return UNKNOWN_ERR_CODE; +return UNKNOWN_ERR_CODE;*/ } //-----------------------------------------------------------------------------