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 1403 additions and 1 deletion
#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
#include <algorithm>
#include <map>
#include <string>
#include <iostream>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include <stdexcept>
enum EServiceStatus{
SERVICE_ENABLED = 1 << 0,
PROCESS_RUNNING = 1 << 2,
};
struct CServiceControl
{
static bool enable();
static bool disable();
static unsigned int serviceStatus();
static bool start();
static bool stop();
static bool restart();
};
\ No newline at end of file
#ifdef __linux__
#include "service.h"
#include "../commands/AbstractCommand.h"
bool CServiceControl::enable(){
std::string cmd = "systemctl enable " + (std::filesystem::path{variable_storage["CONFIGS_PATH"]}/"share"/"cellframe-node.service > /dev/null").string();
int res = std::system(cmd.c_str());
return res == 0 ? true : false;
}
bool CServiceControl::disable()
{
std::string cmd = "systemctl disable cellframe-node.service > /dev/null";
int res = std::system(cmd.c_str());
return res == 0 ? true : false;
}
unsigned int CServiceControl::serviceStatus()
{
unsigned int status = 0;
std::string cmd = "systemctl is-enabled cellframe-node.service > /dev/null";
int res = std::system(cmd.c_str());
if (res == 0)
{
status |= SERVICE_ENABLED;
}
cmd = "pgrep -x cellframe-node > /dev/null";
res = std::system(cmd.c_str());
if (res == 0)
{
status |= PROCESS_RUNNING;
}
return (unsigned int)status;
}
bool CServiceControl::start()
{
std::string cmd = "systemctl start cellframe-node.service > /dev/null";
int res = std::system(cmd.c_str());
return res == 0 ? true : false;
}
bool CServiceControl::stop()
{
std::string cmd = "systemctl stop cellframe-node.service > /dev/null";
int res = std::system(cmd.c_str());
return res == 0 ? true : false;
}
bool CServiceControl::restart()
{
std::string cmd = "systemctl restart cellframe-node.service > /dev/null";
int res = std::system(cmd.c_str());
return res == 0 ? true : false;
}
#endif
#ifdef __APPLE__
#include "service.h"
#include "../commands/AbstractCommand.h"
#include "macos_auth.h"
bool CServiceControl::enable()
{
int res = callSecScript("launchctl load -w /Library/LaunchDaemons/com.demlabs.cellframe-node.plist");
return res == 0 ? true : false;
}
bool CServiceControl::disable()
{
int res = callSecScript("launchctl unload -w /Library/LaunchDaemons/com.demlabs.cellframe-node.plist");
return res == 0 ? true : false;
}
unsigned int CServiceControl::serviceStatus()
{
unsigned int status = 0;
std::string cmd = std::string();
int res = std::system("launchctl print system/com.demlabs.cellframe-node > /dev/null");
if (res == 0)
{
status |= SERVICE_ENABLED;
}
cmd = "pgrep -x cellframe-node > /dev/null";
res = std::system(cmd.c_str());
if (res == 0)
{
status |= PROCESS_RUNNING;
}
return (unsigned int)status;
}
bool CServiceControl::start()
{
return enable();
}
bool CServiceControl::stop()
{
return disable();
}
bool CServiceControl::restart()
{
stop();
start();
return true;
}
#endif
#ifdef WIN32
#include "service.h"
#include "../commands/AbstractCommand.h"
#include <windows.h>
#include <windowsx.h>
#include <shlobj.h>
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
bool isProcessRunning(const TCHAR* const executableName) {
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
const auto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!Process32First(snapshot, &entry)) {
CloseHandle(snapshot);
return false;
}
do {
if (!_tcsicmp(entry.szExeFile, executableName)) {
CloseHandle(snapshot);
return true;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return false;
}
int runShellAdmin(std::string app, std::string cmd)
{
// Launch itself as admin
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.lpVerb = "runas";
sei.lpFile = app.c_str();
sei.lpParameters = cmd.c_str();
sei.hwnd = NULL;
sei.nShow = SW_HIDE;
if (!ShellExecuteEx(&sei))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_CANCELLED)
{
std::cout << "End user did not allow elevation" << std::endl;
return -1;
}
std::cout << "Exec failed" << dwError<< std::endl;
}
WaitForSingleObject(sei.hProcess,INFINITE);
long unsigned int rc;
GetExitCodeProcess(sei.hProcess, &rc);
return rc;
}
bool CServiceControl::enable()
{
auto nodebinpath = std::filesystem::path{variable_storage["NODE_BINARY_PATH"]}/"cellframe-node.exe";
std::string cmd = std::string("/Create /F /RL highest /SC onlogon /TR \"'") + nodebinpath.string() + "'\" /TN CellframeNode";
long unsigned int res = runShellAdmin("schtasks.exe", cmd);
return res == 0 ? true : false;
}
bool CServiceControl::disable()
{
std::string cmd = std::string("/Delete /TN CellframeNode /f");
long unsigned int res = runShellAdmin("schtasks.exe", cmd);
return res == 0 ? true : false;
}
unsigned int CServiceControl::serviceStatus()
{
unsigned int status = 0;
std::string cmd = std::string("schtasks /query /TN CellframeNode");
int res = std::system(cmd.c_str());
if (res == 0)
{
status |= SERVICE_ENABLED;
}
if (isProcessRunning("cellframe-node.exe"))
{
std::cout << "proc running" << std::endl;
status |= PROCESS_RUNNING;
}
return (unsigned)status;
}
bool CServiceControl::start()
{
std::string cmd = std::string("/run /TN CellframeNode");
long unsigned int res = runShellAdmin("schtasks.exe", cmd);
return res==0 ? true : false;
}
bool CServiceControl::stop()
{
std::string cmd = std::string("/IM cellframe-node.exe /F");
long unsigned int res = runShellAdmin("taskkill.exe", cmd);
return res==0 ? true : false;
}
bool CServiceControl::restart()
{
stop();
start();
return true;
}
#endif
\ No newline at end of file
Subproject commit b65cc33aa1ade90d593374ed82bf57c488cd98d1
prod_build/linux/debian/essentials
\ No newline at end of file
Subproject commit 293cc6c4038ea85c6819d9f847ad3802b02162b5
[Unit]
Description=Cellframe DiagTool
After=network-online.target
Wants=network-online.target
[Service]
WorkingDirectory=/opt/cellframe-node/
ExecStart=/opt/cellframe-node/bin/cellframe-diagtool &
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=always
User=root
Group=root
RestartSec=10
LogNamespace=cellframe
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_IPC_LOCK CAP_KILL CAP_LEASE CAP_MKNOD CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW CAP_SYS_NICE CAP_SYS_RAWIO CAP_SYSLOG CAP_WAKE_ALARM CAP_SYS_RESOURCE CAP_DAC_READ_SEARCH
[Install]
WantedBy=multi-user.target