Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-node
  • evseev/cellframe-node
  • dmitry.puzyrkov/cellframe-node
  • MIKA83/cellframe-node
4 results
Show changes
Showing
with 1781 additions and 0 deletions
#pragma once
#include <algorithm>
#include <string>
#include <iostream>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include <regex>
#include <unordered_map>
#include <memory>
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <iterator>
#include <numeric>
#include <map>
#include "../build_config.h"
enum E_FLAGS {
F_VERBOSE = 1 << 0,
F_FORCE = 1 << 1,
F_DRYRUN = 1 << 2
};
template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
auto size = static_cast<size_t>( size_s );
std::unique_ptr<char[]> buf( new char[ size ] );
std::snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
// trim from start (in place)
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
inline void trim(std::string &s) {
rtrim(s);
ltrim(s);
}
std::string string_join(const std::vector<std::string>& vec, const char* delim);
std::vector<std::string> tokenize(const std::string &str, const std::regex re);
struct CAbstractScriptCommand {
CAbstractScriptCommand(std::vector<std::string> tokens);
virtual ~CAbstractScriptCommand() = default;
using create_f = std::unique_ptr<CAbstractScriptCommand>(std::vector <std::string> cmd_tokens);
static void registrate(std::string const & name, create_f * fp)
{
registry()[name] = fp;
}
static bool exists(std::string const & name)
{
auto it = registry().find(name);
return it != registry().end();
}
static std::unique_ptr<CAbstractScriptCommand> instantiate(std::string const & name, std::vector <std::string> cmd_tokens)
{
auto it = registry().find(name);
return it == registry().end() ? nullptr : (it->second)(cmd_tokens);
}
template <typename D>
struct Registrar
{
explicit Registrar(std::string const & name)
{
CAbstractScriptCommand::registrate(name, &D::create);
}
// make non-copyable, etc.
};
private:
static std::unordered_map<std::string, create_f *> & registry();
CAbstractScriptCommand();
std::vector<std::string> cmd_tokens;
public:
virtual bool execute(bool non_interactive, int flags) = 0;
static std::unique_ptr<CAbstractScriptCommand> build(const std::string &line);
virtual bool is_condition_open();
virtual bool is_condition_close();
virtual std::string represent();
};
extern std::map<std::string, std::string> variable_storage;
\ No newline at end of file
#include "ConditionCommand.h"
#include <sstream>
#include <iostream>
#include <iterator>
#include <numeric>
#include "../config/CellframeConfigFile.h"
CAbstractScriptCommand::Registrar<CConditionOpenCommand> if_registrar("if");
CAbstractScriptCommand::Registrar<CConditionCloseCommand> endif_registrar("endif");
bool CConditionOpenCommand::is_condition_open() {return true;}
bool CConditionCloseCommand::is_condition_close() {return true;}
CConditionOpenCommand::CConditionOpenCommand(std::vector <std::string> cmd_tokens):CAbstractScriptCommand(cmd_tokens)
{
std::string joined_condition = string_join(std::vector<std::string>(cmd_tokens.begin()+1,cmd_tokens.end()), "");
auto eq_token = joined_condition.find("==");
auto neq_token = joined_condition.find("!=");
if (eq_token != std::string::npos)
this->cond_op = COND_EQUAL;
if (neq_token != std::string::npos)
this->cond_op = COND_NOT_EQUAL;
if (eq_token == std::string::npos && neq_token == std::string::npos)
this->cond_op = COND_IS_SET;
std::vector < std::string> tokens = tokenize(joined_condition, std::regex("==|!="));
if (this->cond_op == COND_IS_SET && tokens.size() != 1)
throw std::invalid_argument("IS_SET condition requre only one variable for check");
if (this->cond_op != COND_IS_SET && tokens.size() != 2)
throw std::invalid_argument("CONDITION EQ | NEQ requre only two tokens");
this->arg1 = tokens[0];
if (this->cond_op != COND_IS_SET)
this->arg2 = tokens[1];
//auto neq_token = std::find(joined_condition.begin(), joined_condition.end(), "!=");
}
CConditionCloseCommand::CConditionCloseCommand(std::vector <std::string> cmd_tokens):CAbstractScriptCommand(cmd_tokens)
{
}
bool CConditionOpenCommand::execute(bool non_intercative, int flags)
{
std::string a1val = this->arg1;
std::string a2val = this->arg2;
if (flags & F_VERBOSE) std::cout << "[VE] Condition exec: " << a1val << " " << this->cond_op << " "<<a2val << " -> ";
a1val = substitute_variables(arg1);
a2val = substitute_variables(arg2);
bool res = false;
std::string opsym = "";
switch (this->cond_op)
{
case COND_EQUAL:
{
opsym = "==";
res = a1val == a2val;
break;
}
case COND_NOT_EQUAL:
{
opsym = "!=";
res = a1val != a2val;
break;
}
case COND_IS_SET:
{
opsym = "exists";
res = a1val.empty();
break;
}
default:
throw std::invalid_argument("Unknown condition type");
}
if (flags & F_VERBOSE) std::cout << a1val << " " << opsym << " " <<a2val << " -> " << res << std::endl;
return res;
}
bool CConditionCloseCommand::execute(bool non_intercative, int flags)
{
return true;
}
#pragma once
#include "AbstractCommand.h"
enum E_COND_OPS {
COND_EQUAL,
COND_NOT_EQUAL,
COND_IS_SET
};
class CConditionOpenCommand : public CAbstractScriptCommand {
public:
CConditionOpenCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CConditionOpenCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
bool is_condition_open();
E_COND_OPS cond_op;
std::string arg1;
std::string arg2;
};
class CConditionCloseCommand : public CAbstractScriptCommand {
public:
CConditionCloseCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CConditionCloseCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
bool is_condition_close();
};
\ No newline at end of file
#include "ConfigCommand.h"
#include "../config/CellframeConfigFile.h"
CAbstractScriptCommand::Registrar<CConfigCommand> cfg_registrar("config");
/*
config cellframe-node general auto_online default true
config cellframe-node general debug_mode default false
config cellframe-node server enabled default false
config cellframe-node server listen_address default 127.0.0.1
config cellframe-node server listen_port_tcp default 8079
config cellframe-node notify_server listen_address default 127.0.0.1
config cellframe-node notify_server listen_port default 8080
if MacOS == $HOST_OS
config cellframe-node global_db driver ensure $DB_DRIVER
endif
config Backbone general node-role default full
config KelVPN general node-role default full
config raiden general node-role default full
config riemann general node-role default full
config mileena general node-role default full
config subzero general node-role default full
*/
std::vector<std::string> allowed_actions{"default", "ensure", "get"};
CConfigCommand::CConfigCommand(std::vector <std::string> cmd_tokens):CAbstractScriptCommand(cmd_tokens)
{
//zero token is always a command (config)
if (cmd_tokens.size() <= 4)
throw std::invalid_argument("config command invalid numbers of arguments");
this->cfg_name = cmd_tokens[1];
//check if config name accetable
//net should exist
fs::path net_cfg_template_path = config_path(this->cfg_name, CFG_GENERAL, CFG_TEMPLATE);
if (this->cfg_name != "cellframe-node" && !fs::exists(net_cfg_template_path))
throw std::invalid_argument(string_format("config_cmd: config for [%s] not exitst",
this->cfg_name.c_str()));
this->group = cmd_tokens[2];
this->param = cmd_tokens[3];
this->action = cmd_tokens[4];
if (allowed_actions.end() == std::find(allowed_actions.begin(), allowed_actions.end(), this->action))
{
throw std::invalid_argument(string_format("config_cmd: allowed actions are get|ensure|default, not %s",
this->action.c_str()));
}
if (cmd_tokens.size() > 5)
this->value = cmd_tokens[5];
}
bool is_placeholder(const std::string &val)
{
if (val.empty()) return true;
return val[0]=='$' && val[val.size()-1]=='}';
}
bool CConfigCommand::execute(bool non_intercative, int flags)
{
//can't do this in ctr, cause storage-cmds can be not executed yet.
this->value = substitute_variables(this->value);
auto cfg_on_path = config_path(this->cfg_name, CFG_GENERAL, CFG_ON );
auto cfg_off_path = config_path(this->cfg_name, CFG_GENERAL, CFG_OFF );
fs::path cfg_path = cfg_on_path;
if (this->cfg_name != "cellframe-node")
{
if (fs::exists(cfg_off_path))
cfg_path = cfg_off_path;
if (fs::exists(cfg_on_path))
cfg_path = cfg_on_path;
if (fs::exists(cfg_on_path) && fs::exists(cfg_off_path))
{
std::cout << "[C][config] " << "cfg " << this->cfg_name
<< " is in both on&off states, use enabled cfg for modifications" << std::endl;
}
}
std::map <std::string, std::function<bool ()>> actions;
CellframeConfigurationFile cfg(cfg_path, flags);
//check for default net state
//default means
//set if - no parameter defined
//set if value is placeholder ({CFG})
//if exists - skip
actions["default"] = [*this, &cfg]() {
std::string cfg_val;
bool param_exists = cfg.exists(this->group, this->param, &cfg_val);
if (param_exists && !is_placeholder(cfg_val)){
//skip
std::cout << "[C][config default] " << "[" << this->cfg_name<<"] "
<< "[" << this->group<<"] "
<< this->param << "==" <<cfg_val
<< ", skip altering"<<std::endl;
return false;
}
std::cout << "[C][config default] " << "[" << this->cfg_name<<"]"
<< " [" << this->group<<"] set "
<< this->param << "=" <<this->value
<< std::endl;
cfg.set(this->group, this->param, this->value);
return true;
};
//force net state
actions["ensure"] = [*this, &cfg]() {
std::cout << "[C][config ensure] " << "[" << this->cfg_name<<"] "
<< "[" << this->group<<"] set "
<< this->param << "=" <<this->value
<< std::endl;
cfg.set(this->group, this->param, this->value);
return true;
};
actions["get"] = [*this, &cfg]() {
std::string cfg_val;
bool param_exists = cfg.exists(this->group, this->param, &cfg_val);
std::cout << this->cfg_name << ": ["<<this->group<<"] " << this->param+"="+cfg_val<<std::endl;
return false;
};
//actions return true if config was altered and need to be saved
bool res = actions[this->action]();
if (res) cfg.save();
return true;
}
#pragma once
#include "AbstractCommand.h"
class CConfigCommand : public CAbstractScriptCommand {
public:
CConfigCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CConfigCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
std::string cfg_name;
std::string group;
std::string param;
std::string value;
std::string action;
};
#include "FromTemplateCommand.h"
#include <stdexcept>
#include <filesystem>
#include "../build_config.h"
#include "../config/CellframeConfigFile.h"
namespace fs = std::filesystem;
CAbstractScriptCommand::Registrar<CFromTemplateCommand> tmplt_registrar("fromtemplate");
CFromTemplateCommand::CFromTemplateCommand(std::vector <std::string> cmd_tokens): CAbstractScriptCommand(cmd_tokens)
{
if (cmd_tokens.size() <= 2)
throw std::invalid_argument("config command invalid numbers of arguments");
this->cfg_name = cmd_tokens[1];
//check if config name accetable
fs::path net_cfg_template_path = config_path(this->cfg_name, CFG_GENERAL, CFG_TEMPLATE);
if (this->cfg_name != "cellframe-node" && !fs::exists(net_cfg_template_path))
throw std::invalid_argument("config_cmd: config not exitst");
this->action = cmd_tokens[2];
}
bool CFromTemplateCommand::execute(bool non_intercative, int flags)
{
auto path_from = config_path(this->cfg_name, CFG_GENERAL, CFG_TEMPLATE);
auto path_to = config_path(this->cfg_name, CFG_GENERAL, CFG_ON);
if (this->action == "default")
{
if (fs::exists(path_to))
{
std::cout << "[C][fromtemplate default] " << " [" << this->cfg_name<<"]"
<< " exists, skip altering"<<std::endl;
return true;
}
std::cout <<"[C] [fromtemplate default] "
<<"copy "<< path_from << " to "<< path_to << std::endl;
if (!(flags & F_DRYRUN)) fs::copy_file(path_from, path_to);
}
if (this->action == "ensure")
{
std::cout <<"[C] [fromtemplate ensure] "
<<"copy "<< path_from << " to "<< path_to << std::endl;
if (!(flags & F_DRYRUN)) fs::copy_file(path_from, path_to, fs::copy_options::overwrite_existing);
}
//populate
CellframeConfigurationFile cfg(path_to, flags);
cfg.replace_placeholders(variable_storage);
cfg.save();
return true;
}
\ No newline at end of file
#pragma once
#include "AbstractCommand.h"
class CFromTemplateCommand : public CAbstractScriptCommand {
public:
CFromTemplateCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CFromTemplateCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
std::string cfg_name;
std::string action;
};
#include "NetworkCommand.h"
#include <stdexcept>
#include <filesystem>
#include "../build_config.h"
#include "../config/CellframeConfigFile.h"
namespace fs = std::filesystem;
CAbstractScriptCommand::Registrar<CNetworkCommand> registrar("network");
/*
Network Command syntax:
network {netname} default on
network {netname} default off
network {netname} ensure off
network {netname} ensure on
*/
std::vector<std::string> allowed_states{"on", "off"};
CNetworkCommand::CNetworkCommand(std::vector <std::string> cmd_tokens): CAbstractScriptCommand(cmd_tokens)
{
//zero token is always a command (network)
if (cmd_tokens.size() <= 2)
throw std::invalid_argument("network command has no command arguments");
this->net_name = cmd_tokens[1];
//check such net is available: lookup for config files in share dir
fs::path net_cfg_template_path = config_path(this->net_name, CFG_GENERAL, CFG_TEMPLATE);
if (!fs::exists(net_cfg_template_path))
throw std::invalid_argument("network_cmd: template not found in share config path");
std::map <std::string, std::function<void ()>> actions;
actions["default"] = [this, &cmd_tokens](){
if (cmd_tokens.size() < 4 || allowed_states.end() == std::find(allowed_states.begin(), allowed_states.end(), cmd_tokens[3]))
throw std::invalid_argument("network_cmd: [default] require 'on or off' state for net");
this->default_val = cmd_tokens[3];
};
actions["ensure"] = [this, &cmd_tokens](){
if (cmd_tokens.size() < 4 || allowed_states.end() == std::find(allowed_states.begin(), allowed_states.end(), cmd_tokens[3]))
throw std::invalid_argument("network_cmd: [ensure] require 'on or off' state for net" );
this->default_val = cmd_tokens[3];
};
actions["check"] = [this, &cmd_tokens](){};
this->action = cmd_tokens[2];
if (actions.find(this->action) == actions.end())
throw std::invalid_argument("network_cmd: unknown action for network_cmd");
actions[this->action]();
}
bool CNetworkCommand::execute(bool non_intercative, int flags)
{
std::map <std::string, std::function<bool ()>> actions;
//check for default net state
actions["default"] = [&]() {
//validity of default_value ensured by constructor
fs::path check_exist_path;
fs::path template_copy_dest;
fs::path template_path = config_path(this->net_name, CFG_GENERAL, CFG_TEMPLATE);
if (fs::exists(config_path(this->net_name, CFG_GENERAL, CFG_OFF)) &&
fs::exists(config_path(this->net_name, CFG_GENERAL, CFG_ON)) )
{
std::cout << "[C][network default] you have both enabled and disabled files for network [" << this->net_name << "], skip this step"<<std::endl;
return false;
}
//default requested net on
if (this->default_val == "on")
{
check_exist_path = config_path(this->net_name, CFG_GENERAL, CFG_OFF);
template_copy_dest = config_path(this->net_name, CFG_GENERAL, CFG_ON);
} else if (this->default_val == "off")
{
check_exist_path = config_path(this->net_name, CFG_GENERAL, CFG_ON);
template_copy_dest = config_path(this->net_name, CFG_GENERAL, CFG_OFF);
} else { std::cout << "wtf" << std::endl; return false; }
//skip default if net already exists in any state
if (fs::exists(template_copy_dest)) {
std::cout << "[C][network default " << this->default_val<<"] Network [" << this->net_name << "] already "<< this->default_val << ", skip this step" <<std::endl;
return true;
}
if (fs::exists(check_exist_path))
{
if (flags & F_VERBOSE) std::cout << "[VE][network default] File " << check_exist_path << " exists, but default state requested [" << this->default_val << "]";
std::cout << "[C}[network default] Skip altering state for newtwork [" << this->net_name<<"] due to it was user-configured" << std::endl;
return false;
}
// default on: net exists, not on, and not disabled -> copy network config as enabled
std::cout << "[C][network default] Set-up net [" << this->net_name << "] as ["<< (this->default_val == "on" ? "ENABLED" : "DISABLED")
<< "] from template " << template_path << std::endl;
if (flags & F_VERBOSE) std::cout << "[VE][network default] copy file from " << template_path << " to " << template_copy_dest << std::endl;
if (!(flags & F_DRYRUN)) fs::copy(template_path, template_copy_dest);
return true;
};
//force net state
actions["ensure"] = [&]() {
//check for disabled
bool net_enabled = fs::exists(config_path(this->net_name, CFG_GENERAL, CFG_ON));
if (this->default_val == "on" && net_enabled)
{
std::cout << "[C][network ensure on]: Network [" << this->net_name << "] already enabled"<<std::endl;
return false;
}
if (this->default_val == "off" && !net_enabled && fs::exists(config_path(this->net_name, CFG_GENERAL, CFG_OFF)))
{
std::cout << "[C][network ensure off]: Network [" << this->net_name << "] already disabled"<<std::endl;
return false;
}
ENetworkConfigState requested_state, oposite_state;
if (this->default_val == "on") {
requested_state = CFG_ON;
oposite_state = CFG_OFF;
}
if (this->default_val == "off")
{
requested_state = CFG_OFF;
oposite_state = CFG_ON;
}
//move from oposite if exists
if (fs::exists(config_path(this->net_name, CFG_GENERAL, oposite_state))){
std::cout << "[C][network ensure " << this->default_val << "] move file from "
<< config_path(this->net_name, CFG_GENERAL, oposite_state)
<< " to " << config_path(this->net_name, CFG_GENERAL, requested_state)
<< std::endl;
if (!(flags & F_DRYRUN)) fs::rename(config_path(this->net_name, CFG_GENERAL, oposite_state),
config_path(this->net_name, CFG_GENERAL, requested_state));
} else { //copy from template if oposite side of config not exits
std::cout << "[C][network ensure "<<this->default_val << "] copy file from "
<< config_path(this->net_name, CFG_GENERAL, CFG_TEMPLATE)
<< " to " << config_path(this->net_name, CFG_GENERAL, requested_state)
<< std::endl;
if (!(flags & F_DRYRUN)) fs::copy(config_path(this->net_name, CFG_GENERAL, CFG_TEMPLATE),
config_path(this->net_name, CFG_GENERAL, requested_state));
}
return true;
};
//force net state
actions["check"] = [&]() {
//check for disabled
bool net_enabled = fs::exists(config_path(this->net_name, CFG_GENERAL, CFG_ON));
std::cout << "[C][network check]: Network [" << this->net_name << "] " << (net_enabled ? "on" : "off") << std::endl;
return true;
};
return actions[this->action]();
}
#include "AbstractCommand.h"
class CNetworkCommand : public CAbstractScriptCommand {
public:
CNetworkCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CNetworkCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
std::string net_name;
std::string action;
std::string default_val;
};
#include "NetworkListCommand.h"
#include <stdexcept>
#include <filesystem>
#include "../build_config.h"
#include "../config/CellframeConfigFile.h"
namespace fs = std::filesystem;
CAbstractScriptCommand::Registrar<CNetworkListCommand> net_list_registrar("net_list");
CNetworkListCommand::CNetworkListCommand(std::vector <std::string> cmd_tokens)
: CAbstractScriptCommand(cmd_tokens)
{
if (cmd_tokens.size() >= 2)
if(cmd_tokens[1] == "on")
{
m_state = ON;
}
else if(cmd_tokens[1] == "off")
{
m_state = OFF;
}
}
bool CNetworkListCommand::execute(bool non_intercative, int flags)
{
fs::path directoryPath = get_config_path();
if(!fs::exists(directoryPath))
{
std::cout << "The catalog was not found." << std::endl;
return false;
}
if (!fs::is_directory(directoryPath)) {
std::cout << "The specified path is not a directory." << std::endl;
return false;
}
std::vector<NetworkInfo> configs;
const std::string dis = ".dis";
const std::string cfg = ".cfg";
for (const auto& entry : fs::directory_iterator(directoryPath))
{
if(fs::is_regular_file(entry.status()))
{
std::string name = entry.path().filename().string();
auto removeSubstring = [](std::string& str, const std::string& tuRemove)
{
size_t pos = 0;
while ((pos = str.find(tuRemove, pos)) != std::string::npos) {
str.erase(pos, tuRemove.length());
}
};
bool isDis = name.find(dis) != std::string::npos;
bool isCfg = name.find(cfg) != std::string::npos;
if((isDis && isCfg)
&& (m_state == ALL || m_state == OFF) )
{
removeSubstring(name, cfg + dis);
configs.push_back({name, "off"});
}
else if((!isDis && isCfg)
&& (m_state == ALL || m_state == ON))
{
removeSubstring(name, cfg);
configs.push_back({name, "on"});
}
else if((!isDis && !isCfg)
&& m_state == ALL)
{
configs.push_back({name, "unknown"});
}
}
}
if(configs.empty())
{
std::cout << "No networks were found.";
}
else
{
for (const auto& item : configs) {
std::cout << "name: " <<item.networkName << "\t state:" << item.state << std::endl;
}
}
return true;
}
#pragma once
#include "AbstractCommand.h"
class CNetworkListCommand : public CAbstractScriptCommand {
enum NetworState{
ALL = 0,
ON,
OFF
};
struct NetworkInfo
{
std::string networkName = "";
std::string state = "";
};
public:
CNetworkListCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CNetworkListCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
NetworState m_state = ALL;
};
#include "ServiceCommand.h"
#include <stdexcept>
#include <filesystem>
#include "../build_config.h"
#include "../config/CellframeConfigFile.h"
#include "../service/service.h"
namespace fs = std::filesystem;
CAbstractScriptCommand::Registrar<CServiceCommand> service_registrar("service");
CServiceCommand::CServiceCommand(std::vector <std::string> cmd_tokens): CAbstractScriptCommand(cmd_tokens)
{
//zero token is always a command (network)
if (cmd_tokens.size() < 2)
throw std::invalid_argument("service command require action argument");
this->action = cmd_tokens[1];
}
bool CServiceCommand::execute(bool non_intercative, int flags)
{
if (this->action == "enable"){
if (CServiceControl::enable()) {
std::cout << "enabled" <<std::endl;
}
else{
std::cout << "error" <<std::endl;
}
}
if (this->action == "disable")
{
if (CServiceControl::disable()) {
std::cout << "disabled" <<std::endl;
}
else{
std::cout << "error" <<std::endl;
}
}
if (this->action == "status")
{
unsigned int status = CServiceControl::serviceStatus();
if (status & SERVICE_ENABLED)
std::cout << "service: enabled" << std::endl;
else
std::cout << "service: disabled" << std::endl;
if (status & PROCESS_RUNNING)
std::cout << "process: running" << std::endl;
else
std::cout << "process: notfound" << std::endl;
}
if (this->action == "start")
{
if (CServiceControl::start())
{
std::cout << "started" << std::endl;
}
else
{
std::cout << "error" << std::endl;
}
}
if (this->action == "stop")
{
if (CServiceControl::stop())
{
std::cout << "stoped" << std::endl;
}
else
{
std::cout << "error" << std::endl;
}
}
if (this->action == "restart")
{
if (CServiceControl::restart())
{
std::cout << "restarted" << std::endl;
}
else
{
std::cout << "error" << std::endl;
}
}
return true;
}
#include "AbstractCommand.h"
class CServiceCommand : public CAbstractScriptCommand {
public:
CServiceCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CServiceCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
std::string action;
};
#include "StorageCommand.h"
#include "../config/CellframeConfigFile.h"
CAbstractScriptCommand::Registrar<CVariableCommand> var_registrar("var");
CVariableCommand::CVariableCommand(std::vector <std::string> cmd_tokens):CAbstractScriptCommand(cmd_tokens)
{
std::string joined_condition = string_join(std::vector<std::string>(cmd_tokens.begin()+1,cmd_tokens.end()), "");
std::vector < std::string> tokens = tokenize(joined_condition, std::regex("="));
if (tokens.size() != 2) throw std::invalid_argument("var command uses exactly VAR=VAL syntax");
this->var = tokens[0];
this->val = tokens[1];
}
bool CVariableCommand::execute(bool non_intercative, int flags)
{
std::string real_val = substitute_variables(this->val);
variable_storage[this->var] = real_val;
if (flags & F_VERBOSE)
{
std::cout <<"[VC] Set "<<real_val<< " as " << this->var << ", current stor = {";
for (auto a: variable_storage) {
std::cout << a.first << " : " << a.second<<", ";
}
std::cout << "}"<<std::endl;
}
return true;
}
#pragma once
#include "AbstractCommand.h"
class CVariableCommand : public CAbstractScriptCommand {
public:
CVariableCommand(std::vector <std::string> cmd_tokens);
static std::unique_ptr<CAbstractScriptCommand> create(std::vector <std::string> cmd_tokens) { return std::make_unique<CVariableCommand>(cmd_tokens); }
bool execute(bool non_interactive, int flags);
private:
std::string var;
std::string val;
};
#include "CellframeConfigFile.h"
#include <any>
#include <chrono>
#include <functional>
#include <iomanip>
#include <map>
#include <memory>
#include <regex>
#include <stdexcept>
#include <string>
#include <vector>
namespace utils {
std::string escape(const std::string &str);
struct IPlaceholder {
virtual std::string resolve(const std::vector<std::any> &args) const = 0;
virtual const std::string &getPattern() const = 0;
virtual ~IPlaceholder() = default;
};
class ArgCountError : public std::runtime_error {
public:
explicit ArgCountError(const std::string &msg) : std::runtime_error(msg) {}
ArgCountError() : std::runtime_error("Wrong number of arguments provided") {}
};
template <typename... Args>
class Placeholder : public IPlaceholder {
public:
using FuncType = std::function<std::string(Args...)>;
Placeholder(std::string p, FuncType r) : pattern_(std::move(p)), resolver_(std::move(r)) {}
const std::string &getPattern() const override { return pattern_; }
std::string resolve(const std::vector<std::any> &args) const override {
if (args.size() != sizeof...(Args)) throw ArgCountError();
return invoke(args, std::index_sequence_for<Args...>{});
}
private:
std::string pattern_;
FuncType resolver_;
template <size_t... I>
std::string invoke(std::vector<std::any> const &args, std::index_sequence<I...>) const {
return resolver_(std::any_cast<Args>(args[I])...);
}
};
class SubstitutionError : public std::runtime_error {
public:
explicit SubstitutionError(const std::string &msg): std::runtime_error(msg) {}
SubstitutionError() : std::runtime_error("Error executing the replacing of the placeholder") {
}
};
class PlaceholderManager {
public:
typedef std::string(EscapingFnctTp)(const std::string &str);
void addPlaceholder(const std::shared_ptr<IPlaceholder> &placeholder) {
placeholders_[placeholder->getPattern()] = placeholder;
}
void setEscapingFnct(std::function<EscapingFnctTp> escapingFnct) {
escapingFnct_ = escapingFnct;
}
std::string replacePlaceholders(
std::string input, const std::map<std::string, std::vector<std::any>> &args = {}) {
for (const auto &itPh : placeholders_)
{
replaceEachPh(input, args, itPh.second);
}
return input;
}
private:
std::map<std::string, std::shared_ptr<IPlaceholder>> placeholders_;
void replaceEachPh(std::string &input,
const std::map<std::string, std::vector<std::any>> &args,
const std::shared_ptr<IPlaceholder> &ph) {
static const std::vector<std::any> empty{};
const std::string &phStr = ph->getPattern();
std::regex regex(escapingFnct_(phStr));
auto it = args.find(phStr);
const std::vector<std::any> &vArgs = it != args.end() ? it->second : empty;
std::string fmt;
try {
fmt = ph->resolve(vArgs);
try {
input = std::regex_replace(input, regex, fmt);
} catch (...) {
throw SubstitutionError();
}
} catch (const ArgCountError &) {
}
}
private:
std::function<EscapingFnctTp> escapingFnct_{utils::escape};
};
inline std::string escape(const std::string &str) {
std::regex exp("\\{");
std::string res = std::regex_replace(str, exp, "\\{");
exp = std::regex("\\}");
res = std::regex_replace(res, exp, "\\}");
return res;
}
}
fs::path get_config_path(EPathConfigType pathType)
{
fs::path resultPath;
switch (pathType)
{
case CFG_NODE:
resultPath = fs::path{variable_storage["CONFIGS_PATH"]}/"share"/"configs";
break;
case CFG_NODE_TEMPLATE:
resultPath = fs::path{variable_storage["CONFIGS_PATH"]}/"etc";
break;
case CFG_NETWORK:
resultPath = fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"network/";
break;
case CFG_NETWORK_TEMPLATE:
resultPath = fs::path{variable_storage["CONFIGS_PATH"]}/"share"/"configs"/"network/";
break;
default:
break;
}
return resultPath;
}
fs::path config_path(const std::string &name, ENetworkConfigType type, ENetworkConfigState state) {
if (name == "cellframe-node")
{ if (state == CFG_TEMPLATE)
return fs::path{variable_storage["CONFIGS_PATH"]}/"share"/"configs"/"cellframe-node.cfg";
else
return fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"cellframe-node.cfg";
}
switch (type)
{
case CFG_GENERAL:
if (state == CFG_ON) return fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"network/"/(name + ".cfg");
if (state == CFG_OFF) return fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"network/"/(name + ".cfg.dis");
if (state == CFG_TEMPLATE) return fs::path{variable_storage["CONFIGS_PATH"]}/"share"/"configs"/"network/"/(name + ".cfg");
break;
case CFG_MAINCHAIN:
return fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"network/"/name/"main.cfg";
case CFG_ZEROCHAIN:
return fs::path{variable_storage["CONFIGS_PATH"]}/"etc"/"network/"/name/"zerochain.cfg";
}
throw std::invalid_argument("cfg for such params cant be detectd");
}
CellframeConfigurationFile::CellframeConfigurationFile(fs::path filepath, int flags):flags(flags) {
if (!fs::exists(filepath))
throw std::invalid_argument(string_format("Config path [%s] not exitsts", filepath.c_str()));
std::ifstream infile(filepath);
size_t line_num = 0;
for( std::string line; std::getline( infile, line ); line_num++)
{
this->lines.push_back(line);
}
if (flags & F_VERBOSE) std::cout << "[VC] Loaded "<<line_num<<" lines form " << filepath << std::endl;
this->path = filepath;
}
bool is_group_decl(const std::string line, std::string *gname)
{
std::string trimmed_line = line;
auto tokens = tokenize(trimmed_line, std::regex("="));
if (tokens.size()>1) return false;
if (tokens[0][0]!='[') return false;
std::string group_name = tokens[0].substr(tokens[0].find('[')+1, tokens[0].find(']')-1);
trim(group_name);
if (group_name.empty()) return false;
if (gname) *gname = group_name;
return true;
}
struct cfg_pair {
std::string param;
std::string val;
};
cfg_pair parse_param_value(const std::string line)
{
std::string trimmed_line = line;
if (line.find("=") == line.npos) throw std::invalid_argument("config line expected to be key=value");
auto tokens = tokenize(trimmed_line, std::regex("="));
trim(tokens[0]);
if (tokens.size() < 2)
tokens.push_back("");
return {tokens[0], tokens[1]};
}
bool CellframeConfigurationFile::exists(const std::string & group, const std::string & param, std::string *value, int *line_no, bool *group_exists)
{
if (flags & F_VERBOSE) std::cout << "[VC] Check for existanse [" << group<<"] "<<param << " in "<<this->path <<std::endl;
bool group_found = false;
int current_line = -1;
std::string group_name;
for( auto line : lines)
{
current_line ++;
trim(line);
line = line.substr(0, line.find("#")); //skip comments
if(line.empty()) continue; //skip empties
bool is_grp_decl = is_group_decl(line, &group_name);
if (is_grp_decl && !group_found)
{
if (flags & F_VERBOSE) std::cout << "[VC] Found group [" << group_name<<"] " << std::endl;
if (group_name == group) group_found = true;
continue;
}
if (is_grp_decl && group_found)
{
if (flags & F_VERBOSE) std::cout << "[VC] No param in group [" << group_name<<"], group ends at " << current_line-1 << std::endl;
if (line_no) *line_no = current_line-1;
if (group_exists) *group_exists = group_found;
return false;
}
if (!group_found) continue;
auto res = parse_param_value(line);
if (res.param == param)
{
if (flags & F_VERBOSE) std::cout << "[VC] in group [" << group_name<<"] found "
<< res.param
<< ":" <<res.val
<< " at line "
<< current_line << std::endl;
if (group_exists) *group_exists = group_found;
if (value) *value = res.val;
if (line_no) *line_no = current_line;
return true;
}
}
if (line_no) *line_no = current_line-1;
if (group_exists)
*group_exists = group_found;
return false;
}
std::string CellframeConfigurationFile::set(const std::string & group, const std::string & param, const std::string &value)
{
if (flags & F_VERBOSE) std::cout << "[VC] set ["
<< group << "] "<<param<<"="<<value << std::endl;
int line_set_to;
bool group_exists = false;
bool param_exists = exists(group, param, nullptr, &line_set_to, &group_exists);
if (param_exists) lines[line_set_to] = param+"="+value;
else
{
if (!group_exists)
{
lines.emplace(lines.begin()+line_set_to, "["+group+"]");
line_set_to += 1;
}
lines.emplace(lines.begin()+line_set_to, param+"="+value);
lines.emplace(lines.begin()+line_set_to + 1, "\n");
}
return lines[line_set_to];
}
bool CellframeConfigurationFile::save()
{
if (flags & F_VERBOSE) std::cout << "[VC] saving " << this->lines.size() << " lines to " << this->path << std::endl;
if (flags & F_DRYRUN) {
for (auto l : lines) std::cout << l << std::endl;
return true;
};
std::ofstream file(path);
for (auto l : lines) file << l << std::endl;
file.close();
return true;
}
void CellframeConfigurationFile::replace_placeholders(std::map<std::string, std::string> data)
{
if (flags & F_VERBOSE) std::cout << "[VC] replacing placeholders in" << this->path<< std::endl;
int current_line = -1;
for( auto line : lines)
{
current_line ++;
trim(line);
line = line.substr(0, line.find("#")); //skip comments
if(line.empty()) continue; //skip empties
auto nline = substitute_variables(line);
lines[current_line] = nline;
}
}
std::string substitute_variables(const std::string &string)
{
utils::PlaceholderManager pman;
for (auto var: variable_storage){
pman.addPlaceholder(std::make_shared<utils::Placeholder<>>(
std::string("\\${"+var.first+"}"), [=] { return var.second; }));
}
return pman.replacePlaceholders(string);
}
#pragma once
#include <algorithm>
#include <string>
#include <iostream>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include <regex>
#include <unordered_map>
#include <memory>
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <iterator>
#include <numeric>
#include "../commands/AbstractCommand.h"
#include "../build_config.h"
namespace fs = std::filesystem;
enum ENetworkConfigType{
CFG_GENERAL,
CFG_MAINCHAIN,
CFG_ZEROCHAIN
};
enum ENetworkConfigState{
CFG_ON = 1,
CFG_OFF = 1 << 2,
CFG_TEMPLATE = 1 << 3,
};
enum EPathConfigType{
CFG_NODE = 0,
CFG_NODE_TEMPLATE,
CFG_NETWORK,
CFG_NETWORK_TEMPLATE
};
fs::path config_path(const std::string &netname, ENetworkConfigType type, ENetworkConfigState state = CFG_ON);
fs::path get_config_path(EPathConfigType pathType = CFG_NETWORK);
struct CellframeConfigurationFile {
CellframeConfigurationFile(fs::path filepath, int flags = 0);
bool exists(const std::string & group, const std::string & param, std::string *value = nullptr, int *line_no = nullptr, bool *group_exists = nullptr);
std::string set(const std::string & group, const std::string & param, const std::string &value);
void replace_placeholders(std::map<std::string, std::string> data);
bool save();
private:
fs::path path;
std::vector<std::string> lines;
int flags;
};
std::string substitute_variables(const std::string &string);
/*
Cellframe-Node Configuration controll tool.
2024 dmitry.puzrkov@demlabs.net
confctl tool uses .setup files with basic command and scripting capabilities to
initial setup of cellframe-node as intended by developers.
It will not alter any user settings if they exists.
// cellframe-node-config --init /path/to/cellframe-node.setup [-v | --verbose]
// .setup file syntax:
command param1 param2 param3 ....
*/
#include <algorithm>
#include <map>
#include <string>
#include <iostream>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include "commands/AbstractCommand.h"
#include <stdexcept>
#ifdef __linux__
#include <unistd.h> //Linux
#endif
#ifdef __APPLE__
#include <unistd.h> //Apple
#endif
#ifdef _WIN32
#include <winsock.h> //Windows
#include <windows.h>
#endif
namespace conftool {
std::string getHostName(void)
{
std::string res = "unknown";
char tmp[0x100];
if( gethostname(tmp, sizeof(tmp)) == 0 )
{
res = tmp;
}
return res;
}
#ifdef WIN32
LONG GetDWORDRegKey(HKEY hKey, const std::wstring &strValueName, DWORD &nValue, DWORD nDefaultValue)
{
nValue = nDefaultValue;
DWORD dwBufferSize(sizeof(DWORD));
DWORD nResult(0);
LONG nError = ::RegQueryValueExW(hKey,
strValueName.c_str(),
0,
NULL,
reinterpret_cast<LPBYTE>(&nResult),
&dwBufferSize);
if (ERROR_SUCCESS == nError)
{
nValue = nResult;
}
return nError;
}
LONG GetBoolRegKey(HKEY hKey, const std::wstring &strValueName, bool &bValue, bool bDefaultValue)
{
DWORD nDefValue((bDefaultValue) ? 1 : 0);
DWORD nResult(nDefValue);
LONG nError = GetDWORDRegKey(hKey, strValueName.c_str(), nResult, nDefValue);
if (ERROR_SUCCESS == nError)
{
bValue = (nResult != 0) ? true : false;
}
return nError;
}
LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
strValue = strDefaultValue;
WCHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
strValue = szBuffer;
}
return nError;
}
#endif
namespace fs = std::filesystem;
std::string getNodeConfigPath(std::string basepath){
#ifdef ANDROID
return basepath;
#endif
#ifdef __linux__
return "/opt/cellframe-node";
#endif
#ifdef __APPLE__
return "/Library/Application Support/CellframeNode";
#endif
#ifdef WIN32
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hKey);
bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
std::wstring path;
GetStringRegKey(hKey, L"Common Documents", path, L"");
std::string stdpath(path.begin(),path.end());
return (std::filesystem::path{stdpath}/"cellframe-node").string();
#endif
}
std::string getNodeBinaryPath(){
#ifdef __linux__
return "/opt/cellframe-node/bin/";
#endif
#ifdef __APPLE__
return "/Applications/CellframeNode.app/Contents/MacOS/";
#endif
#ifdef WIN32
//HKLM "Software\${APP_NAME}" "Path"
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\cellframe-node\\", 0, KEY_READ, &hKey);
bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
std::wstring path;
GetStringRegKey(hKey, L"Path", path, L"");
std::string stdpath(path.begin(),path.end());
return (std::filesystem::path{stdpath}).string();
#endif
}
bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
return std::find(begin, end, option) != end;
}
std::string getCmdOption(char ** begin, char ** end, const std::string & option_long, const std::string & option_short )
{
std::string option = option_long;
if (!cmdOptionExists(begin, end, option))
option = option_short;
char ** itr = std::find(begin, end, option);
if (itr != end && ++itr != end)
{
return std::string(*itr);
}
return std::string();
}
void print_help()
{
std::cout << "cellframe-node-config -h | --help" << std::endl;
std::cout << "\t prints this help message" << std::endl;
std::cout << "cellframe-node-config -s | --vars" << std::endl;
std::cout << "\t prints installation config variables." << std::endl;
std::cout << "cellframe-node-config -v | --verbose" << std::endl;
std::cout << "\t enable verbose output" << std::endl;
std::cout << "cellframe-node-config -d | --dry-run" << std::endl;
std::cout << "\t do not actual do a file-system commands" << std::endl;
std::cout << "cellframe-node-config -i | --init /path/to/cellframe-node.setup" << std::endl;
std::cout << "\t do initial configuration based on provided setup script" << std::endl;
std::cout << "cellframe-node-config -e | --exec <command> [and <command> [and <command>]...]" << std::endl;
std::cout << "\t execute provided commands. " << std::endl<< std::endl;
std::cout << "Allowed commands:" << std::endl;
std::cout << "\tnetwork <netname> ensure on|off" << std::endl;
std::cout << "\t\t enable | disable <netname> network" << std::endl;
std::cout << "\tnet_list all|on|off" << std::endl;
std::cout << "\t\t on - active networks. off - not active networks. all or nothing - all network" << std::endl;
std::cout << "\tconfig <configname> <section> <param> ensure <value>" << std::endl;
std::cout << "\t\t set a parameter <param> in section <section> in config <configname> to <value>" << std::endl;
std::cout << "\t\t Possible configs: \"cellframe-node\", \"<netname>\"" << std::endl;
std::cout << "\tservice enable" << std::endl;
std::cout << "\t\t set cellframe-node to autostart on boot" << std::endl;
std::cout << "\tservice disable" << std::endl;
std::cout << "\t\t remove cellframe-node from autostart on boot" << std::endl;
std::cout << "\tservice start" << std::endl;
std::cout << "\t\t start cellframe-node (if registred as service!)" << std::endl;
std::cout << "\tservice stop" << std::endl;
std::cout << "\t\t stop cellframe-node (if registred as service!)" << std::endl;
std::cout << "\tservice status" << std::endl;
std::cout << "\t\t get service & process statuses" << std::endl;
}
std::unique_ptr<CAbstractScriptCommand> parse_line_to_cmd(std::string line, int line_no, int flags) {
auto cmd = CAbstractScriptCommand::build(line);
if (!cmd)
throw std::invalid_argument("setup file line " + std::to_string(line_no) + " << {" +line +"} >> error: unknown command");
if (flags & F_VERBOSE) std::cout << "[V] Command: " << cmd->represent() <<std::endl;
return cmd;
}
std::vector <std::unique_ptr<CAbstractScriptCommand> > parse_setup_file(const std::string &init_file_name, int flags)
{
std::ifstream infile(init_file_name);
std::vector <std::unique_ptr<CAbstractScriptCommand> > res;
size_t line_num = 0;
if (flags & F_VERBOSE) std::cout << "[V] Parsing "<<init_file_name << " as setup-script" << std::endl;
for( std::string line; std::getline( infile, line ); line_num++)
{
trim(line);
line = line.substr(0, line.find("#")); //skip comments
if(line.empty()) continue; //skip empties
res.push_back(std::move(parse_line_to_cmd(line, line_num, flags)));
}
return res;
}
void print_cond_stack(std::vector < std::unique_ptr<CAbstractScriptCommand>> &condition_stack)
{
std::cout << "[VE] Condition stack: [";
for (auto &a : condition_stack)
std::cout << "{" << a->represent() << "} ";
std::cout << "] "<<std::endl;
}
bool run_commands(std::vector <std::unique_ptr<CAbstractScriptCommand>> &commands, int interactive, int flags)
{
//dry_run for conditions check
std::vector<std::unique_ptr <CAbstractScriptCommand>> condition_stack;
for (auto &cmd : commands)
{
if (cmd->is_condition_open() || cmd->is_condition_close()) {
if (cmd->is_condition_open()) condition_stack.push_back(std::move(cmd));
else if (cmd->is_condition_close()) condition_stack.pop_back();
if (flags & F_VERBOSE) print_cond_stack(condition_stack);
continue;
}
if (condition_stack.size() > 0)
{
//execute only of condition passed
if (condition_stack.back()->execute(!interactive, flags)) cmd->execute(!interactive, flags);
} else
{
//no condition in stack, exec command
cmd->execute(!interactive, flags);
}
}
return true;
}
void populate_variables(std::string basepath)
{
variable_storage["HOST_OS"] = HOST_OS;
variable_storage["HOSTNAME"] = getHostName();
variable_storage["CONFIGS_PATH"] = getNodeConfigPath(basepath);
variable_storage["NODE_BINARY_PATH"] = getNodeBinaryPath();
}
int init_configs(std::string init_file_name, int flags, int non_interactive)
{
if (init_file_name.empty())
{
std::cout << "No setup file provided for init procedure, see --help" << std::endl;
return -1;
}
if (!fs::exists(fs::path{init_file_name}))
{
std::cout << "Setup file " << init_file_name << " not found" << std::endl;
return -1;
}
std::cout << "Cellframe-node configs install path: " << variable_storage["CONFIGS_PATH"] << std::endl;
auto commands = parse_setup_file(init_file_name, flags);
run_commands(commands, !non_interactive, flags);
return 0;
}
}
using namespace conftool;
int main(int argc, char * argv[])
{
populate_variables(""); //basepath used only for android
if(cmdOptionExists(argv, argv+argc, "-h") || cmdOptionExists(argv, argv+argc, "--help"))
{
print_help();
return 0;
}
int flags = 0;
if (cmdOptionExists(argv, argv+argc, "--verbose") || cmdOptionExists(argv, argv+argc, "-v")) flags = flags | F_VERBOSE;
if (cmdOptionExists(argv, argv+argc, "--vars") || cmdOptionExists(argv, argv+argc, "-s")) {
for (auto v: variable_storage)
{
std::cout << v.first << "="<<v.second<<std::endl;
}
return 0;
}
if (cmdOptionExists(argv, argv+argc, "--dryrun") || cmdOptionExists(argv, argv+argc, "-d")) flags = flags | F_DRYRUN;
if(cmdOptionExists(argv, argv+argc, "-i") || cmdOptionExists(argv, argv+argc, "--init"))
{
//--init already exists, give me filename
std::string init_file_name = getCmdOption(argv, argv+argc, "--init", "-i");
std::string node_intall_path = getCmdOption(argv, argv+argc, "--path", "-p");
if (!node_intall_path.empty())
{
variable_storage["CONFIGS_PATH"] = node_intall_path;
}
bool non_interactive = cmdOptionExists(argv, argv+argc, "--non-interactive") || cmdOptionExists(argv, argv+argc, "-n");
return init_configs(init_file_name, flags, non_interactive);
}
if(cmdOptionExists(argv, argv+argc, "-e") || cmdOptionExists(argv, argv+argc, "--exec"))
{
std::string option = "-e";
if (cmdOptionExists(argv, argv+argc, "--exec")) option = "--exec";
auto pos = std::find(argv, argv+argc, option);
std::vector <std::string> commands_lines;
std::string curr_cmd;
while (pos != argv+argc-1)
{
pos++;
if (std::string(*pos) == "and") { commands_lines.push_back(curr_cmd); curr_cmd = ""; continue; }
curr_cmd += *pos;
curr_cmd += " ";
}
commands_lines.push_back(curr_cmd);
std::vector <std::unique_ptr<CAbstractScriptCommand> > script_cmds;
for (int i =0; i< commands_lines.size(); i++) {
script_cmds.push_back(parse_line_to_cmd(commands_lines[i], i, flags));
}
run_commands(script_cmds, false, flags);
return 0;
}
print_help();
return 0;
}
extern "C" int callSec (char *tool, char* args[]);
extern "C" int callSecScript(char *script);
\ No newline at end of file
#ifdef __APPLE__
#import <Foundation/Foundation.h>
#include "Foundation/NSString.h"
#include "Foundation/NSAppleScript.h"
#
int callSec (char *tool, char* args[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Create authorization reference
AuthorizationRef authorizationRef;
OSStatus status;
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
// Run the tool using the authorization reference
FILE *pipe = NULL;
status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
if (status == errAuthorizationSuccess) {
return 0;
} else {
NSLog(@"Authorization Result Code: %d", status);
}
[pool drain];
return -1;
}
int callSecScript(char *script)
{
NSDictionary *error = [NSDictionary new];
NSString *appleScriptString = @"do shell script ";
appleScriptString = [appleScriptString stringByAppendingString:@"\""];
appleScriptString = [appleScriptString stringByAppendingString:[NSString stringWithUTF8String: script]];
appleScriptString = [appleScriptString stringByAppendingString:@"\""];
appleScriptString = [appleScriptString stringByAppendingString:@" with administrator privileges"];
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:appleScriptString];
NSString *result;
result = [[appleScript executeAndReturnError: &error] stringValue];
return 0;
}
#endif
\ No newline at end of file