From ce50a627be79ceb8e8c71c15f1a3ee1a05af3eca Mon Sep 17 00:00:00 2001 From: Alexis Date: Sat, 18 Aug 2018 17:54:20 +0200 Subject: [PATCH] refactor: move command execution into their own file --- include/modules/custom.hpp | 2 +- include/util/chrono.hpp | 122 ++++++++++++++++++------------------- include/util/command.hpp | 35 +++++++++++ include/util/json.hpp | 44 ++++++------- src/modules/custom.cpp | 41 ++----------- 5 files changed, 124 insertions(+), 120 deletions(-) create mode 100644 include/util/command.hpp diff --git a/include/modules/custom.hpp b/include/modules/custom.hpp index 6d987b2..79bd760 100644 --- a/include/modules/custom.hpp +++ b/include/modules/custom.hpp @@ -2,8 +2,8 @@ #include #include -#include #include "util/chrono.hpp" +#include "util/command.hpp" #include "ALabel.hpp" namespace waybar::modules { diff --git a/include/util/chrono.hpp b/include/util/chrono.hpp index f0ad9a7..09ac5b2 100644 --- a/include/util/chrono.hpp +++ b/include/util/chrono.hpp @@ -8,85 +8,85 @@ namespace waybar::chrono { - using namespace std::chrono; +using namespace std::chrono; - using clock = std::chrono::system_clock; - using duration = clock::duration; - using time_point = std::chrono::time_point; +using clock = std::chrono::system_clock; +using duration = clock::duration; +using time_point = std::chrono::time_point; - inline struct timespec to_timespec(time_point t) noexcept - { - long secs = duration_cast(t.time_since_epoch()).count(); - long nsc = duration_cast(t.time_since_epoch() % seconds(1)).count(); - return {secs, nsc}; - } +inline struct timespec to_timespec(time_point t) noexcept +{ + long secs = duration_cast(t.time_since_epoch()).count(); + long nsc = duration_cast(t.time_since_epoch() % seconds(1)).count(); + return {secs, nsc}; +} - inline time_point to_time_point(struct timespec t) noexcept - { - return time_point(duration_cast(seconds(t.tv_sec) + nanoseconds(t.tv_nsec))); - } +inline time_point to_time_point(struct timespec t) noexcept +{ + return time_point(duration_cast(seconds(t.tv_sec) + nanoseconds(t.tv_nsec))); +} } namespace waybar::util { - struct SleeperThread { - SleeperThread() = default; +struct SleeperThread { + SleeperThread() = default; - SleeperThread(std::function func) - : thread{[this, func] { - do { - func(); - } while (do_run); - }} - { - defined = true; - } - - SleeperThread& operator=(std::function func) - { - thread = std::thread([this, func] { + SleeperThread(std::function func) + : thread{[this, func] { do { func(); } while (do_run); - }); - defined = true; - return *this; - } + }} + { + defined = true; + } + + SleeperThread& operator=(std::function func) + { + thread = std::thread([this, func] { + do { + func(); + } while (do_run); + }); + defined = true; + return *this; + } - auto sleep_for(chrono::duration dur) - { - auto lock = std::unique_lock(mutex); - return condvar.wait_for(lock, dur); - } + auto sleep_for(chrono::duration dur) + { + auto lock = std::unique_lock(mutex); + return condvar.wait_for(lock, dur); + } - auto sleep_until(chrono::time_point time) - { - auto lock = std::unique_lock(mutex); - return condvar.wait_until(lock, time); - } + auto sleep_until(chrono::time_point time) + { + auto lock = std::unique_lock(mutex); + return condvar.wait_until(lock, time); + } - auto wake_up() - { + auto wake_up() + { + condvar.notify_all(); + } + + ~SleeperThread() + { + do_run = false; + if (defined) { condvar.notify_all(); + thread.join(); } + } - ~SleeperThread() - { - do_run = false; - if (defined) { - condvar.notify_all(); - thread.join(); - } - } - - private: - std::thread thread; - std::condition_variable condvar; - std::mutex mutex; - bool defined = false; - bool do_run = true; - }; +private: + std::thread thread; + std::condition_variable condvar; + std::mutex mutex; + bool defined = false; + bool do_run = true; +}; } diff --git a/include/util/command.hpp b/include/util/command.hpp new file mode 100644 index 0000000..80773cb --- /dev/null +++ b/include/util/command.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace waybar::util::command { + +struct cmd_res { + int exit_code; + std::string out; +}; + +inline struct cmd_res exec(const std::string cmd) +{ + FILE* fp(popen(cmd.c_str(), "r")); + if (!fp) { + return { -1, "" }; + } + + std::array buffer = {0}; + std::string output; + while (feof(fp) == 0) { + if (fgets(buffer.data(), 128, fp) != nullptr) { + output += buffer.data(); + } + } + + // Remove last newline + if (!output.empty() && output[output.length()-1] == '\n') { + output.erase(output.length()-1); + } + int exit_code = WEXITSTATUS(pclose(fp)); + return { exit_code, output }; +} + +} diff --git a/include/util/json.hpp b/include/util/json.hpp index 53b9345..6c2db95 100644 --- a/include/util/json.hpp +++ b/include/util/json.hpp @@ -4,31 +4,31 @@ namespace waybar::util { - struct JsonParser { +struct JsonParser { - JsonParser() - : _reader(_builder.newCharReader()) - {} + JsonParser() + : _reader(_builder.newCharReader()) + {} - Json::Value parse(const std::string data) - { - Json::Value root; - std::string err; - bool res = - _reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err); - if (!res) - throw std::runtime_error(err); - return root; - } + Json::Value parse(const std::string data) + { + Json::Value root; + std::string err; + bool res = + _reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err); + if (!res) + throw std::runtime_error(err); + return root; + } - ~JsonParser() - { - delete _reader; - } + ~JsonParser() + { + delete _reader; + } - private: - Json::CharReaderBuilder _builder; - Json::CharReader *_reader; - }; +private: + Json::CharReaderBuilder _builder; + Json::CharReader *_reader; +}; } diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index e192f80..d298c54 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -10,22 +10,8 @@ waybar::modules::Custom::Custom(std::string name, Json::Value config) thread_ = [this, interval] { bool can_update = true; if (config_["exec-if"]) { - auto pid = fork(); - int res = 0; - if (pid == 0) { - std::istringstream iss(config_["exec-if"].asString()); - std::vector av; - for (std::string s; iss >> s;) { - // Need to copy otherwise values are the same - char *str = new char[s.size() + 1]; - memcpy(str, s.c_str(), s.size() + 1); - av.push_back(str); - } - av.push_back(0); - execvp(av.front(), av.data()); - _exit(127); - } else if (pid > 0 && waitpid(pid, &res, 0) != -1 - && WEXITSTATUS(res) != 0) { + auto res = waybar::util::command::exec(config_["exec-if"].asString()); + if (res.exit_code != 0) { can_update = false; } } @@ -38,33 +24,16 @@ waybar::modules::Custom::Custom(std::string name, Json::Value config) auto waybar::modules::Custom::update() -> void { - std::array buffer = {0}; - std::string output; - std::shared_ptr fp(popen(config_["exec"].asCString(), "r"), pclose); - if (!fp) { - std::cerr << name_ + " can't exec " + config_["exec"].asString() << std::endl; - return; - } - - while (feof(fp.get()) == 0) { - if (fgets(buffer.data(), 128, fp.get()) != nullptr) { - output += buffer.data(); - } - } - - // Remove last newline - if (!output.empty() && output[output.length()-1] == '\n') { - output.erase(output.length()-1); - } + auto res = waybar::util::command::exec(config_["exec"].asString()); // Hide label if output is empty - if (output.empty()) { + if (res.out.empty() || res.exit_code != 0) { label_.hide(); label_.set_name(""); } else { label_.set_name("custom-" + name_); auto format = config_["format"] ? config_["format"].asString() : "{}"; - auto str = fmt::format(format, output); + auto str = fmt::format(format, res.out); label_.set_text(str); label_.set_tooltip_text(str); label_.show();