diff --git a/CMakeLists.txt b/CMakeLists.txt index 50be2e08..de6ad5d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,21 +2,22 @@ cmake_minimum_required(VERSION 3.16) project(HPCore) # Check for gold linker for faster linking time. -execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version OUTPUT_VARIABLE stdout ERROR_QUIET) +execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl -ldl,--version OUTPUT_VARIABLE stdout ERROR_QUIET) if("${stdout}" MATCHES "GNU gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") else() message(WARNING "GNU gold linker isn't available, using the default system linker.") endif() -add_definitions("-std=c++17") - +add_definitions("-std=c++17 -ldl") #-ldl to support printing stack trace at runtime +set(CMAKE_CXX_FLAGS_DEBUG "-g") # ensure debug symbols are added +set(CMAKE_BUILD_TYPE Debug) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY build) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY build) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build) # Using buildtype MinSizeRel for smaller build outputs. -set(CMAKE_BUILD_TYPE "MinSizeRel" FORCE) +#set(CMAKE_BUILD_TYPE "MinSizeRel" FORCE) link_directories(/usr/local/lib) @@ -36,6 +37,7 @@ target_link_libraries(hpsupport pthread crypto ssl + ${CMAKE_DL_LIBS} ) add_library(hpproc @@ -114,4 +116,4 @@ add_custom_target(docker COMMAND docker build -t hpcore:latest . ) set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE) -add_dependencies(docker hpcore) \ No newline at end of file +add_dependencies(docker hpcore) diff --git a/src/conf.cpp b/src/conf.cpp index 94bf8465..2ac1df0a 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -2,6 +2,8 @@ #include "conf.hpp" #include "crypto.hpp" #include "util.hpp" +#include +#include namespace conf { @@ -12,6 +14,15 @@ contract_ctx ctx; // Global configuration struct exposed to the application. contract_config cfg; +// provide a safe std::string overload for realpath +std::string realpath(std::string path) { + std::array buffer; + ::realpath(path.c_str(), buffer.data()); + buffer[PATH_MAX] = '\0'; + return buffer.data(); +} + + /** * Loads and initializes the contract config for execution. Must be called once during application startup. * @return 0 for success. -1 for failure. @@ -96,6 +107,8 @@ int create_contract() cfg.loglevel = "warn"; #endif cfg.loggers.emplace("console"); + + cfg.binary = ""; //Save the default settings into the config file. if (save_config() != 0) @@ -112,8 +125,14 @@ int create_contract() */ void set_contract_dir_paths(std::string basedir) { - if (basedir[basedir.size() - 1] == '/') - basedir = basedir.substr(0, basedir.size() - 1); + if (basedir == "") { + // this code branch will never execute the way main is currently coded, but it might change in future + std::cerr << "a contract directory must be specified\n"; + exit(1); + } + + // resolving the path through realpath will remove any trailing slash if present + basedir = realpath(basedir); ctx.contractDir = basedir; ctx.configDir = basedir + "/cfg"; @@ -178,9 +197,11 @@ int load_config() cfg.pubkeyhex = d["pubkeyhex"].GetString(); cfg.seckeyhex = d["seckeyhex"].GetString(); - cfg.binary = d["binary"].GetString(); - cfg.binargs = d["binargs"].GetString(); cfg.listenip = d["listenip"].GetString(); + + cfg.binary = realpath(d["binary"].GetString()); + cfg.binargs = d["binargs"].GetString(); + // Storing peers in unordered map keyed by the concatenated address:port and also saving address and port // seperately to retrieve easily when handling peer connections. @@ -401,8 +422,18 @@ int validate_config() } // Other required fields. - if (cfg.binary.empty() || cfg.listenip.empty() || - cfg.peerport == 0 || cfg.roundtime == 0 || cfg.pubport == 0 || cfg.loglevel.empty() || cfg.loggers.empty()) + + bool fields_missing = false; + + fields_missing |= cfg.binary.empty() && std::cout << "Missing cfg field: binary\n"; + fields_missing |= cfg.listenip.empty() && std::cout << "Missing cfg field: listenip\n"; + fields_missing |= cfg.peerport ==0 && std::cout << "Missing cfg field: peerport\n"; + fields_missing |= cfg.roundtime == 0 && std::cout << "Missing cfg field: roundtime\n"; + fields_missing |= cfg.pubport == 0 && std::cout << "Missing cfg field: pubport\n"; + fields_missing |= cfg.loglevel.empty() && std::cout << "Missing cfg field: loglevel\n"; + fields_missing |= cfg.loggers.empty() && std::cout << "Missing cfg field: loggers\n"; + + if (fields_missing) { std::cout << "Required configuration fields missing at " << ctx.configFile << std::endl; return -1; @@ -545,4 +576,4 @@ int is_schema_valid(const rapidjson::Document &d) return 0; } -} // namespace conf \ No newline at end of file +} // namespace conf