From d76f258a49fdd23d6c39cdc39a87e9a8bb46ff44 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Sep 2021 09:16:39 +0200 Subject: [PATCH 001/289] Added: Wait for terminal size properties to be available at start --- src/btop.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/btop.cpp b/src/btop.cpp index af2ffcf..3d70bf0 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -792,6 +792,18 @@ int main(int argc, char **argv) { } //? Calculate sizes of all boxes + { + int t_count = 0; + while (Term::width <= 0 or Term::width > 10000 or Term::height <= 0 or Term::height > 10000) { + sleep_ms(10); + Term::refresh(); + if (++t_count == 100) { + Global::exit_error_msg = "Failed to get size of terminal!"; + exit(1); + } + } + } + Config::presetsValid(Config::getS("presets")); if (Global::arg_preset >= 0) { Config::current_preset = min(Global::arg_preset, (int)Config::preset_list.size() - 1); @@ -808,8 +820,9 @@ int main(int argc, char **argv) { } - //? Print out box outlines Draw::calcSizes(); + + //? Print out box outlines cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush; From 65c62cef4780667d4e53b469f9ee6f8f6b0ee111 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Sep 2021 11:01:56 +0200 Subject: [PATCH 002/289] Changed: Stop second thread before updating terminal size variables --- src/btop.cpp | 3 ++- src/btop_tools.cpp | 8 +++++--- src/btop_tools.hpp | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 3d70bf0..4ce81fe 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -152,7 +152,7 @@ void argumentParser(const int& argc, char **argv) { void term_resize(bool force) { if (Global::resizing) return; atomic_lock lck(Global::resizing); - if (auto refreshed = Term::refresh(); refreshed or force) { + if (auto refreshed = Term::refresh(true); refreshed or force) { if (force and refreshed) force = false; } else return; @@ -160,6 +160,7 @@ void term_resize(bool force) { static const array all_boxes = {"cpu", "mem", "net", "proc"}; Global::resized = true; if (Runner::active) Runner::stop(); + Term::refresh(); Config::unlock(); auto boxes = Config::getS("shown_boxes"); diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index d801fe1..dc3a0bd 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -73,12 +73,14 @@ namespace Term { } } - bool refresh() { + bool refresh(bool only_check) { struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) return false; if (width != w.ws_col or height != w.ws_row) { - width = w.ws_col; - height = w.ws_row; + if (not only_check) { + width = w.ws_col; + height = w.ws_row; + } return true; } return false; diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index da4a784..eaf072c 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -114,7 +114,7 @@ namespace Term { const string sync_end = Fx::e + "?2026l"; //? End of terminal synchronized output //* Returns true if terminal has been resized and updates width and height - bool refresh(); + bool refresh(bool only_check=false); //* Returns an array with the lowest possible width, height with current box config auto get_min_size(const string& boxes) -> array; From 01dfd27ec4813c60efa424b01416e670e8598f5b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Sep 2021 11:59:10 +0200 Subject: [PATCH 003/289] Changed: Moved check for valid terminal dimensions to before platform init --- src/btop.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 4ce81fe..bf635c5 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -769,6 +769,19 @@ int main(int argc, char **argv) { Logger::info("Real tty detected: setting 16 color mode and using tty friendly graph symbols"); } + //? Check for valid terminal dimensions + { + int t_count = 0; + while (Term::width <= 0 or Term::width > 10000 or Term::height <= 0 or Term::height > 10000) { + sleep_ms(10); + Term::refresh(); + if (++t_count == 100) { + Global::exit_error_msg = "Failed to get size of terminal!"; + exit(1); + } + } + } + //? Platform dependent init and error check try { Shared::init(); @@ -793,18 +806,6 @@ int main(int argc, char **argv) { } //? Calculate sizes of all boxes - { - int t_count = 0; - while (Term::width <= 0 or Term::width > 10000 or Term::height <= 0 or Term::height > 10000) { - sleep_ms(10); - Term::refresh(); - if (++t_count == 100) { - Global::exit_error_msg = "Failed to get size of terminal!"; - exit(1); - } - } - } - Config::presetsValid(Config::getS("presets")); if (Global::arg_preset >= 0) { Config::current_preset = min(Global::arg_preset, (int)Config::preset_list.size() - 1); From a09ad063672c73743670603c28cd9c68732d5db4 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Sep 2021 12:51:04 +0200 Subject: [PATCH 004/289] Added: Check for empty percentage deques --- src/btop_draw.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 91a239a..380df65 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -472,21 +472,6 @@ namespace Cpu { vector core_graphs; vector temp_graphs; - unsigned long fastrand(void) { - static unsigned long x=123456789, y=362436069, z=521288629; - unsigned long t; - x ^= x << 16; - x ^= x >> 5; - x ^= x << 1; - - t = x; - x = y; - y = z; - z = t ^ x ^ y; - - return z; - } - string draw(const cpu_info& cpu, const bool force_redraw, const bool data_same) { if (Runner::stopping) return ""; if (force_redraw) redraw = true; @@ -504,6 +489,7 @@ namespace Cpu { const string& title_left = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_left_down : Symbols::title_left); const string& title_right = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_right_down : Symbols::title_right); static int bat_pos = 0, bat_len = 0; + if (cpu.cpu_percent.at("total").empty() or cpu.core_percent.at(0).empty() or (show_temps and cpu.temp.empty())) return ""; string out; out.reserve(width * height); From 4f3db691a58836c9045507e6e4e570db7d0ff0b3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Sep 2021 13:00:04 +0200 Subject: [PATCH 005/289] Update bug_report.md Fixed names --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fd2bf38..fd64412 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,7 +24,7 @@ assignees: aristocratos [If applicable, add screenshots to help explain your problem.] **Info (please complete the following information):** - - btop++ version: `bpytop -v` + - btop++ version: `btop -v` - Binary: [self compiled or static binary from release] - (If compiled) Compiler and version: - Architecture: [x86_64, aarch64, etc.] `uname -m` @@ -38,7 +38,7 @@ assignees: aristocratos contents of `~/.config/btop/btop.log` -(try running btop with `--debug` flag if error.log is empty) +(try running btop with `--debug` flag if btop.log is empty) **GDB Backtrace** From 73119d33b93ace942038ef7668e32f0d9e6ef413 Mon Sep 17 00:00:00 2001 From: zack kourouma Date: Mon, 27 Sep 2021 12:27:17 -0700 Subject: [PATCH 006/289] Add night-owl theme Inspired by sdras' VS Code theme: https://github.com/sdras/night-owl-vscode-theme --- themes/night-owl.theme | 92 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 themes/night-owl.theme diff --git a/themes/night-owl.theme b/themes/night-owl.theme new file mode 100644 index 0000000..de1b361 --- /dev/null +++ b/themes/night-owl.theme @@ -0,0 +1,92 @@ +#Bashtop theme with night-owl colors +#by zkourouma + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#ffffff", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#011627" + +# Main text color +theme[main_fg]="#d6deeb" + +# Title color for boxes +theme[title]="#ffffff" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#addb67" + +# Background color of selected items +theme[selected_bg]="#000000" + +# Foreground color of selected items +theme[selected_fg]="#ffeb95" + +# Color of inactive/disabled text +theme[inactive_fg]="#000000" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#585858" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#22da6e" + +# Cpu box outline color +theme[cpu_box]="#ffffff" + +# Memory/disks box outline color +theme[mem_box]="#ffffff" + +# Net up/down box outline color +theme[net_box]="#ffffff" + +# Processes box outline color +theme[proc_box]="#ffffff" + +# Box divider line and small boxes line color +theme[div_line]="#ffffff" + +# Temperature graph colors +theme[temp_start]="#82aaff" +theme[temp_mid]="#c792ea" +theme[temp_end]="#fb4394" + +# CPU graph colors +theme[cpu_start]="#22da6e" +theme[cpu_mid]="#addb67" +theme[cpu_end]="#ef5350" + +# Mem/Disk free meter +theme[free_start]="#4e5900" +theme[free_mid]="" +theme[free_end]="#22da6e" + +# Mem/Disk cached meter +theme[cached_start]="#82aaff" +theme[cached_mid]="" +theme[cached_end]="#82aaff" + +# Mem/Disk available meter +theme[available_start]="#addb67" +theme[available_mid]="" +theme[available_end]="#ffeb95" + +# Mem/Disk used meter +theme[used_start]="#ef5350" +theme[used_mid]="" +theme[used_end]="#ef5350" + +# Download graph colors +theme[download_start]="#3d4070" +theme[download_mid]="#6c71c4" +theme[download_end]="#a3a8f7" + +# Upload graph colors +theme[upload_start]="#701c45" +theme[upload_mid]="#c792ea" +theme[upload_end]="#c792ea" From a1fa532914a35364bf6790ead74da186a9b52c22 Mon Sep 17 00:00:00 2001 From: zack kourouma Date: Mon, 27 Sep 2021 18:40:26 -0700 Subject: [PATCH 007/289] More readable inactive/disabled text --- themes/night-owl.theme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/night-owl.theme b/themes/night-owl.theme index de1b361..7537fea 100644 --- a/themes/night-owl.theme +++ b/themes/night-owl.theme @@ -28,7 +28,7 @@ theme[selected_bg]="#000000" theme[selected_fg]="#ffeb95" # Color of inactive/disabled text -theme[inactive_fg]="#000000" +theme[inactive_fg]="#575656" # Color of text appearing on top of graphs, i.e uptime and current network graph scaling theme[graph_text]="#585858" From 1e842654791d6551c6467edcfea9b5a6c6d38604 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 08:54:22 +0200 Subject: [PATCH 008/289] Changed: Cpu temp values check for existing values --- src/btop_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 380df65..2ade665 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -489,7 +489,7 @@ namespace Cpu { const string& title_left = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_left_down : Symbols::title_left); const string& title_right = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_right_down : Symbols::title_right); static int bat_pos = 0, bat_len = 0; - if (cpu.cpu_percent.at("total").empty() or cpu.core_percent.at(0).empty() or (show_temps and cpu.temp.empty())) return ""; + if (cpu.cpu_percent.at("total").empty() or cpu.core_percent.at(0).empty() or (show_temps and cpu.temp.at(0).empty())) return ""; string out; out.reserve(width * height); From 683c57539a207b8990ef2293b4f9f390818f9332 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 09:05:16 +0200 Subject: [PATCH 009/289] Changed: Moved signal handler setup to later in init --- src/btop.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index bf635c5..84e8a97 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -650,13 +650,6 @@ int main(int argc, char **argv) { //? Call argument parser if launched with arguments if (argc > 1) argumentParser(argc, argv); - //? Setup signal handlers for CTRL-C, CTRL-Z, resume and terminal resize - std::atexit(_exit_handler); - std::signal(SIGINT, _signal_handler); - std::signal(SIGTSTP, _signal_handler); - std::signal(SIGCONT, _signal_handler); - std::signal(SIGWINCH, _signal_handler); - //? Setup paths for config, log and user themes for (const auto& env : {"XDG_CONFIG_HOME", "HOME"}) { if (std::getenv(env) != NULL and access(std::getenv(env), W_OK) != -1) { @@ -795,6 +788,13 @@ int main(int argc, char **argv) { Theme::updateThemes(); Theme::setTheme(); + //? Setup signal handlers for CTRL-C, CTRL-Z, resume and terminal resize + std::atexit(_exit_handler); + std::signal(SIGINT, _signal_handler); + std::signal(SIGTSTP, _signal_handler); + std::signal(SIGCONT, _signal_handler); + std::signal(SIGWINCH, _signal_handler); + //? Start runner thread Runner::thread_sem_init(); if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) { From dc914aa86de91b59e05ad09883e2c9073b6bef5c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 09:26:50 +0200 Subject: [PATCH 010/289] Fixed: Cpu percent cutting off above 1000 percent and added scaling with "k" prefix above 10'000 --- src/btop_draw.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 2ade665..0234d3a 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1414,7 +1414,12 @@ namespace Proc { } //? Common end of line string cpu_str = to_string(p.cpu_p); - if (p.cpu_p < 10 or p.cpu_p >= 100) cpu_str.resize(3); + if (p.cpu_p < 10 or (p.cpu_p >= 100 and p.cpu_p < 1000)) cpu_str.resize(3); + else if (p.cpu_p >= 10'000) { + cpu_str = to_string(p.cpu_p / 1000); + cpu_str.resize(3); + cpu_str += "k"; + } string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : ""); if (not mem_bytes) { double mem_p = clamp((double)p.mem * 100 / Shared::totalMem, 0.0, 100.0); From 8296c1a8d560081e78b03843d3053a8510534d20 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 13:08:45 +0200 Subject: [PATCH 011/289] Changed: UTF8 detection search if LANG is set but fails to set --- src/btop.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 84e8a97..4f69977 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -713,10 +713,8 @@ int main(int argc, char **argv) { //? Try to find and set a UTF-8 locale if (bool found = false; std::setlocale(LC_ALL, NULL) == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, NULL), "-", "")).ends_with("UTF8")) { - if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8")) { - if (std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) { - found = true; - } + if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8") and std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) { + found = true; } else { if (setenv("LANG", "", 1) == 0) { From 5fba94c96ced784cc210821e68d8a30d23ef1c53 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 16:37:02 +0200 Subject: [PATCH 012/289] v1.0.10 Bug fixes --- CHANGELOG.md | 16 ++++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7354364..10532f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v1.0.10 + +* Added: Wait for terminal size properties to be available at start + +* Changed: Stop second thread before updating terminal size variables + +* Changed: Moved check for valid terminal dimensions to before platform init + +* Added: Check for empty percentage deques + +* Changed: Cpu temp values check for existing values + +* Fixed: Cpu percent cutting off above 1000 percent and added scaling with "k" prefix above 10'000 + +* Fixed: Crash when rapidly resizing terminal at start + ## v1.0.9 * Added: ifstream check and try-catch for stod() in Tools::system_uptime() diff --git a/src/btop.cpp b/src/btop.cpp index 4f69977..0bd5ab8 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.9"; + const string Version = "1.0.10"; int coreCount; string overlay; From ff6d1d6eece2603c30113f66c323882f16c608e2 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 16:58:08 +0200 Subject: [PATCH 013/289] Changed: atomic_wait to use while loop instead of atom.wait() because of random stalls --- src/btop_tools.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index eaf072c..7bb0445 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -269,13 +269,13 @@ namespace Tools { string hostname(); string username(); -#if __GNUC__ < 11 +// #if __GNUC__ < 11 inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { while (atom.load() == old) sleep_ms(1); } inline void atomic_notify(const atomic& atom) noexcept { (void)atom; } -#else - inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { atom.wait(old); } - inline void atomic_notify(const atomic& atom) noexcept { atom.notify_all(); } -#endif +// #else +// inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { if (atom == old) atom.wait(old); } +// inline void atomic_notify(const atomic& atom) noexcept { atom.notify_all(); } +// #endif //* Waits for atomic to be false and sets it to true on construct, sets to false and notifies on destruct class atomic_lock { From 06cac6756df2c35fbf9b0885c1651c59c4ae0328 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 21:01:50 +0200 Subject: [PATCH 014/289] Fixed: Get real / mountpoint when running inside snap --- snap/snapcraft.yaml | 1 + src/linux/btop_collect.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index d41dbf4..0662db5 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -34,6 +34,7 @@ apps: environment: LC_ALL: C.UTF-8 LANG: C.UTF-8 + BTOP_SNAPPED: true plugs: - mount-observe - process-control diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 3c8b9fe..2e8671c 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -679,6 +679,7 @@ namespace Mem { auto& swap_disk = Config::getB("swap_disk"); auto& show_disks = Config::getB("show_disks"); auto& mem = current_mem; + static const bool snapped = (getenv("BTOP_SNAPPED") != NULL); mem.stats.at("swap_total") = 0; @@ -803,6 +804,14 @@ namespace Mem { std::error_code ec; diskread >> dev >> mountpoint >> fstype; + //? If running snapped, remove internal / mountpoint and replace /mnt with / to get correct device + if (snapped) { + if (mountpoint == "/") + continue; + else if (mountpoint == "/mnt") + mountpoint = "/"; + } + //? Match filter if not empty if (not filter.empty()) { bool match = v_contains(filter, mountpoint); From ab013b989b5f3419fa58764c3ffe580d382c5633 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 28 Sep 2021 21:54:51 +0200 Subject: [PATCH 015/289] Changed: Snap new / mountpoint detection --- src/linux/btop_collect.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 2e8671c..d8ea597 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -784,7 +784,8 @@ namespace Mem { for (string instr; diskread >> instr;) { if (not instr.starts_with('#')) { diskread >> instr; - if (not is_in(instr, "none", "swap")) fstab.push_back(instr); + if (snapped and instr == "/") fstab.push_back("/mnt"); + else if (not is_in(instr, "none", "swap")) fstab.push_back(instr); } diskread.ignore(SSmax, '\n'); } @@ -804,14 +805,6 @@ namespace Mem { std::error_code ec; diskread >> dev >> mountpoint >> fstype; - //? If running snapped, remove internal / mountpoint and replace /mnt with / to get correct device - if (snapped) { - if (mountpoint == "/") - continue; - else if (mountpoint == "/mnt") - mountpoint = "/"; - } - //? Match filter if not empty if (not filter.empty()) { bool match = v_contains(filter, mountpoint); @@ -829,7 +822,7 @@ namespace Mem { if (not disks.contains(mountpoint)) { disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename()}; if (disks.at(mountpoint).dev.empty()) disks.at(mountpoint).dev = dev; - if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); + if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" or (snapped and mountpoint == "/mnt") ? "root" : mountpoint); string devname = disks.at(mountpoint).dev.filename(); while (devname.size() >= 2) { if (fs::exists("/sys/block/" + devname + "/stat", ec) and access(string("/sys/block/" + devname + "/stat").c_str(), R_OK) == 0) { @@ -875,7 +868,8 @@ namespace Mem { //? Setup disks order in UI and add swap if enabled mem.disks_order.clear(); - if (disks.contains("/")) mem.disks_order.push_back("/"); + if (snapped and disks.contains("/mnt")) mem.disks_order.push_back("/mnt"); + else if (disks.contains("/")) mem.disks_order.push_back("/"); if (swap_disk and has_swap) { mem.disks_order.push_back("swap"); if (not disks.contains("swap")) disks["swap"] = {"", "swap"}; From b08f47383247a80ee4d7bf6dd9ff4e46c6ae0a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=9C=D0=B0?= =?UTF-8?q?=D1=80=D0=BA=D0=BE=D0=B2?= <13werwolf13@mail.ru> Date: Wed, 29 Sep 2021 09:50:16 +0500 Subject: [PATCH 016/289] add opensuse repo --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 6278b0a..7f5922f 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,22 @@ Also needs a UTF8 locale and a font that covers: make help ``` +**Binary release (from native os repo)** + +* **openSUSE** + * **Add repo** + ```bash + sudo zypper ar --refresh obs://home:Werwolf2517 home:Werwolf2517 + ``` + * **Refresh metadata** + ```bash + sudo zypper ref + ``` + * **Install package** + ```bash + sudo zypper in btop + ``` + ## Compilation Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary). From c70667e9e588336288c38d8bfef5da7cbb940ddb Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Sep 2021 08:16:49 +0200 Subject: [PATCH 017/289] Fixed: UTF8 set LANG and LC_ALL to empty before UTF8 search and fixed empty error msg on exit before signal handler init --- src/btop.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 0bd5ab8..7730d4b 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -712,20 +712,20 @@ int main(int argc, char **argv) { } //? Try to find and set a UTF-8 locale - if (bool found = false; std::setlocale(LC_ALL, NULL) == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, NULL), "-", "")).ends_with("UTF8")) { + if (bool found = false; std::setlocale(LC_ALL, "") == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) { if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8") and std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) { found = true; } else { - if (setenv("LANG", "", 1) == 0) { + if (setenv("LC_ALL", "", 1) == 0 and setenv("LANG", "", 1) == 0) { try { if (const auto loc = std::locale("").name(); not loc.empty() and loc != "*") { for (auto& l : ssplit(loc, ';')) { if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) { if (std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str()) != NULL) { found = true; + break; } - break; } } } @@ -738,16 +738,16 @@ int main(int argc, char **argv) { Logger::warning("No UTF-8 locale detected! Forcing start with --utf-force argument."); else if (not found) { Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it."; - exit(1); + clean_quit(1); } else - Logger::debug("Setting LC_ALL=" + (string)std::setlocale(LC_ALL, NULL)); + Logger::debug("Setting LC_ALL=" + (string)std::setlocale(LC_ALL, "")); } //? Initialize terminal and set options if (not Term::init()) { Global::exit_error_msg = "No tty detected!\nbtop++ needs an interactive shell to run."; - exit(1); + clean_quit(1); } if (Term::current_tty != "unknown") Logger::info("Running on " + Term::current_tty); @@ -768,7 +768,7 @@ int main(int argc, char **argv) { Term::refresh(); if (++t_count == 100) { Global::exit_error_msg = "Failed to get size of terminal!"; - exit(1); + clean_quit(1); } } } @@ -779,7 +779,7 @@ int main(int argc, char **argv) { } catch (const std::exception& e) { Global::exit_error_msg = "Exception in Shared::init() -> " + (string)e.what(); - exit(1); + clean_quit(1); } //? Update list of available themes and generate the selected theme From a49b8f999f7931fc4e2dda2f91b08f062bfc4e17 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Sep 2021 11:43:37 +0200 Subject: [PATCH 018/289] Changed: Init will continue if UTF-8 locale are detected even if it fails to set the locale --- src/btop.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 7730d4b..50a2bba 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -712,36 +712,47 @@ int main(int argc, char **argv) { } //? Try to find and set a UTF-8 locale - if (bool found = false; std::setlocale(LC_ALL, "") == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) { - if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8") and std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) { - found = true; + if (std::setlocale(LC_ALL, "") != NULL and str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) { + Logger::debug("Using locale " + (string)std::setlocale(LC_ALL, "")); + } + else { + string found; + if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8")) { + found = std::getenv("LANG"); + if (std::setlocale(LC_ALL, std::getenv("LANG")) == NULL) + Logger::warning("Failed to set locale " + (string)std::getenv("LANG") + " continuing anyway."); } - else { + if (found.empty() and std::getenv("LC_ALL") != NULL and str_to_upper(s_replace((string)std::getenv("LC_ALL"), "-", "")).ends_with("UTF8")) { + found = std::getenv("LC_ALL"); + if (std::setlocale(LC_ALL, std::getenv("LC_ALL")) == NULL) + Logger::warning("Failed to set locale " + (string)std::getenv("LC_ALL") + " continuing anyway."); + } + if (found.empty()) { if (setenv("LC_ALL", "", 1) == 0 and setenv("LANG", "", 1) == 0) { try { if (const auto loc = std::locale("").name(); not loc.empty() and loc != "*") { for (auto& l : ssplit(loc, ';')) { if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) { if (std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str()) != NULL) { - found = true; + found = l; break; } } } } } - catch (...) { found = false; } + catch (...) { found.clear(); } } } - if (not found and Global::utf_force) + if (found.empty() and Global::utf_force) Logger::warning("No UTF-8 locale detected! Forcing start with --utf-force argument."); - else if (not found) { + else if (found.empty()) { Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it."; clean_quit(1); } else - Logger::debug("Setting LC_ALL=" + (string)std::setlocale(LC_ALL, "")); + Logger::debug("Setting LC_ALL=" + found); } //? Initialize terminal and set options From a246c098cd6ca794b8c6a6680f6c50b22e1b0797 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Sep 2021 21:24:33 +0200 Subject: [PATCH 019/289] v1.0.11 Bug fixes --- CHANGELOG.md | 10 ++++++++++ src/btop.cpp | 29 +++++++++++++++-------------- src/btop_tools.cpp | 1 - src/btop_tools.hpp | 8 +------- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10532f5..9ec21b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.0.11 + +* Changed: atomic_wait to use while loop instead of wait() because of rare stall when a signal handler is triggered while waiting + +* Fixed: Get real / mountpoint when running inside snap + +* Fixed: UTF8 set LANG and LC_ALL to empty before UTF8 search and fixed empty error msg on exit before signal handler init + +* Changed: Init will continue with a warning if UTF-8 locale are detected and it fails to set the locale + ## v1.0.10 * Added: Wait for terminal size properties to be available at start diff --git a/src/btop.cpp b/src/btop.cpp index 50a2bba..02ca177 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.10"; + const string Version = "1.0.11"; int coreCount; string overlay; @@ -712,20 +712,21 @@ int main(int argc, char **argv) { } //? Try to find and set a UTF-8 locale - if (std::setlocale(LC_ALL, "") != NULL and str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) { + if (std::setlocale(LC_ALL, "") != NULL and not s_contains((string)std::setlocale(LC_ALL, ""), ";") + and str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) { Logger::debug("Using locale " + (string)std::setlocale(LC_ALL, "")); } else { string found; - if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8")) { - found = std::getenv("LANG"); - if (std::setlocale(LC_ALL, std::getenv("LANG")) == NULL) - Logger::warning("Failed to set locale " + (string)std::getenv("LANG") + " continuing anyway."); - } - if (found.empty() and std::getenv("LC_ALL") != NULL and str_to_upper(s_replace((string)std::getenv("LC_ALL"), "-", "")).ends_with("UTF8")) { - found = std::getenv("LC_ALL"); - if (std::setlocale(LC_ALL, std::getenv("LC_ALL")) == NULL) - Logger::warning("Failed to set locale " + (string)std::getenv("LC_ALL") + " continuing anyway."); + bool set_failure = false; + for (const auto loc_env : array{"LANG", "LC_ALL"}) { + if (std::getenv(loc_env) != NULL and str_to_upper(s_replace((string)std::getenv(loc_env), "-", "")).ends_with("UTF8")) { + found = std::getenv(loc_env); + if (std::setlocale(LC_ALL, found.c_str()) == NULL) { + set_failure = true; + Logger::warning("Failed to set locale " + found + " continuing anyway."); + } + } } if (found.empty()) { if (setenv("LC_ALL", "", 1) == 0 and setenv("LANG", "", 1) == 0) { @@ -733,8 +734,8 @@ int main(int argc, char **argv) { if (const auto loc = std::locale("").name(); not loc.empty() and loc != "*") { for (auto& l : ssplit(loc, ';')) { if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) { - if (std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str()) != NULL) { - found = l; + found = l.substr(l.find('=') + 1); + if (std::setlocale(LC_ALL, found.c_str()) != NULL) { break; } } @@ -751,7 +752,7 @@ int main(int argc, char **argv) { Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it."; clean_quit(1); } - else + else if (not set_failure) Logger::debug("Setting LC_ALL=" + found); } diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index dc3a0bd..c897b1b 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -329,7 +329,6 @@ namespace Tools { atomic_lock::~atomic_lock() { active_locks--; this->atom.store(false); - atomic_notify(this->atom); } string readfile(const std::filesystem::path& path, const string& fallback) { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 7bb0445..97e010a 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -269,15 +269,9 @@ namespace Tools { string hostname(); string username(); -// #if __GNUC__ < 11 inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { while (atom.load() == old) sleep_ms(1); } - inline void atomic_notify(const atomic& atom) noexcept { (void)atom; } -// #else -// inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { if (atom == old) atom.wait(old); } -// inline void atomic_notify(const atomic& atom) noexcept { atom.notify_all(); } -// #endif - //* Waits for atomic to be false and sets it to true on construct, sets to false and notifies on destruct + //* Waits for atomic to be false and sets it to true on construct, sets to false on destruct class atomic_lock { atomic& atom; bool not_true = false; From d226e6199f0a28c1ff1c7739f024e7dc6cb40a39 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 30 Sep 2021 22:48:03 +0200 Subject: [PATCH 020/289] Fixed: Cpu percent formatting if over 10'000 --- src/btop_draw.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 0234d3a..7406d15 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1418,6 +1418,7 @@ namespace Proc { else if (p.cpu_p >= 10'000) { cpu_str = to_string(p.cpu_p / 1000); cpu_str.resize(3); + if (cpu_str.ends_with('.')) cpu_str.pop_back(); cpu_str += "k"; } string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : ""); From 304b9af4e86d571530256668a449448ef194a9dd Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 30 Sep 2021 22:49:14 +0200 Subject: [PATCH 021/289] Fixed: Exception handling for faulty net download/upload speed --- src/linux/btop_collect.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index d8ea597..56730e7 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1007,7 +1007,10 @@ namespace Net { auto& saved_stat = net.at(iface).stat.at(dir); auto& bandwidth = net.at(iface).bandwidth.at(dir); - const uint64_t val = max((uint64_t)stoul(readfile(sys_file, "0")), saved_stat.last); + uint64_t val = saved_stat.last; + try { val = max((uint64_t)stoul(readfile(sys_file, "0")), val); } + catch (const std::invalid_argument&) {} + catch (const std::out_of_range&) {} //? Update speed, total and top values saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); From ae7b8b77ff31f66f2384a4de243e99a6cc5e63a3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 30 Sep 2021 22:51:05 +0200 Subject: [PATCH 022/289] Version bump --- src/btop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop.cpp b/src/btop.cpp index 02ca177..bef5a16 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.11"; + const string Version = "1.0.12"; int coreCount; string overlay; From 8d393b858feb7ddf8ebe044cfe0ffa5e3bf906ae Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 30 Sep 2021 22:56:14 +0200 Subject: [PATCH 023/289] Version > Release --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6278b0a..9cd7ba7 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux) ![Usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-yellow) ![c++20](https://img.shields.io/badge/cpp-c%2B%2B20-green) -![btop_version](https://img.shields.io/github/v/tag/aristocratos/btop?label=version) +![latest_release](https://img.shields.io/github/v/tag/aristocratos/btop?label=release) [![Donate](https://img.shields.io/badge/-Donate-yellow?logo=paypal)](https://paypal.me/aristocratos) [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos) From a15f961b2f0fe642ee61e2331c0d109fab7e9b05 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 1 Oct 2021 15:24:41 +0200 Subject: [PATCH 024/289] Updated Prerequisites --- README.md | 1 + src/btop_tools.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cd7ba7..1247fb5 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Also needs a UTF8 locale and a font that covers: * Unicode Block “Braille Patterns” U+2800 - U+28FF (Not needed in TTY mode or with graphs set to type: block or tty.) * Unicode Block “Geometric Shapes” U+25A0 - U+25FF * Unicode Block "Box Drawing" and "Block Elements" U+2500 - U+259F +* Unicode Block "General punctuation" U+2005 ### **Notice (Text rendering issues)** diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index c897b1b..bb75f2f 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -339,7 +339,8 @@ namespace Tools { for (string readstr; getline(file, readstr); out += readstr); } catch (const std::exception& e) { - throw std::runtime_error("readfile() : Exception when reading " + (string)path + " : " + e.what()); + Logger::error("readfile() : Exception when reading " + (string)path + " : " + e.what()); + return fallback; } return (out.empty() ? fallback : out); } From 3a4a9d09b59cee6ee1d60669a1bc885d7c8a40fa Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 1 Oct 2021 20:46:05 +0200 Subject: [PATCH 025/289] v1.0.12 Bug fixes --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec21b0..6e98539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.0.12 + +* Fixed: Exception handling for faulty net download/upload speed + +* Fixed: Cpu percent formatting if over 10'000 + ## v1.0.11 * Changed: atomic_wait to use while loop instead of wait() because of rare stall when a signal handler is triggered while waiting From 585bb7bb1e31e7193b8d749ac9b999a1c9870f52 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 2 Oct 2021 22:39:45 +0200 Subject: [PATCH 026/289] Changed: Graph empty symbol is now regular whitespace --- src/btop_draw.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 7406d15..6a8cf68 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -43,42 +43,42 @@ namespace Symbols { const unordered_flat_map> graph_symbols = { { "braille_up", { - " ", "⢀", "⢠", "⢰", "⢸", + " ", "⢀", "⢠", "⢰", "⢸", "⡀", "⣀", "⣠", "⣰", "⣸", "⡄", "⣄", "⣤", "⣴", "⣼", "⡆", "⣆", "⣦", "⣶", "⣾", "⡇", "⣇", "⣧", "⣷", "⣿" }}, {"braille_down", { - " ", "⠈", "⠘", "⠸", "⢸", + " ", "⠈", "⠘", "⠸", "⢸", "⠁", "⠉", "⠙", "⠹", "⢹", "⠃", "⠋", "⠛", "⠻", "⢻", "⠇", "⠏", "⠟", "⠿", "⢿", "⡇", "⡏", "⡟", "⡿", "⣿" }}, {"block_up", { - " ", "▗", "▗", "▐", "▐", + " ", "▗", "▗", "▐", "▐", "▖", "▄", "▄", "▟", "▟", "▖", "▄", "▄", "▟", "▟", "▌", "▙", "▙", "█", "█", "▌", "▙", "▙", "█", "█" }}, {"block_down", { - " ", "▝", "▝", "▐", "▐", + " ", "▝", "▝", "▐", "▐", "▘", "▀", "▀", "▜", "▜", "▘", "▀", "▀", "▜", "▜", "▌", "▛", "▛", "█", "█", "▌", "▛", "▛", "█", "█" }}, {"tty_up", { - " ", "░", "░", "▒", "▒", + " ", "░", "░", "▒", "▒", "░", "░", "▒", "▒", "█", "░", "▒", "▒", "▒", "█", "▒", "▒", "▒", "█", "█", "▒", "█", "█", "█", "█" }}, {"tty_down", { - " ", "░", "░", "▒", "▒", + " ", "░", "░", "▒", "▒", "░", "░", "▒", "▒", "█", "░", "▒", "▒", "▒", "█", "▒", "▒", "▒", "█", "█", @@ -431,7 +431,7 @@ namespace Draw { //? Populate the two switching graph vectors and fill empty space if data size < width for (const int& i : iota(0, height * 2)) { if (tty_mode and i % 2 != current) continue; - graphs[(i % 2 != 0)].push_back((value_width < width) ? ((height == 1) ? Mv::r(1) : " "s) * (width - value_width) : ""); + graphs[(i % 2 != 0)].push_back((value_width < width) ? ((height == 1) ? Mv::r(1) : " "s) * (width - value_width) : ""); } if (data.size() == 0) return; this->_create(data, data_offset); @@ -444,6 +444,7 @@ namespace Draw { if (not tty_mode) current = not current; for (const int& i : iota(0, height)) { if (graphs.at(current).at(i).at(1) == '[') graphs.at(current).at(i).erase(0, 4); + else if (graphs.at(current).at(i).at(0) == ' ') graphs.at(current).at(i).erase(0, 1); else graphs.at(current).at(i).erase(0, 3); } this->_create(data, (int)data.size() - 1); From f9505a425d3d4eac5bb11009eb8ab8c841066ba5 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 2 Oct 2021 22:43:49 +0200 Subject: [PATCH 027/289] v1.0.13 Better symbol compatibility --- CHANGELOG.md | 4 ++++ README.md | 3 +-- src/btop.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e98539..b4fec24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.13 + +* Changed: Graph empty symbol is now regular whitespace + ## v1.0.12 * Fixed: Exception handling for faulty net download/upload speed diff --git a/README.md b/README.md index db5f46e..3d4e2f6 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,6 @@ Also needs a UTF8 locale and a font that covers: * Unicode Block “Braille Patterns” U+2800 - U+28FF (Not needed in TTY mode or with graphs set to type: block or tty.) * Unicode Block “Geometric Shapes” U+25A0 - U+25FF * Unicode Block "Box Drawing" and "Block Elements" U+2500 - U+259F -* Unicode Block "General punctuation" U+2005 ### **Notice (Text rendering issues)** @@ -213,7 +212,7 @@ Also needs a UTF8 locale and a font that covers: * **openSUSE** * **Add repo** ```bash - sudo zypper ar --refresh obs://home:Werwolf2517 home:Werwolf2517 + sudo zypper ar --refresh obs://home:Werwolf2517 home:Werwolf2517 ``` * **Refresh metadata** ```bash diff --git a/src/btop.cpp b/src/btop.cpp index bef5a16..64b925d 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.12"; + const string Version = "1.0.13"; int coreCount; string overlay; From 665a8b136614a2b0664ced8a6dd6ccee8b8ddc58 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 00:27:15 +0530 Subject: [PATCH 028/289] Add 'info' option in help Might be helpful when more platforms are compatible --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e6b4d44..f8ec78a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Ver override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") ifneq ($(QUIET),true) - override PRE := info + override PRE := info info-quiet override QUIET := false else override PRE := info-quiet @@ -111,8 +111,6 @@ info: @printf "\033[1;95mCXXFLAGS \033[1;92m+| \033[0;37m\$$(\033[92mREQFLAGS\033[37m) \$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n" @printf "\033[1;95mLDFLAGS \033[1;92m+| \033[0;37m\$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n" - @printf "\n\033[1;92mBuilding btop++ \033[93m(\033[97mv$(BTOP_VERSION)\033[93m)\033[0m\n" - info-quiet: @printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n" @@ -128,6 +126,7 @@ help: @printf " install Install btop++ to \$$PREFIX ($(PREFIX))\n" @printf " setuid Set installed binary owner/group to \$$SU_USER/\$$SU_GROUP ($(SU_USER)/$(SU_GROUP)) and set SUID bit\n" @printf " uninstall Uninstall btop++ from \$$PREFIX\n" + @printf " info Display information about Environment,compiler and linker flags\n" #? Make the Directories directories: From 02fcb8c34a18f96574f05750e32c7cf861341e20 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 5 Oct 2021 09:18:04 +0200 Subject: [PATCH 029/289] Changed: Total system memory is checked at every update instead of once at start --- src/btop_draw.cpp | 10 +++++---- src/btop_shared.hpp | 5 +++-- src/linux/btop_collect.cpp | 44 ++++++++++++++++++++++---------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 6a8cf68..d290832 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -698,6 +698,7 @@ namespace Mem { auto& tty_mode = Config::getB("tty_mode"); auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_mem")); auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6); + auto totalMem = Mem::get_totalMem(); string out; out.reserve(height * width); @@ -791,7 +792,7 @@ namespace Mem { string up = (graph_height >= 2 ? Mv::l(mem_width - 2) + Mv::u(graph_height - 1) : ""); bool big_mem = mem_width > 21; - out += Mv::to(y + 1, x + 2) + Theme::c("title") + Fx::b + "Total:" + rjust(floating_humanizer(Shared::totalMem), mem_width - 9) + Fx::ub + Theme::c("main_fg"); + out += Mv::to(y + 1, x + 2) + Theme::c("title") + Fx::b + "Total:" + rjust(floating_humanizer(totalMem), mem_width - 9) + Fx::ub + Theme::c("main_fg"); vector comb_names (mem_names.begin(), mem_names.end()); if (show_swap and has_swap and not swap_disk) comb_names.insert(comb_names.end(), swap_names.begin(), swap_names.end()); for (auto name : comb_names) { @@ -1107,6 +1108,7 @@ namespace Proc { const int y = show_detailed ? Proc::y + 8 : Proc::y; const int height = show_detailed ? Proc::height - 8 : Proc::height; const int select_max = show_detailed ? Proc::select_max - 8 : Proc::select_max; + auto totalMem = Mem::get_totalMem(); int numpids = Proc::numpids; if (force_redraw) redraw = true; string out; @@ -1312,7 +1314,7 @@ namespace Proc { if (item_fit >= 8) out += cjust(to_string(detailed.entry.p_nice), item_width); - const double mem_p = (double)detailed.mem_bytes.back() * 100 / Shared::totalMem; + const double mem_p = (double)detailed.mem_bytes.back() * 100 / totalMem; string mem_str = to_string(mem_p); mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4)); out += Mv::to(d_y + 4, d_x + 1) + Theme::c("title") + Fx::b + rjust((item_fit > 4 ? "Memory: " : "M:") + mem_str + "% ", (d_width / 3) - 2) @@ -1370,7 +1372,7 @@ namespace Proc { if (proc_colors) { end = Theme::c("main_fg") + Fx::ub; array colors; - for (int i = 0; int v : {(int)round(p.cpu_p), (int)round(p.mem * 100 / Shared::totalMem), (int)p.threads / 3}) { + for (int i = 0; int v : {(int)round(p.cpu_p), (int)round(p.mem * 100 / totalMem), (int)p.threads / 3}) { if (proc_gradient) { int val = (min(v, 100) + 100) - calc * 100 / select_max; if (val < 100) colors[i++] = Theme::g("proc_color").at(max(0, val)); @@ -1424,7 +1426,7 @@ namespace Proc { } string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : ""); if (not mem_bytes) { - double mem_p = clamp((double)p.mem * 100 / Shared::totalMem, 0.0, 100.0); + double mem_p = clamp((double)p.mem * 100 / totalMem, 0.0, 100.0); mem_str = to_string(mem_p); if (mem_str.size() < 4) mem_str = "0"; else mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4)); diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 4d0f323..832208c 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -70,8 +70,6 @@ namespace Shared { void init(); extern long coreCount, page_size, clk_tck; - extern int totalMem_len; - extern uint64_t totalMem; } @@ -149,6 +147,9 @@ namespace Mem { vector disks_order; }; + //?* Get total system memory + uint64_t get_totalMem(); + //* Collect mem & disks stats auto collect(const bool no_update=false) -> mem_info&; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 56730e7..ea36b89 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -78,9 +78,7 @@ namespace Mem { namespace Shared { fs::path procPath, passwd_path; - uint64_t totalMem; long pageSize, clkTck, coreCount; - int totalMem_len; void init() { @@ -110,17 +108,7 @@ namespace Shared { clkTck = 100; Logger::warning("Could not get system clock ticks per second. Defaulting to 100, processes cpu usage might be incorrect."); } - - ifstream meminfo(Shared::procPath / "meminfo"); - if (meminfo.good()) { - meminfo.ignore(SSmax, ':'); - meminfo >> totalMem; - totalMem_len = to_string(totalMem).size(); - totalMem <<= 10; - } - if (not meminfo.good() or totalMem == 0) - throw std::runtime_error("Could not get total memory size from /proc/meminfo"); - + //? Init for namespace Cpu if (not fs::exists(Cpu::freq_path) or access(Cpu::freq_path.c_str(), R_OK) == -1) Cpu::freq_path.clear(); Cpu::current_cpu.core_percent.insert(Cpu::current_cpu.core_percent.begin(), Shared::coreCount, {}); @@ -673,11 +661,26 @@ namespace Mem { mem_info current_mem {}; + uint64_t get_totalMem() { + ifstream meminfo(Shared::procPath / "meminfo"); + int64_t totalMem; + if (meminfo.good()) { + meminfo.ignore(SSmax, ':'); + meminfo >> totalMem; + totalMem <<= 10; + } + if (not meminfo.good() or totalMem == 0) + throw std::runtime_error("Could not get total memory size from /proc/meminfo"); + + return totalMem; + } + auto collect(const bool no_update) -> mem_info& { if (Runner::stopping or (no_update and not current_mem.percent.at("used").empty())) return current_mem; auto& show_swap = Config::getB("show_swap"); auto& swap_disk = Config::getB("swap_disk"); auto& show_disks = Config::getB("show_disks"); + auto totalMem = get_totalMem(); auto& mem = current_mem; static const bool snapped = (getenv("BTOP_SNAPPED") != NULL); @@ -714,7 +717,7 @@ namespace Mem { meminfo.ignore(SSmax, '\n'); } if (not got_avail) mem.stats.at("available") = mem.stats.at("free") + mem.stats.at("cached"); - mem.stats.at("used") = Shared::totalMem - mem.stats.at("available"); + mem.stats.at("used") = totalMem - mem.stats.at("available"); if (mem.stats.at("swap_total") > 0) mem.stats.at("swap_used") = mem.stats.at("swap_total") - mem.stats.at("swap_free"); } else @@ -724,7 +727,7 @@ namespace Mem { //? Calculate percentages for (const auto& name : mem_names) { - mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / Shared::totalMem)); + mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / totalMem)); while (cmp_greater(mem.percent.at(name).size(), width * 2)) mem.percent.at(name).pop_front(); } @@ -1259,7 +1262,7 @@ namespace Proc { detailed.memory = floating_humanizer(detailed.entry.mem); } if (detailed.first_mem == -1 or detailed.first_mem < detailed.mem_bytes.back() / 2 or detailed.first_mem > detailed.mem_bytes.back() * 4) { - detailed.first_mem = min((uint64_t)detailed.mem_bytes.back() * 2, Shared::totalMem); + detailed.first_mem = min((uint64_t)detailed.mem_bytes.back() * 2, Mem::get_totalMem()); redraw = true; } @@ -1324,6 +1327,9 @@ namespace Proc { else { should_filter = true; + auto totalMem = Mem::get_totalMem(); + int totalMem_len = to_string(totalMem >> 10).size(); + //? Update uid_user map if /etc/passwd changed since last run if (not Shared::passwd_path.empty() and fs::last_write_time(Shared::passwd_path) != passwd_time) { string r_uid, r_user; @@ -1460,8 +1466,8 @@ namespace Proc { next_x = 24; continue; case 24: //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~20x) - if (cmp_greater(short_str.size(), Shared::totalMem_len)) - new_proc.mem = Shared::totalMem; + if (cmp_greater(short_str.size(), totalMem_len)) + new_proc.mem = totalMem; else new_proc.mem = stoull(short_str) * Shared::pageSize; } @@ -1477,7 +1483,7 @@ namespace Proc { if (x-offset < 24) continue; //? Get RSS memory from /proc/[pid]/statm if value from /proc/[pid]/stat looks wrong - if (new_proc.mem >= Shared::totalMem) { + if (new_proc.mem >= totalMem) { pread.open(d.path() / "statm"); if (not pread.good()) continue; pread.ignore(SSmax, ' '); From 76536c523097398e33fa4b0a64788b8a88a5d073 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 14:05:06 +0530 Subject: [PATCH 030/289] Track .github directory --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3817f1b..fc1994b 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,8 @@ stage/ build bin btop -.*/ \ No newline at end of file +.*/ + + +#do not ignore .github directory +!.github \ No newline at end of file From 50a434db10adb1721e2bf5a1b007707a6c17b6da Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 14:12:36 +0530 Subject: [PATCH 031/289] Add workflow for continuous build --- .github/workflows/continuous-build.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/continuous-build.yml diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml new file mode 100644 index 0000000..d8d8f80 --- /dev/null +++ b/.github/workflows/continuous-build.yml @@ -0,0 +1,22 @@ +name: Continuous Build + +on: + push + +jobs: + build: + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: update system + run: | + sudo apt update && sudo apt upgrade -y + - name: Build + run: make -j `nproc` + + - uses: actions/upload-artifact@v2 + with: + name: Upload built binary + path: 'bin/btop' From 72ed836144894d6e5f96f91887c4bbdd4601e159 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 16:03:41 +0530 Subject: [PATCH 032/289] Use ubuntu 21.04 container --- .github/workflows/continuous-build.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index d8d8f80..5fa8bff 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -6,16 +6,18 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest + container: ubuntu:21.04 steps: - uses: actions/checkout@v2 - - name: update system + - name: Install g++, make run: | - sudo apt update && sudo apt upgrade -y + apt update && \ + apt install coreutils sed git build-essential gcc-11 g++-11 -y - name: Build - run: make -j `nproc` - + run: make + - uses: actions/upload-artifact@v2 with: name: Upload built binary From 28ab3d9c1a4ba108f6b4798c6c776da463fe9cfe Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 16:23:22 +0530 Subject: [PATCH 033/289] Rename binary to git hash --- .github/workflows/continuous-build.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 5fa8bff..7007a64 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -11,14 +11,17 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install g++, make + - name: Install build tools run: | apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y - - name: Build - run: make + - name: Compile + run: | + make STATIC=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop bin/btop-$GIT_HASH - uses: actions/upload-artifact@v2 with: - name: Upload built binary - path: 'bin/btop' + name: Btop + path: 'bin/btop-*' \ No newline at end of file From 4dd856760d30fac1edccd0e01f8a7dce2ac4c143 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 16:26:22 +0530 Subject: [PATCH 034/289] fix (GIT_DISCOVERY_ACROSS_FILESYSTEM not set) --- .github/workflows/continuous-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 7007a64..811425b 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -18,6 +18,7 @@ jobs: - name: Compile run: | make STATIC=true + git init GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") mv bin/btop bin/btop-$GIT_HASH From c84dcf396a79ac72abbf87fda099bc18e71f9fe1 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 16:43:31 +0530 Subject: [PATCH 035/289] Add Linux CI badge --- .github/workflows/continuous-build.yml | 4 +-- README.md | 40 +++++++++++++++++--------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 811425b..91b28ca 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,4 +1,4 @@ -name: Continuous Build +name: Continuous Build Linux on: push @@ -24,5 +24,5 @@ jobs: - uses: actions/upload-artifact@v2 with: - name: Btop + name: btop path: 'bin/btop-*' \ No newline at end of file diff --git a/README.md b/README.md index 3d4e2f6..4ffbe6e 100644 --- a/README.md +++ b/README.md @@ -12,24 +12,36 @@ [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos) [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) +[![Continuous Build](https://github.com/aristocratos/btop/actions/workflows/continuous-build.yml/badge.svg)](https://github.com/aristocratos/btop/actions) ## Index -* [News](#news) -* [Documents](#documents) -* [Description](#description) -* [Features](#features) -* [Themes](#themes) -* [Support and funding](#support-and-funding) -* [Prerequisites](#prerequisites) (Read this if you are having issues!) -* [Screenshots](#screenshots) -* [Keybindings](#help-menu) -* [Installation](#installation) -* [Manual compilation](#compilation) -* [Install the snap](#install-the-snap) -* [Configurability](#configurability) -* [License](#license) +- [!btop++](#) + - [Index](#index) + - [News](#news) + - [Under development](#under-development) + - [18 September 2021](#18-september-2021) + - [5 May 2021](#5-may-2021) + - [Documents](#documents) + - [Description](#description) + - [Features](#features) + - [Themes](#themes) + - [Support and funding](#support-and-funding) + - [Prerequisites](#prerequisites) + - [**Notice (Text rendering issues)**](#notice-text-rendering-issues) + - [Screenshots](#screenshots) + - [Main UI showing details for a selected process](#main-ui-showing-details-for-a-selected-process) + - [Main UI in TTY mode](#main-ui-in-tty-mode) + - [Main UI with custom options](#main-ui-with-custom-options) + - [Main-menu](#main-menu) + - [Options-menu](#options-menu) + - [Help-menu](#help-menu) + - [Installation](#installation) + - [Compilation](#compilation) + - [Install the snap](#install-the-snap) + - [Command line options](#command-line-options) + - [LICENSE](#license) ## News From 0c7357d4056514f62b1c669e782be0f6b46d2436 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 17:31:10 +0530 Subject: [PATCH 036/289] Fix README.md --- README.md | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 4ffbe6e..b37b268 100644 --- a/README.md +++ b/README.md @@ -13,35 +13,26 @@ [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos) [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) [![Continuous Build](https://github.com/aristocratos/btop/actions/workflows/continuous-build.yml/badge.svg)](https://github.com/aristocratos/btop/actions) + + ## Index -- [!btop++](#) - - [Index](#index) - - [News](#news) - - [Under development](#under-development) - - [18 September 2021](#18-september-2021) - - [5 May 2021](#5-may-2021) - - [Documents](#documents) - - [Description](#description) - - [Features](#features) - - [Themes](#themes) - - [Support and funding](#support-and-funding) - - [Prerequisites](#prerequisites) - - [**Notice (Text rendering issues)**](#notice-text-rendering-issues) - - [Screenshots](#screenshots) - - [Main UI showing details for a selected process](#main-ui-showing-details-for-a-selected-process) - - [Main UI in TTY mode](#main-ui-in-tty-mode) - - [Main UI with custom options](#main-ui-with-custom-options) - - [Main-menu](#main-menu) - - [Options-menu](#options-menu) - - [Help-menu](#help-menu) - - [Installation](#installation) - - [Compilation](#compilation) - - [Install the snap](#install-the-snap) - - [Command line options](#command-line-options) - - [LICENSE](#license) +* [News](#news) +* [Documents](#documents) +* [Description](#description) +* [Features](#features) +* [Themes](#themes) +* [Support and funding](#support-and-funding) +* [Prerequisites](#prerequisites) (Read this if you are having issues!) +* [Screenshots](#screenshots) +* [Keybindings](#help-menu) +* [Installation](#installation) +* [Manual compilation](#compilation) +* [Install the snap](#install-the-snap) +* [Configurability](#configurability) +* [License](#license) ## News From c4f8cf22cb989f87da2e0ebee0bbf961fc13cec6 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 17:46:08 +0530 Subject: [PATCH 037/289] Add aarch64 to workflow --- .github/workflows/continuous-build.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 91b28ca..f31ed9d 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -15,12 +15,19 @@ jobs: run: | apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y - - name: Compile + apt install g++-11-aarch64-linux-gnu -y + - name: Resolve git hash run: | - make STATIC=true git init GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop bin/btop-$GIT_HASH + - name: Compile x86_64 + run: | + make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true + mv bin/btop bin/btop-x86_64-$GIT_HASH + - name: Compile aarch64 + run: | + make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true + mv bin/btop bin/btop-aarch64-$GIT_HASH - uses: actions/upload-artifact@v2 with: From 0b0022859849d057a411cae7fa7282bb6ac227b9 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:23:12 +0530 Subject: [PATCH 038/289] Add distclean after builds --- .github/workflows/continuous-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index f31ed9d..3bf81a5 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -24,11 +24,12 @@ jobs: run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true mv bin/btop bin/btop-x86_64-$GIT_HASH + make distclean - name: Compile aarch64 run: | make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true mv bin/btop bin/btop-aarch64-$GIT_HASH - + make distclean - uses: actions/upload-artifact@v2 with: name: btop From 2e058b171a1f396e31c33da1a7b1e634522f1702 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:25:57 +0530 Subject: [PATCH 039/289] Store built binaries in 'multiarch_bin' --- .github/workflows/continuous-build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 3bf81a5..e4ef344 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -20,17 +20,18 @@ jobs: run: | git init GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mkdir multiarch_bin - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - mv bin/btop bin/btop-x86_64-$GIT_HASH + mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH make distclean - name: Compile aarch64 run: | make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - mv bin/btop bin/btop-aarch64-$GIT_HASH + mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH make distclean - uses: actions/upload-artifact@v2 with: name: btop - path: 'bin/btop-*' \ No newline at end of file + path: 'multiarch_bin/btop-*' \ No newline at end of file From 8952694b04461d7f5219f910f4b3bfd33847ddf4 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:31:53 +0530 Subject: [PATCH 040/289] Fix git hash in binary name --- .github/workflows/continuous-build.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index e4ef344..36bbbbe 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -16,20 +16,15 @@ jobs: apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y apt install g++-11-aarch64-linux-gnu -y - - name: Resolve git hash - run: | - git init - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mkdir multiarch_bin - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH + mv bin/btop multiarch_bin/btop-x86_64-$(git rev-parse --short "$GITHUB_SHA") make distclean - name: Compile aarch64 run: | make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH + mv bin/btop multiarch_bin/btop-aarch64-$(git rev-parse --short "$GITHUB_SHA") make distclean - uses: actions/upload-artifact@v2 with: From 7ab51dae4b1e397ec9a8eff71f26c8b2e60fe6a9 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:34:51 +0530 Subject: [PATCH 041/289] create 'multiarch_bin' directory --- .github/workflows/continuous-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 36bbbbe..f684558 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -16,6 +16,7 @@ jobs: apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y apt install g++-11-aarch64-linux-gnu -y + mkdir -p multiarch_bin - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true From 0fedb9efc317457f1bb762ee8950e95723e5b31f Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:54:51 +0530 Subject: [PATCH 042/289] Add more architectures to Continuous build --- .github/workflows/continuous-build.yml | 49 ++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index f684558..4a70f07 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -15,18 +15,61 @@ jobs: run: | apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y - apt install g++-11-aarch64-linux-gnu -y + apt install -y g++-11-aarch64-linux-gnu g++-11-i686-linux-gnu \ + g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-riscv64-linux-gnu \ + g++-11-sparc64-linux-gnu + mkdir -p multiarch_bin + - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - mv bin/btop multiarch_bin/btop-x86_64-$(git rev-parse --short "$GITHUB_SHA") + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH make distclean + + - name: Compile i686 + run: | + make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-i686-$GIT_HASH + make distclean + - name: Compile aarch64 run: | make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - mv bin/btop multiarch_bin/btop-aarch64-$(git rev-parse --short "$GITHUB_SHA") + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH make distclean + + - name: Compile armel + run: | + make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-armel-$GIT_HASH + make distclean + + - name: Compile armhf + run: | + make CXX=arm-linux-gnueabihf-g++-11 ARCH=armhf STATIC=true QUIET=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-armhf-$GIT_HASH + make distclean + + - name: Compile riscv64 + run: | + make CXX=riscv64-linux-gnu-g++-11 ARCH=riscv64 STATIC=true QUIET=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-riscv64-$GIT_HASH + make distclean + + - name: Compile sparc64 + run: | + make CXX=sparc64-linux-gnu-g++-11 ARCH=sparc64 STATIC=true QUIET=true + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop multiarch_bin/btop-sparc64-$GIT_HASH + make distclean + - uses: actions/upload-artifact@v2 with: name: btop From d311651f5f6eb14fa002d63b7d93e101fb88f534 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 18:58:06 +0530 Subject: [PATCH 043/289] Fix git fix Stopping at filesystem boundary --- .github/workflows/continuous-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 4a70f07..1459524 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -24,6 +24,7 @@ jobs: - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true + git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH make distclean From 222c387d40eb99b06273ee9ae7a97990225d8ef4 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 19:26:15 +0530 Subject: [PATCH 044/289] Fix riscv64 cross compiler package name Move git init command --- .github/workflows/continuous-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 1459524..abc19cf 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -16,15 +16,16 @@ jobs: apt update && \ apt install coreutils sed git build-essential gcc-11 g++-11 -y apt install -y g++-11-aarch64-linux-gnu g++-11-i686-linux-gnu \ - g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-riscv64-linux-gnu \ + g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-11-riscv64-linux-gnu \ g++-11-sparc64-linux-gnu mkdir -p multiarch_bin + git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] + - name: Compile x86_64 run: | make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH make distclean From 8d4afa34ca19f78677593d6e03c948235ce2f0d1 Mon Sep 17 00:00:00 2001 From: Shriraj Hegde Date: Tue, 5 Oct 2021 23:50:47 +0530 Subject: [PATCH 045/289] Upload each architecture binary separately --- .github/workflows/continuous-build.yml | 38 ++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index abc19cf..f83ac58 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -72,7 +72,41 @@ jobs: mv bin/btop multiarch_bin/btop-sparc64-$GIT_HASH make distclean + - name: Make executable + run: | + chmod +x multiarch_bin/* + - uses: actions/upload-artifact@v2 with: - name: btop - path: 'multiarch_bin/btop-*' \ No newline at end of file + name: btop-x86_64 + path: 'multiarch_bin/btop-x86_64*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-i686 + path: 'multiarch_bin/btop-i686*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-aarch64 + path: 'multiarch_bin/btop-aarch64*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-armel + path: 'multiarch_bin/btop-armel*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-armhf + path: 'multiarch_bin/btop-armhf*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-riscv64 + path: 'multiarch_bin/btop-riscv64*' + + - uses: actions/upload-artifact@v2 + with: + name: btop-sparc64 + path: 'multiarch_bin/btop-sparc64*' \ No newline at end of file From acdefb788996953559e703024983f13fdee4fadd Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 5 Oct 2021 20:55:15 +0200 Subject: [PATCH 046/289] Change to only build if there are changes to source files or the build script itself --- .github/workflows/continuous-build.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index f83ac58..7bffe29 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -2,6 +2,11 @@ name: Continuous Build Linux on: push + paths: + - 'src/**' + - 'include/**' + - 'Makefile' + - '.github/workflows/continuous-build.yml' jobs: build: @@ -32,7 +37,7 @@ jobs: - name: Compile i686 run: | - make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true + make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") mv bin/btop multiarch_bin/btop-i686-$GIT_HASH make distclean @@ -46,7 +51,7 @@ jobs: - name: Compile armel run: | - make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true + make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") mv bin/btop multiarch_bin/btop-armel-$GIT_HASH make distclean From 721da8c0553cc695f2f2cfc3146470777273d5d3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 5 Oct 2021 20:57:33 +0200 Subject: [PATCH 047/289] Fixed missing colon --- .github/workflows/continuous-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 7bffe29..d90f2b7 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,7 +1,7 @@ name: Continuous Build Linux on: - push + push: paths: - 'src/**' - 'include/**' From 9cf7a77ef867df1bcf1d8bbdf388e0cfb1651632 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 5 Oct 2021 21:06:19 +0200 Subject: [PATCH 048/289] Upcoming in v1.0.14 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4fec24..2cc3fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.0.14 (next release) + +* Changed: Total system memory is checked at every update instead of once at start + +* Added: Continuous Build workflow, by @ShrirajHegde + ## v1.0.13 * Changed: Graph empty symbol is now regular whitespace From 8c0b815bc1fb6b4f2ef330a3dbec421353be0bf3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 08:19:33 +0200 Subject: [PATCH 049/289] Ignore changes to osx or freebsd --- .github/workflows/continuous-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index d90f2b7..91392c0 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -4,6 +4,8 @@ on: push: paths: - 'src/**' + - '!src/osx/**' + - '!src/freebsd/**' - 'include/**' - 'Makefile' - '.github/workflows/continuous-build.yml' @@ -114,4 +116,4 @@ jobs: - uses: actions/upload-artifact@v2 with: name: btop-sparc64 - path: 'multiarch_bin/btop-sparc64*' \ No newline at end of file + path: 'multiarch_bin/btop-sparc64*' From 69c5eba1db6ad88ee6c3156a4991b2c3fa30fcdc Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 10:47:24 +0200 Subject: [PATCH 050/289] Fixed: Uid -> User fallback to getpwuid() if failure for non static builds --- Makefile | 2 +- src/linux/btop_collect.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f8ec78a..c614b93 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ ifeq ($(ARCH),x86_64) endif ifeq ($(STATIC),true) - override ADDFLAGS += -static -static-libgcc -static-libstdc++ + override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ endif #? Make sure PLATFORM Darwin is OSX and not Darwin diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index ea36b89..376be7f 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -27,6 +27,10 @@ tab-size = 4 #include #include +#ifndef STATIC_BUILD + #include +#endif + #include #include #include @@ -1416,7 +1420,26 @@ namespace Proc { } } pread.close(); - new_proc.user = (uid_user.contains(uid)) ? uid_user.at(uid) : uid; + if (uid_user.contains(uid)) { + new_proc.user = uid_user.at(uid); + } + else { + #ifndef STATIC_BUILD + try { + struct passwd* udet; + udet = getpwuid(stoi(uid)); + if (udet != NULL and udet->pw_name != NULL) { + new_proc.user = string(udet->pw_name); + } + else { + new_proc.user = uid; + } + } + catch (...) { new_proc.user = uid; } + #else + new_proc.user = uid; + #endif + } } //? Parse /proc/[pid]/stat From ad0b3d6b097aaca2c718dc2901748527f7ce60b3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 10:54:19 +0200 Subject: [PATCH 051/289] Added notice about LDAP and static compilation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b37b268..3d269e4 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,8 @@ Also needs a UTF8 locale and a font that covers: Append `STATIC=true` to `make` command for static compilation. + Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users when compiling statically. + Append `QUIET=true` for less verbose output. Notice! Manually set `$ARCH` variable if cross-compiling From dbcd12b9d0d7c8c5ce95e066b40118a6faa78063 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 11:25:10 +0200 Subject: [PATCH 052/289] Fixed: snap root disk and changed to compiler flags instead of env variables for detection --- snap/snapcraft.yaml | 3 +-- src/linux/btop_collect.cpp | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f7a87ba..17d75ed 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -29,7 +29,6 @@ apps: environment: LC_ALL: C.UTF-8 LANG: C.UTF-8 - BTOP_SNAPPED: true plugs: - mount-observe - process-control @@ -48,7 +47,7 @@ parts: make-parameters: - PREFIX=/usr/local - STATIC=true - - BTOP_SNAPPED=1 + - ADDFLAGS="-D SNAPPED" build-packages: - coreutils diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 376be7f..ff72654 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -686,7 +686,6 @@ namespace Mem { auto& show_disks = Config::getB("show_disks"); auto totalMem = get_totalMem(); auto& mem = current_mem; - static const bool snapped = (getenv("BTOP_SNAPPED") != NULL); mem.stats.at("swap_total") = 0; @@ -791,8 +790,12 @@ namespace Mem { for (string instr; diskread >> instr;) { if (not instr.starts_with('#')) { diskread >> instr; - if (snapped and instr == "/") fstab.push_back("/mnt"); - else if (not is_in(instr, "none", "swap")) fstab.push_back(instr); + #ifdef SNAPPED + if (instr == "/") fstab.push_back("/mnt"); + else if (not is_in(instr, "none", "swap")) fstab.push_back(instr); + #else + if (not is_in(instr, "none", "swap")) fstab.push_back(instr); + #endif } diskread.ignore(SSmax, '\n'); } @@ -829,7 +832,10 @@ namespace Mem { if (not disks.contains(mountpoint)) { disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename()}; if (disks.at(mountpoint).dev.empty()) disks.at(mountpoint).dev = dev; - if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" or (snapped and mountpoint == "/mnt") ? "root" : mountpoint); + #ifdef SNAPPED + if (mountpoint == "/mnt") disks.at(mountpoint).name = "root"; + #endif + if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); string devname = disks.at(mountpoint).dev.filename(); while (devname.size() >= 2) { if (fs::exists("/sys/block/" + devname + "/stat", ec) and access(string("/sys/block/" + devname + "/stat").c_str(), R_OK) == 0) { @@ -875,8 +881,11 @@ namespace Mem { //? Setup disks order in UI and add swap if enabled mem.disks_order.clear(); - if (snapped and disks.contains("/mnt")) mem.disks_order.push_back("/mnt"); - else if (disks.contains("/")) mem.disks_order.push_back("/"); + #ifdef SNAPPED + if (disks.contains("/mnt")) mem.disks_order.push_back("/mnt"); + #else + if (disks.contains("/")) mem.disks_order.push_back("/"); + #endif if (swap_disk and has_swap) { mem.disks_order.push_back("swap"); if (not disks.contains("swap")) disks["swap"] = {"", "swap"}; From 3a20e55f3a38eb163fd13dbe3571bd41437bb526 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 12:36:54 +0200 Subject: [PATCH 053/289] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cc3fb7..4e51591 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ * Added: Continuous Build workflow, by @ShrirajHegde +* Fixed: Uid -> User fallback to getpwuid() if failure for non static builds + +* Fixed: snap root disk and changed to compiler flags instead of env variables for detection + ## v1.0.13 * Changed: Graph empty symbol is now regular whitespace From 2d013e857f751c709730482ad9efe4ba3352eb96 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 17:11:10 +0200 Subject: [PATCH 054/289] v1.0.14 Bug fixes and start of OSX development --- CHANGELOG.md | 4 +++- src/btop.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e51591..c101021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## v1.0.14 (next release) +## v1.0.14 * Changed: Total system memory is checked at every update instead of once at start @@ -8,6 +8,8 @@ * Fixed: snap root disk and changed to compiler flags instead of env variables for detection +* Added: Development branch for OSX, by @joske + ## v1.0.13 * Changed: Graph empty symbol is now regular whitespace diff --git a/src/btop.cpp b/src/btop.cpp index 64b925d..f6a5978 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.13"; + const string Version = "1.0.14"; int coreCount; string overlay; From dee69b54685e74b840ff5178c8c650339aad59ef Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 17:16:49 +0200 Subject: [PATCH 055/289] News --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 3d269e4..e25e74d 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,11 @@ ### Under development +##### 6 October 2021 + +OsX development have been started by @joske , big thanks :) +See branch [OSX](https://github.com/aristocratos/btop/tree/OSX) for current progress. + ##### 18 September 2021 The Linux version of btop++ is complete. Released as version 1.0.0 From 132f4e6da127281763d0a30e44d2bf7a9040936d Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 17:25:22 +0200 Subject: [PATCH 056/289] Ignore tags and other branches --- .github/workflows/continuous-build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 91392c0..33d545c 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -2,13 +2,16 @@ name: Continuous Build Linux on: push: + branches: + - main + tags-ignore: + - '*.*' paths: - 'src/**' - '!src/osx/**' - '!src/freebsd/**' - 'include/**' - 'Makefile' - - '.github/workflows/continuous-build.yml' jobs: build: From d96fdd7eb2fcd60b48d4837908476deb027f7c9a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Oct 2021 18:06:05 +0200 Subject: [PATCH 057/289] Fixed: Extra "root" partition when running in snap --- src/linux/btop_collect.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index ff72654..9ba9bcc 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -112,7 +112,7 @@ namespace Shared { clkTck = 100; Logger::warning("Could not get system clock ticks per second. Defaulting to 100, processes cpu usage might be incorrect."); } - + //? Init for namespace Cpu if (not fs::exists(Cpu::freq_path) or access(Cpu::freq_path.c_str(), R_OK) == -1) Cpu::freq_path.clear(); Cpu::current_cpu.core_percent.insert(Cpu::current_cpu.core_percent.begin(), Shared::coreCount, {}); @@ -675,7 +675,7 @@ namespace Mem { } if (not meminfo.good() or totalMem == 0) throw std::runtime_error("Could not get total memory size from /proc/meminfo"); - + return totalMem; } @@ -896,7 +896,11 @@ namespace Mem { disks.at("swap").free_percent = mem.percent.at("swap_free").back(); } for (const auto& name : last_found) - if (not is_in(name, "/", "swap")) mem.disks_order.push_back(name); + #ifdef SNAPPED + if (not is_in(name, "/mnt", "swap")) mem.disks_order.push_back(name); + #else + if (not is_in(name, "/", "swap")) mem.disks_order.push_back(name); + #endif //? Get disks IO int64_t sectors_read, sectors_write, io_ticks; From 27c58dfc76a0d45285d7c3286957bcae9ebc05df Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 8 Oct 2021 09:18:31 +0200 Subject: [PATCH 058/289] Changelog v1.0.15 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c101021..b951adf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.15 + +* Fixed: Extra "root" partition when running in snap + ## v1.0.14 * Changed: Total system memory is checked at every update instead of once at start From 4b4bac7edd4181d929654f80b8bc74e48be21100 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 12 Oct 2021 16:49:10 +0200 Subject: [PATCH 059/289] Changed: Limit atomic_wait() to 1000ms to fix rare stall --- src/btop_tools.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 97e010a..27463a5 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -269,7 +269,7 @@ namespace Tools { string hostname(); string username(); - inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { while (atom.load() == old) sleep_ms(1); } + inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { for (int x = 0; atom.load() == old and x < 1000; x++) sleep_ms(1); } //* Waits for atomic to be false and sets it to true on construct, sets to false on destruct class atomic_lock { From 07145f9351c206e39c0c69b9a2e4232758522653 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 12 Oct 2021 16:56:47 +0200 Subject: [PATCH 060/289] Fixed: Removed unneeded lock in Runner::run() --- src/btop.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index f6a5978..7df9060 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -589,8 +589,7 @@ namespace Runner { //* Runs collect and draw in a secondary thread, unlocks and locks config to update cached values void run(const string& box, const bool no_update, const bool force_redraw) { - atomic_lock lck(waiting); - atomic_wait(active); + if (active) atomic_wait(active); if (stopping or Global::resized) return; if (box == "overlay") { From 2df9b58ff14dc7834421b978394ed920e34d7833 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 12 Oct 2021 17:34:52 +0200 Subject: [PATCH 061/289] Added: Toggle in options for enabling directional vim keys "h,j,k,l" --- src/btop_config.cpp | 4 ++++ src/btop_draw.cpp | 5 +++-- src/btop_input.cpp | 14 ++++++++------ src/btop_menu.cpp | 30 ++++++++++++++++++++---------- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 2a1bbc0..a26323f 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -54,6 +54,9 @@ namespace Config { "#* Use withespace \" \" as seprator between different presets.\n" "#* Example: \"cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty\""}, + {"vim_keys", "#* Set to True to enable \"h,j,k,l\" keys for directional control in lists.\n" + "#* Conflicting keys for h:\"help\" and k:\"kill\" is accessible while holding shift."}, + {"rounded_corners", "#* Rounded corners on boxes, is ignored if TTY mode is ON."}, {"graph_symbol", "#* Default symbols to use for graph creation, \"braille\", \"block\" or \"tty\".\n" @@ -231,6 +234,7 @@ namespace Config { {"net_auto", true}, {"net_sync", false}, {"show_battery", true}, + {"vim_keys", false}, {"tty_mode", false}, {"force_tty", false}, {"lowcolor", false}, diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index d290832..a489d37 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1039,9 +1039,10 @@ namespace Proc { auto selected = Config::getI("proc_selected"); auto last_selected = Config::getI("proc_last_selected"); const int select_max = (Config::getB("show_detailed") ? Proc::select_max - 8 : Proc::select_max); + auto& vim_keys = Config::getB("vim_keys"); int numpids = Proc::numpids; - if (cmd_key == "up" and selected > 0) { + if ((cmd_key == "up" or (vim_keys and cmd_key == "k")) and selected > 0) { if (start > 0 and selected == 1) start--; else selected--; if (Config::getI("proc_last_selected") > 0) Config::set("proc_last_selected", 0); @@ -1052,7 +1053,7 @@ namespace Proc { else if (cmd_key == "mouse_scroll_down" and start < numpids - select_max) { start = min(numpids - select_max, start + 3); } - else if (cmd_key == "down") { + else if (cmd_key == "down" or (vim_keys and cmd_key == "j")) { if (start < numpids - select_max and selected == select_max) start++; else if (selected == 0 and last_selected > 0) { selected = last_selected; diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 2056bea..df9e35a 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -182,7 +182,9 @@ namespace Input { if (key.empty()) return; try { auto& filtering = Config::getB("proc_filtering"); - + auto& vim_keys = Config::getB("vim_keys"); + auto help_key = (vim_keys ? "H" : "h"); + auto kill_key = (vim_keys ? "K" : "k"); //? Global input actions if (not filtering) { bool keep_going = false; @@ -193,7 +195,7 @@ namespace Input { Menu::show(Menu::Menus::Main); return; } - else if (is_in(key, "F1", "h")) { + else if (is_in(key, "F1", help_key)) { Menu::show(Menu::Menus::Help); return; } @@ -252,13 +254,13 @@ namespace Input { else return; } - else if (key == "left") { + else if (key == "left" or (vim_keys and key == "h")) { int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting")); if (--cur_i < 0) cur_i = Proc::sort_vector.size() - 1; Config::set("proc_sorting", Proc::sort_vector.at(cur_i)); } - else if (key == "right") { + else if (key == "right" or (vim_keys and key == "l")) { int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting")); if (std::cmp_greater(++cur_i, Proc::sort_vector.size() - 1)) cur_i = 0; @@ -344,7 +346,7 @@ namespace Input { if (key == "-" or key == "space") Proc::collapse = pid; no_update = false; } - else if (is_in(key, "t", "k") and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) { + else if (is_in(key, "t", kill_key) and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) { atomic_wait(Runner::active); if (Config::getB("show_detailed") and Config::getI("proc_selected") == 0 and Proc::detailed.status == "Dead") return; Menu::show(Menu::Menus::SignalSend, (key == "t" ? SIGTERM : SIGKILL)); @@ -356,7 +358,7 @@ namespace Input { Menu::show(Menu::Menus::SignalChoose); return; } - else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end")) { + else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k"))) { proc_mouse_scroll: redraw = false; auto old_selected = Config::getI("proc_selected"); diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 3128544..6c9eb8d 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -177,6 +177,15 @@ namespace Menu { "Will force 16-color mode and TTY theme,", "set all graph symbols to \"tty\" and swap", "out other non tty friendly symbols."}, + {"vim_keys", + "Enable vim keys.", + "Set to True to enable \"h,j,k,l\" keys for", + "directional control in lists.", + "", + "Conflicting keys for", + "h (help) and k (kill)", + "is accessible while holding shift."}, + {"presets", "Define presets for the layout of the boxes.", "", @@ -695,7 +704,7 @@ namespace Menu { else if (key == "backspace" and selected_signal != -1) { selected_signal = (selected_signal < 10 ? -1 : selected_signal / 10); } - else if (key == "up" and selected_signal != 16) { + else if (is_in(key, "up", "k") and selected_signal != 16) { if (selected_signal == 1) selected_signal = 31; else if (selected_signal < 6) selected_signal += 25; else { @@ -704,7 +713,7 @@ namespace Menu { if (selected_signal <= 16 and offset) selected_signal--; } } - else if (key == "down") { + else if (is_in(key, "down", "j")) { if (selected_signal == 31) selected_signal = 1; else if (selected_signal < 1 or selected_signal == 16) selected_signal = 1; else if (selected_signal > 26) selected_signal -= 25; @@ -715,11 +724,11 @@ namespace Menu { if (selected_signal > 31) selected_signal = 31; } } - else if (key == "left" and selected_signal > 0 and selected_signal != 16) { + else if (is_in(key, "left", "h") and selected_signal > 0 and selected_signal != 16) { if (--selected_signal < 1) selected_signal = 31; else if (selected_signal == 16) selected_signal--; } - else if (key == "right" and selected_signal <= 31 and selected_signal != 16) { + else if (is_in(key, "right", "l") and selected_signal <= 31 and selected_signal != 16) { if (++selected_signal > 31) selected_signal = 1; else if (selected_signal == 16) selected_signal++; } @@ -903,10 +912,10 @@ namespace Menu { exit(0); } } - else if (is_in(key, "down", "tab", "mouse_scroll_down")) { + else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) { if (++selected > 2) selected = 0; } - else if (is_in(key, "up", "shift_tab", "mouse_scroll_up")) { + else if (is_in(key, "up", "shift_tab", "mouse_scroll_up", "k")) { if (--selected < 0) selected = 2; } else { @@ -956,6 +965,7 @@ namespace Menu { {"cpu_sensor", std::cref(Cpu::available_sensors)} }; auto& tty_mode = Config::getB("tty_mode"); + auto& vim_keys = Config::getB("vim_keys"); if (max_items == 0) { for (const auto& cat : categories) { if ((int)cat.size() > max_items) max_items = cat.size(); @@ -1054,14 +1064,14 @@ namespace Menu { else if (is_in(key, "escape", "q", "o", "backspace")) { return Closed; } - else if (is_in(key, "down", "mouse_scroll_down")) { + else if (is_in(key, "down", "mouse_scroll_down") or (vim_keys and key == "j")) { if (++selected > select_max or selected >= item_height) { if (page < pages - 1) page++; else if (pages > 1) page = 0; selected = 0; } } - else if (is_in(key, "up", "mouse_scroll_up")) { + else if (is_in(key, "up", "mouse_scroll_up") or (vim_keys and key == "k")) { if (--selected < 0) { if (page > 0) page--; else if (pages > 1) page = pages - 1; @@ -1089,12 +1099,12 @@ namespace Menu { selected_cat = key.back() - '0' - 1; page = selected = 0; } - else if (is_in(key, "left", "right")) { + else if (is_in(key, "left", "right") or (vim_keys and is_in(key, "h", "l"))) { const auto& option = categories[selected_cat][item_height * page + selected][0]; if (selPred.test(isInt)) { const int mod = (option == "update_ms" ? 100 : 1); long value = Config::getI(option); - if (key == "right") value += mod; + if (key == "right" or (vim_keys and key == "l")) value += mod; else value -= mod; if (Config::intValid(option, to_string(value))) From 903ab4cc8a8aa491eb3c9eaf46417c1f5d922c92 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 12 Oct 2021 17:39:21 +0200 Subject: [PATCH 062/289] v1.0.15 Vim keys --- CHANGELOG.md | 6 ++++++ src/btop.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b951adf..ac7a881 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ * Fixed: Extra "root" partition when running in snap +* Changed: Limit atomic_wait() to 1000ms to fix rare stall + +* Fixed: Removed unneeded lock in Runner::run() + +* Added: Toggle in options for enabling directional vim keys "h,j,k,l" + ## v1.0.14 * Changed: Total system memory is checked at every update instead of once at start diff --git a/src/btop.cpp b/src/btop.cpp index 7df9060..55c1af2 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -55,7 +55,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.14"; + const string Version = "1.0.15"; int coreCount; string overlay; From a1bda5f30c632fda8161d5af4f2927c1a797628f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 12 Oct 2021 20:09:35 +0200 Subject: [PATCH 063/289] Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep --- src/btop_tools.cpp | 4 +++- src/btop_tools.hpp | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index bb75f2f..4668169 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -323,7 +323,9 @@ namespace Tools { atomic_lock::atomic_lock(atomic& atom) : atom(atom) { active_locks++; - while (not this->atom.compare_exchange_strong(this->not_true, true)); + while (not this->atom.compare_exchange_strong(this->not_true, true, std::memory_order_relaxed)) { + busy_wait(); + } } atomic_lock::~atomic_lock() { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 27463a5..4e705c7 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -269,7 +269,21 @@ namespace Tools { string hostname(); string username(); - inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { for (int x = 0; atom.load() == old and x < 1000; x++) sleep_ms(1); } + static inline void busy_wait (void) { + #if defined __i386__ || defined __x86_64__ + __builtin_ia32_pause(); + #elif defined __ia64__ + __asm volatile("hint @pause" : : : "memory"); + #elif defined __sparc__ && (defined __arch64__ || defined __sparc_v9__) + __asm volatile("membar #LoadLoad" : : : "memory"); + #else + __asm volatile("" : : : "memory"); + #endif + } + + inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { + while (atom.load(std::memory_order_relaxed) == old) busy_wait(); + } //* Waits for atomic to be false and sets it to true on construct, sets to false on destruct class atomic_lock { From 804fe60ca971a46c2f4427c1488076452ecc91ef Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 Oct 2021 20:54:36 +0200 Subject: [PATCH 064/289] Fixed: Swapped from atomic bool spinlocks to mutexes to fix rare deadlock --- src/btop.cpp | 71 +++++++++++++++++++++++++++------------------ src/btop_config.cpp | 11 +++---- src/btop_tools.cpp | 28 +++++++++++------- src/btop_tools.hpp | 6 ++-- 4 files changed, 70 insertions(+), 46 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 55c1af2..eca96c4 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -30,6 +30,7 @@ tab-size = 4 #include #include #include +#include #include #include @@ -40,7 +41,7 @@ tab-size = 4 #include using std::string, std::string_view, std::vector, std::atomic, std::endl, std::cout, std::min, std::flush, std::endl; -using std::string_literals::operator""s, std::to_string, std::future, std::async, std::bitset, std::future_status; +using std::string_literals::operator""s, std::to_string, std::future, std::async, std::bitset, std::future_status, std::mutex, std::lock_guard; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -79,7 +80,6 @@ namespace Global { uint64_t start_time; atomic resized (false); - atomic resizing (false); atomic quitting (false); atomic _runner_started (false); @@ -150,8 +150,8 @@ void argumentParser(const int& argc, char **argv) { //* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true void term_resize(bool force) { - if (Global::resizing) return; - atomic_lock lck(Global::resizing); + static mutex resizing; + lock_guard lock(resizing); if (auto refreshed = Term::refresh(true); refreshed or force) { if (force and refreshed) force = false; } @@ -271,6 +271,7 @@ namespace Runner { atomic stopping (false); atomic waiting (false); atomic redraw (false); + // mutex runner_mtx; //* Setup semaphore for triggering thread to do work #if __GNUC__ < 11 @@ -302,6 +303,7 @@ namespace Runner { sigset_t mask; pthread_t runner_id; pthread_mutex_t mtx; + pthread_mutex_t active_mtx; const unordered_flat_map box_bits = { {"proc", 0b0000'0001}, @@ -387,6 +389,7 @@ namespace Runner { //* ----------------------------------------------- THREAD LOOP ----------------------------------------------- while (not Global::quitting) { thread_wait(); + thread_lock lock(active_mtx); if (stopping or Global::resized) { continue; } @@ -589,34 +592,40 @@ namespace Runner { //* Runs collect and draw in a secondary thread, unlocks and locks config to update cached values void run(const string& box, const bool no_update, const bool force_redraw) { - if (active) atomic_wait(active); - if (stopping or Global::resized) return; + bool trigger = false; + { + thread_lock lock(active_mtx); + if (stopping or Global::resized) return; - if (box == "overlay") { - cout << Term::sync_start << Global::overlay << Term::sync_end << flush; - } - else if (box == "clock") { - cout << Term::sync_start << Global::clock << Term::sync_end << flush; - } - else { - Config::unlock(); - Config::lock(); - - //? Setup bitmask for selected boxes and pass to _runner thread - bitset<8> box_mask; - for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { - box_mask |= box_bits.at(box); + if (box == "overlay") { + cout << Term::sync_start << Global::overlay << Term::sync_end << flush; } + else if (box == "clock") { + cout << Term::sync_start << Global::clock << Term::sync_end << flush; + } + else { + Config::unlock(); + Config::lock(); - current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; + //? Setup bitmask for selected boxes and pass to _runner thread + bitset<8> box_mask; + for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { + box_mask |= box_bits.at(box); + } - if (Menu::active and not current_conf.background_update) Global::overlay.clear(); + current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; - thread_trigger(); + if (Menu::active and not current_conf.background_update) Global::overlay.clear(); - //? Wait for _runner thread to be active before returning - for (int i = 0; not active and i < 10; i++) sleep_ms(1); + trigger = true; + } } + //? Trigger thread start and wait for it to be active before returning + if (trigger) { + thread_trigger(); + atomic_wait_for(active, false, 10); + } + } //* Stops any work being done in runner thread and checks for thread errors @@ -629,9 +638,15 @@ namespace Runner { exit(1); } else if (ret == EBUSY) { - atomic_wait(active); + atomic_wait_for(active, true, 1000); + if (active) { + Global::exit_error_msg = "No response from Runner thread, quitting!"; + active = false; + exit(1); + } thread_trigger(); - sleep_ms(1); + atomic_wait_for(active, false, 100); + atomic_wait_for(active, true, 100); } stopping = false; } @@ -857,7 +872,7 @@ int main(int argc, char **argv) { Global::resized = false; if (Menu::active) Menu::process(); else Runner::run("all", true, true); - atomic_wait(Runner::active); + atomic_wait_for(Runner::active, true, 1000); } //? Update clock if needed diff --git a/src/btop_config.cpp b/src/btop_config.cpp index a26323f..4ca2ac1 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -21,12 +21,13 @@ tab-size = 4 #include #include #include +#include #include #include #include -using std::array, std::atomic, std::string_view, std::string_literals::operator""s; +using std::array, std::atomic, std::string_view, std::string_literals::operator""s, std::mutex, std::lock_guard; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -35,7 +36,7 @@ using namespace Tools; namespace Config { atomic locked (false); - atomic writelock (false); + mutex writelock; bool write_new; const vector> descriptions = { @@ -256,7 +257,7 @@ namespace Config { unordered_flat_map intsTmp; bool _locked(const string& name) { - atomic_wait(writelock); + lock_guard lock(writelock); if (not write_new and rng::find_if(descriptions, [&name](const auto& a) { return a.at(0) == name; }) != descriptions.end()) write_new = true; return locked.load(); @@ -334,7 +335,7 @@ namespace Config { } void lock() { - atomic_wait(writelock); + lock_guard lock(writelock); locked = true; } @@ -448,7 +449,7 @@ namespace Config { void unlock() { if (not locked) return; atomic_wait(Runner::active); - atomic_lock lck(writelock); + lock_guard lock(writelock); try { if (Proc::shown) { ints.at("selected_pid") = Proc::selected_pid; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 4668169..72b7e90 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -24,6 +24,7 @@ tab-size = 4 #include #include #include +#include #include #include @@ -33,7 +34,8 @@ tab-size = 4 #include #include -using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map; +using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map, + std::mutex, std::lock_guard; namespace fs = std::filesystem; namespace rng = std::ranges; @@ -321,11 +323,18 @@ namespace Tools { return ss.str(); } + void atomic_wait(const atomic& atom, const bool old) noexcept { + while (atom.load(std::memory_order_relaxed) == old ) busy_wait(); + } + + void atomic_wait_for(const atomic& atom, const bool old, const uint64_t wait_ms) noexcept { + const uint64_t start_time = time_ms(); + while (atom.load(std::memory_order_relaxed) == old and (time_ms() - start_time < wait_ms)) sleep_ms(1); + } + atomic_lock::atomic_lock(atomic& atom) : atom(atom) { active_locks++; - while (not this->atom.compare_exchange_strong(this->not_true, true, std::memory_order_relaxed)) { - busy_wait(); - } + this->atom.store(true); } atomic_lock::~atomic_lock() { @@ -375,11 +384,10 @@ namespace Tools { namespace Logger { using namespace Tools; - namespace { - std::atomic busy (false); - bool first = true; - const string tdf = "%Y/%m/%d (%T) | "; - } + + mutex logger_mtx; + bool first = true; + const string tdf = "%Y/%m/%d (%T) | "; size_t loglevel; fs::path logfile; @@ -390,7 +398,7 @@ namespace Logger { void log_write(const size_t level, const string& msg) { if (loglevel < level or logfile.empty()) return; - atomic_lock lck(busy); + lock_guard lock(logger_mtx); std::error_code ec; try { if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 4e705c7..0810adc 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -281,9 +281,9 @@ namespace Tools { #endif } - inline void atomic_wait(const atomic& atom, const bool old=true) noexcept { - while (atom.load(std::memory_order_relaxed) == old) busy_wait(); - } + void atomic_wait(const atomic& atom, const bool old=true) noexcept; + + void atomic_wait_for(const atomic& atom, const bool old=true, const uint64_t wait_ms=0) noexcept; //* Waits for atomic to be false and sets it to true on construct, sets to false on destruct class atomic_lock { From 79a030ca82ecd465883cf592230bb142ab00211b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 14 Oct 2021 09:22:14 +0200 Subject: [PATCH 065/289] Changed: Reverted thread mutex lock to atomic bool with wait and timeout --- src/btop.cpp | 70 ++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index eca96c4..4200606 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -303,7 +303,7 @@ namespace Runner { sigset_t mask; pthread_t runner_id; pthread_mutex_t mtx; - pthread_mutex_t active_mtx; + // pthread_mutex_t active_mtx; const unordered_flat_map box_bits = { {"proc", 0b0000'0001}, @@ -389,8 +389,15 @@ namespace Runner { //* ----------------------------------------------- THREAD LOOP ----------------------------------------------- while (not Global::quitting) { thread_wait(); - thread_lock lock(active_mtx); + atomic_wait_for(active, true, 5000); + if (active) { + Global::exit_error_msg = "Runner thread failed to get active lock!"; + Global::thread_exception = true; + Input::interrupt = true; + stopping = true; + } if (stopping or Global::resized) { + sleep_ms(1); continue; } @@ -592,40 +599,39 @@ namespace Runner { //* Runs collect and draw in a secondary thread, unlocks and locks config to update cached values void run(const string& box, const bool no_update, const bool force_redraw) { - bool trigger = false; - { - thread_lock lock(active_mtx); - if (stopping or Global::resized) return; - - if (box == "overlay") { - cout << Term::sync_start << Global::overlay << Term::sync_end << flush; - } - else if (box == "clock") { - cout << Term::sync_start << Global::clock << Term::sync_end << flush; - } - else { - Config::unlock(); - Config::lock(); - - //? Setup bitmask for selected boxes and pass to _runner thread - bitset<8> box_mask; - for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { - box_mask |= box_bits.at(box); - } - - current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; - - if (Menu::active and not current_conf.background_update) Global::overlay.clear(); - - trigger = true; - } + atomic_wait_for(active, true, 5000); + if (active) { + Global::exit_error_msg = "Stall in Runner thread, quitting!"; + active = false; + exit(1); } - //? Trigger thread start and wait for it to be active before returning - if (trigger) { + if (stopping or Global::resized) return; + + if (box == "overlay") { + cout << Term::sync_start << Global::overlay << Term::sync_end << flush; + } + else if (box == "clock") { + cout << Term::sync_start << Global::clock << Term::sync_end << flush; + } + else { + Config::unlock(); + Config::lock(); + + //? Setup bitmask for selected boxes and pass to _runner thread + bitset<8> box_mask; + for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { + box_mask |= box_bits.at(box); + } + + current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; + + if (Menu::active and not current_conf.background_update) Global::overlay.clear(); + thread_trigger(); atomic_wait_for(active, false, 10); } + } //* Stops any work being done in runner thread and checks for thread errors @@ -638,7 +644,7 @@ namespace Runner { exit(1); } else if (ret == EBUSY) { - atomic_wait_for(active, true, 1000); + atomic_wait_for(active, true, 5000); if (active) { Global::exit_error_msg = "No response from Runner thread, quitting!"; active = false; From 832699ffe6de3e51e18cd269e0f81093b3f041e7 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 14 Oct 2021 21:44:39 +0200 Subject: [PATCH 066/289] Changed: Removed unnecessary async threads in Runner thread --- src/btop.cpp | 225 +++++++++++++++++++-------------------------------- 1 file changed, 85 insertions(+), 140 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 4200606..3e5fa5e 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -19,8 +19,6 @@ tab-size = 4 #include #include #include -#include -#include #include #include #include @@ -41,7 +39,7 @@ tab-size = 4 #include using std::string, std::string_view, std::vector, std::atomic, std::endl, std::cout, std::min, std::flush, std::endl; -using std::string_literals::operator""s, std::to_string, std::future, std::async, std::bitset, std::future_status, std::mutex, std::lock_guard; +using std::string_literals::operator""s, std::to_string, std::mutex, std::lock_guard; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -200,8 +198,13 @@ void clean_quit(int sig) { if (Global::quitting) return; Global::quitting = true; Runner::stop(); - if (Global::_runner_started and pthread_join(Runner::runner_id, NULL) != 0) { - Logger::error("Failed to join _runner thread!"); + if (Global::_runner_started) { + struct timespec ts; + ts.tv_sec = 5; + if (pthread_timedjoin_np(Runner::runner_id, NULL, &ts) != 0) { + Logger::error("Failed to join _runner thread!"); + pthread_cancel(Runner::runner_id); + } } Config::write(); @@ -271,7 +274,6 @@ namespace Runner { atomic stopping (false); atomic waiting (false); atomic redraw (false); - // mutex runner_mtx; //* Setup semaphore for triggering thread to do work #if __GNUC__ < 11 @@ -303,21 +305,6 @@ namespace Runner { sigset_t mask; pthread_t runner_id; pthread_mutex_t mtx; - // pthread_mutex_t active_mtx; - - const unordered_flat_map box_bits = { - {"proc", 0b0000'0001}, - {"net", 0b0000'0100}, - {"mem", 0b0001'0000}, - {"cpu", 0b0100'0000}, - }; - - enum bit_pos { - proc_present, proc_running, - net_present, net_running, - mem_present, mem_running, - cpu_present, cpu_running - }; enum debug_actions { collect_begin, @@ -330,16 +317,11 @@ namespace Runner { draw }; - const uint_fast8_t proc_done = 0b0000'0011; - const uint_fast8_t net_done = 0b0000'1100; - const uint_fast8_t mem_done = 0b0011'0000; - const uint_fast8_t cpu_done = 0b1100'0000; - string debug_bg; unordered_flat_map> debug_times; struct runner_conf { - bitset<8> box_mask; + vector boxes; bool no_update; bool force_redraw; bool background_update; @@ -415,128 +397,86 @@ namespace Runner { output.clear(); - //* Start collection functions for all boxes in async threads and draw in this thread when finished - //? Starting order below based on mean time to finish + //* Run collection and draw functions for all boxes try { - future cpu; - future mem; - future net; - future&> proc; + //? PROC + if (v_contains(conf.boxes, "proc")) { + try { + if (Global::debug) debug_timer("proc", collect_begin); - //? Loop until all box flags present in bitmask have been zeroed - while (conf.box_mask.count() > 0) { - if (stopping) break; + //? Start collect + auto proc = Proc::collect(conf.no_update); - //? PROC - if (conf.box_mask.test(proc_present)) { - if (not conf.box_mask.test(proc_running)) { - if (Global::debug) debug_timer("proc", collect_begin); + if (Global::debug) debug_timer("proc", draw_begin); - //? Start async collect - proc = async(Proc::collect, conf.no_update); - conf.box_mask.set(proc_running); - } - else if (not proc.valid()) - throw std::runtime_error("Proc::collect() future not valid."); + //? Draw box + if (not pause_output) output += Proc::draw(proc, conf.force_redraw, conf.no_update); - else if (proc.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("proc", draw_begin); - - //? Draw box - if (not pause_output) output += Proc::draw(proc.get(), conf.force_redraw, conf.no_update); - - if (Global::debug) debug_timer("proc", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Proc:: -> " + (string)e.what()); - } - conf.box_mask ^= proc_done; - } + if (Global::debug) debug_timer("proc", draw_done); } - - //? NET - if (conf.box_mask.test(net_present)) { - if (not conf.box_mask.test(net_running)) { - if (Global::debug) debug_timer("net", collect_begin); - - //? Start async collect - net = async(Net::collect, conf.no_update); - conf.box_mask.set(net_running); - } - else if (not net.valid()) - throw std::runtime_error("Net::collect() future not valid."); - - else if (net.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("net", draw_begin); - - //? Draw box - if (not pause_output) output += Net::draw(net.get(), conf.force_redraw, conf.no_update); - - if (Global::debug) debug_timer("net", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Net:: -> " + (string)e.what()); - } - conf.box_mask ^= net_done; - } + catch (const std::exception& e) { + throw std::runtime_error("Proc:: -> " + (string)e.what()); } + } - //? MEM - if (conf.box_mask.test(mem_present)) { - if (not conf.box_mask.test(mem_running)) { - if (Global::debug) debug_timer("mem", collect_begin); - //? Start async collect - mem = async(Mem::collect, conf.no_update); - conf.box_mask.set(mem_running); - } - else if (not mem.valid()) - throw std::runtime_error("Mem::collect() future not valid."); + //? NET + if (v_contains(conf.boxes, "net")) { + try { + if (Global::debug) debug_timer("net", collect_begin); - else if (mem.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("mem", draw_begin); + //? Start collect + auto net = Net::collect(conf.no_update); - //? Draw box - if (not pause_output) output += Mem::draw(mem.get(), conf.force_redraw, conf.no_update); + if (Global::debug) debug_timer("net", draw_begin); - if (Global::debug) debug_timer("mem", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Mem:: -> " + (string)e.what()); - } - conf.box_mask ^= mem_done; - } + //? Draw box + if (not pause_output) output += Net::draw(net, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("net", draw_done); } + catch (const std::exception& e) { + throw std::runtime_error("Net:: -> " + (string)e.what()); + } + } - //? CPU - if (conf.box_mask.test(cpu_present)) { - if (not conf.box_mask.test(cpu_running)) { - if (Global::debug) debug_timer("cpu", collect_begin); + //? MEM + if (v_contains(conf.boxes, "mem")) { + try { + if (Global::debug) debug_timer("mem", collect_begin); - //? Start async collect - cpu = async(Cpu::collect, conf.no_update); - conf.box_mask.set(cpu_running); - } - else if (not cpu.valid()) - throw std::runtime_error("Cpu::collect() future not valid."); + //? Start collect + auto mem = Mem::collect(conf.no_update); - else if (cpu.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("cpu", draw_begin); + if (Global::debug) debug_timer("mem", draw_begin); - //? Draw box - if (not pause_output) output += Cpu::draw(cpu.get(), conf.force_redraw, conf.no_update); + //? Draw box + if (not pause_output) output += Mem::draw(mem, conf.force_redraw, conf.no_update); - if (Global::debug) debug_timer("cpu", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Cpu:: -> " + (string)e.what()); - } - conf.box_mask ^= cpu_done; - } + if (Global::debug) debug_timer("mem", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Mem:: -> " + (string)e.what()); + } + } + + //? CPU + if (v_contains(conf.boxes, "cpu")) { + try { + if (Global::debug) debug_timer("cpu", collect_begin); + + //? Start collect + auto cpu = Cpu::collect(conf.no_update); + + if (Global::debug) debug_timer("cpu", draw_begin); + + //? Draw box + if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("cpu", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Cpu:: -> " + (string)e.what()); } } } @@ -617,13 +557,13 @@ namespace Runner { Config::unlock(); Config::lock(); - //? Setup bitmask for selected boxes and pass to _runner thread - bitset<8> box_mask; - for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { - box_mask |= box_bits.at(box); - } - - current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; + current_conf = { + (box == "all" ? Config::current_boxes : vector{box}), + no_update, force_redraw, + (not Config::getB("tty_mode") and Config::getB("background_update")), + Global::overlay, + Global::clock + }; if (Menu::active and not current_conf.background_update) Global::overlay.clear(); @@ -646,9 +586,14 @@ namespace Runner { else if (ret == EBUSY) { atomic_wait_for(active, true, 5000); if (active) { - Global::exit_error_msg = "No response from Runner thread, quitting!"; active = false; - exit(1); + if (Global::quitting) { + return; + } + else { + Global::exit_error_msg = "No response from Runner thread, quitting!"; + exit(1); + } } thread_trigger(); atomic_wait_for(active, false, 100); From e20258ea9fce67b6a5f5009588817aee7ee6872e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 15 Oct 2021 08:32:37 +0200 Subject: [PATCH 067/289] Added: Try to restart secondary thread in case of stall and addiotional error checks for ifstream in Proc::collect() --- src/btop.cpp | 9 +++++++-- src/linux/btop_collect.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 3e5fa5e..86bba5f 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -541,9 +541,14 @@ namespace Runner { void run(const string& box, const bool no_update, const bool force_redraw) { atomic_wait_for(active, true, 5000); if (active) { - Global::exit_error_msg = "Stall in Runner thread, quitting!"; + Logger::error("Stall in Runner thread, restarting!"); active = false; - exit(1); + // exit(1); + pthread_cancel(Runner::runner_id); + if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) { + Global::exit_error_msg = "Failed to re-create _runner thread!"; + exit(1); + } } if (stopping or Global::resized) return; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 9ba9bcc..6d3abaa 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1354,7 +1354,7 @@ namespace Proc { uid_user.clear(); pread.open(Shared::passwd_path); if (pread.good()) { - while (not pread.eof()) { + while (pread.good()) { getline(pread, r_user, ':'); pread.ignore(SSmax, ':'); getline(pread, r_uid, ':'); @@ -1422,7 +1422,7 @@ namespace Proc { if (not pread.good()) continue; string uid; string line; - while (not pread.eof()) { + while (pread.good()) { getline(pread, line, ':'); if (line == "Uid") { pread.ignore(); @@ -1465,9 +1465,9 @@ namespace Proc { uint64_t cpu_t = 0; try { for (;;) { - while (++x < next_x + offset) pread.ignore(SSmax, ' '); - getline(pread, short_str, ' '); + while (pread.good() and ++x < next_x + offset) pread.ignore(SSmax, ' '); if (not pread.good()) break; + else getline(pread, short_str, ' '); switch (x-offset) { case 3: //? Process state From e5ccf7db2ce19317283e1240174587ce9c0cf892 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 16 Oct 2021 02:23:44 +0200 Subject: [PATCH 068/289] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fd64412..de86eaf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -44,10 +44,12 @@ contents of `~/.config/btop/btop.log` If btop++ is crashing at start the following steps could be helpful: +(Extra helpful if compiled with `make OPTFLAGS="-O0 -g"`) + 1. run `gdb btop` 2. `r` to run, wait for crash and press enter -3. `bt` to get backtrace +3. `thread apply all bt` to get backtrace for all threads 4. Copy and paste the backtrace here: From 084e231f1e908abf4415ef88af7f357dc7d523a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20L=C3=B3pez=20=C3=9Abeda?= Date: Sat, 16 Oct 2021 03:29:39 +0200 Subject: [PATCH 069/289] fix: when vim keys [k]ill should be [K]ill When we activate the vim_keys new option the label for kill a process should be capitalized as "Kill" for match the shortcut Shift+K fix: #87 --- src/btop_draw.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index a489d37..bc64dc9 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1104,6 +1104,7 @@ namespace Proc { auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_proc")); auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6); auto& mem_bytes = Config::getB("proc_mem_bytes"); + auto& vim_keys = Config::getB("vim_keys"); start = Config::getI("proc_start"); selected = Config::getI("proc_selected"); const int y = show_detailed ? Proc::y + 8 : Proc::y; @@ -1168,7 +1169,7 @@ namespace Proc { if (alive and selected == 0) Input::mouse_mappings["t"] = {d_y, mouse_x, 1, 9}; mouse_x += 11; } - out += title_left + hi_color + Fx::b + 'k' + t_color + "ill" + Fx::ub + title_right + out += title_left + hi_color + Fx::b + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right + title_left + hi_color + Fx::b + 's' + t_color + "ignals" + Fx::ub + title_right + Mv::to(d_y, d_x + d_width - 10) + title_left + t_color + Fx::b + hide + Symbols::enter + Fx::ub + title_right; if (alive and selected == 0) { @@ -1261,7 +1262,7 @@ namespace Proc { mouse_x += 11; } if (width > 55) { - out += title_left_down + Fx::b + hi_color + 'k' + t_color + "ill" + Fx::ub + title_right_down; + out += title_left_down + Fx::b + hi_color + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right_down; if (selected > 0) Input::mouse_mappings["k"] = {y + height - 1, mouse_x, 1, 4}; mouse_x += 6; } From 3e936bfa8ef1d70a9b7582ad452f5d7be3916934 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 16 Oct 2021 11:14:11 +0200 Subject: [PATCH 070/289] v1.0.16 Bug fixes --- CHANGELOG.md | 16 ++++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac7a881..69f1507 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v1.0.16 + +* Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep + +* Fixed: Swapped from atomic bool spinlocks to mutexes to fix rare deadlock + +* Added: Continuous Build workflow for OSX branch, by @ShrirajHegde + +* Changed: Reverted thread mutex lock to atomic bool with wait and timeout + +* Changed: Removed unnecessary async threads in Runner thread + +* Added: Try to restart secondary thread in case of stall and additional error checks for ifstream in Proc::collect() + +* Fixed: change [k]ill to [K]ill when enabling vim keys, by @jlopezcur + ## v1.0.15 * Fixed: Extra "root" partition when running in snap diff --git a/src/btop.cpp b/src/btop.cpp index 86bba5f..ff35ec0 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -54,7 +54,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.15"; + const string Version = "1.0.16"; int coreCount; string overlay; From 19ff46369532b2aca5dac75b9de1b8cb3eb7b1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 13:00:23 +0200 Subject: [PATCH 071/289] added yml definitions to .editorconfig --- .editorconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.editorconfig b/.editorconfig index 61b7846..63202f0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,7 @@ [*.{cpp,h,sh,md,cfg,sample}] indent_style = tab indent_size = 4 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 From c8a7c0dc19c74dbd9f15efa5af54977617a405e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 13:02:06 +0200 Subject: [PATCH 072/289] changed static build behavior restrict getpwuid usage only in static builds with glibc --- src/linux/btop_collect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 6d3abaa..6e436e5 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -27,7 +27,7 @@ tab-size = 4 #include #include -#ifndef STATIC_BUILD +#if !defined(STATIC_BUILD) || !defined(__GLIBC__) #include #endif @@ -1437,7 +1437,7 @@ namespace Proc { new_proc.user = uid_user.at(uid); } else { - #ifndef STATIC_BUILD + #if !defined(STATIC_BUILD) || !defined(__GLIBC__) try { struct passwd* udet; udet = getpwuid(stoi(uid)); From f0535095a26309861e5c37948913a7c5d181c1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 13:03:09 +0200 Subject: [PATCH 073/289] changed workflow to build binaries using musl --- .github/workflows/continuous-build.yml | 184 ++++++++++++------------- 1 file changed, 88 insertions(+), 96 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 33d545c..6662fda 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,9 +1,11 @@ name: Continuous Build Linux - + on: + workflow_dispatch: push: branches: - - main + - master + - musl-build tags-ignore: - '*.*' paths: @@ -12,111 +14,101 @@ on: - '!src/freebsd/**' - 'include/**' - 'Makefile' + - '.github/workflows/continuous-build.yml' jobs: - build: + static-build: + continue-on-error: true + strategy: + matrix: + toolchain: + - aarch64-linux-musl + - aarch64_be-linux-musl + - arm-linux-musleabi + - arm-linux-musleabihf + - armeb-linux-musleabi + - armeb-linux-musleabihf + - armel-linux-musleabi + - armel-linux-musleabihf + - armv5l-linux-musleabi + - armv5l-linux-musleabihf + - armv6-linux-musleabi + - armv6-linux-musleabihf + - armv7l-linux-musleabihf + - armv7m-linux-musleabi + - armv7r-linux-musleabihf + - i486-linux-musl + - i686-linux-musl + - m68k-linux-musl + - microblaze-linux-musl + - microblazeel-linux-musl + - mips-linux-musl + - mips-linux-musln32sf + - mips-linux-muslsf + - mips64-linux-musl + - mips64-linux-musln32 + - mips64-linux-musln32sf + - mips64el-linux-musl + - mips64el-linux-musln32 + - mips64el-linux-musln32sf + - mipsel-linux-musl + - mipsel-linux-musln32 + - mipsel-linux-musln32sf + - mipsel-linux-muslsf + - or1k-linux-musl + - powerpc-linux-musl + - powerpc-linux-muslsf + - powerpc64-linux-musl + - powerpc64le-linux-musl + - powerpcle-linux-musl + - powerpcle-linux-muslsf + - riscv32-linux-musl + - riscv64-linux-musl + - s390x-linux-musl + - sh2-linux-musl + - sh2-linux-muslfdpic + - sh2eb-linux-musl + - sh2eb-linux-muslfdpic + - sh4-linux-musl + - sh4eb-linux-musl + - x86_64-linux-musl + - x86_64-linux-muslx32 runs-on: ubuntu-latest - container: ubuntu:21.04 + container: muslcc/x86_64:${{ matrix.toolchain }} steps: - - uses: actions/checkout@v2 - name: Install build tools + run: apk add --no-cache coreutils git make tar zstd + + - name: Checkout source + uses: actions/checkout@v2 + + - name: Fix - Stopping at filesystem boundary + run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] + + - name: Build run: | - apt update && \ - apt install coreutils sed git build-essential gcc-11 g++-11 -y - apt install -y g++-11-aarch64-linux-gnu g++-11-i686-linux-gnu \ - g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-11-riscv64-linux-gnu \ - g++-11-sparc64-linux-gnu - - mkdir -p multiarch_bin - - git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] - - - name: Compile x86_64 - run: | - make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH - make distclean - - - name: Compile i686 - run: | - make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-i686-$GIT_HASH - make distclean - - - name: Compile aarch64 - run: | - make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH - make distclean - - - name: Compile armel - run: | - make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armel-$GIT_HASH - make distclean - - - name: Compile armhf - run: | - make CXX=arm-linux-gnueabihf-g++-11 ARCH=armhf STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armhf-$GIT_HASH - make distclean - - - name: Compile riscv64 - run: | - make CXX=riscv64-linux-gnu-g++-11 ARCH=riscv64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-riscv64-$GIT_HASH - make distclean - - - name: Compile sparc64 - run: | - make CXX=sparc64-linux-gnu-g++-11 ARCH=sparc64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-sparc64-$GIT_HASH - make distclean + TOOLCHAIN=${{ matrix.toolchain }} + make -j $(getconf _NPROCESSORS_ONLN) ARCH=${TOOLCHAIN/-*/} STATIC=true QUIET=true - name: Make executable + run: chmod +x bin/* + + - name: Set up directories run: | - chmod +x multiarch_bin/* + mkdir .artifacts + mkdir .package - - uses: actions/upload-artifact@v2 - with: - name: btop-x86_64 - path: 'multiarch_bin/btop-x86_64*' + - name: Create binary atrifacts + run: | + TOOLCHAIN=${{ matrix.toolchain }} + GIT_HASH=$(git rev-parse --short "${{ github.sha }}") + FILENAME=btop-${TOOLCHAIN/linux-musl/}-$GIT_HASH + cp bin/btop .artifacts/$FILENAME - - uses: actions/upload-artifact@v2 + - name: Upload artifacts + uses: actions/upload-artifact@v2 with: - name: btop-i686 - path: 'multiarch_bin/btop-i686*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-aarch64 - path: 'multiarch_bin/btop-aarch64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armel - path: 'multiarch_bin/btop-armel*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armhf - path: 'multiarch_bin/btop-armhf*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-riscv64 - path: 'multiarch_bin/btop-riscv64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-sparc64 - path: 'multiarch_bin/btop-sparc64*' + name: btop-${{ matrix.toolchain }} + path: '.artifacts/**' From 7d4c2bd3c921b6b44889e99aa8fd3c36e14328c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 15:15:56 +0200 Subject: [PATCH 074/289] updated Makefile - added platform and arch detection from CXX machine tuple - add PLATFORM_LC, a lowercase version of PLATFORM, for case insensitive comparison - added bool flag STRIP to force -s linker flag - turned linker warnings into errors in case of STATIC to fail in case of glibc static linking issues - bumped version to 1.3 --- Makefile | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index c614b93..3cae977 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ #* Btop++ makefile v1.2 -BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.2\033[0m +BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.3\033[0m override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") @@ -14,9 +14,11 @@ endif PREFIX ?= /usr/local -#? NOTICE! Manually set PLATFORM and ARCH if not compiling for host system -PLATFORM ?= $(shell uname -s || echo unknown) -ARCH ?= $(shell uname -m || echo unknown) +#? Detect PLATFORM and ARCH from gcc if not set +PLATFORM ?= $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') +ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) + +override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Only enable fcf-protection if on x86_64 ifeq ($(ARCH),x86_64) @@ -24,11 +26,15 @@ ifeq ($(ARCH),x86_64) endif ifeq ($(STATIC),true) - override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ + override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings +endif + +ifeq ($(STRIP),true) + override ADDFLAGS += -s endif #? Make sure PLATFORM Darwin is OSX and not Darwin -ifeq ($(PLATFORM),Darwin) +ifeq ($(PLATFORM_LC),darwin) ifeq ($(shell sw_vers >/dev/null 2>&1; echo $$?),0) PLATFORM := OSX endif @@ -50,13 +56,13 @@ ifeq ($(CXX),g++) endif #? Pull in platform specific source files and get thread count -ifeq ($(PLATFORM),Linux) +ifeq ($(PLATFORM_LC),linux) PLATFORM_DIR := linux THREADS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),FreeBSD) +else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),OSX) +else ifeq ($(PLATFORM_LC),osx) PLATFORM_DIR := osx THREADS := $(shell sysctl -n hw.ncpu || echo 1) else From b83f58a5b781c5e69e8407d024fc1405b58ba64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 15:16:44 +0200 Subject: [PATCH 075/289] updated workflow - removed ARCH parameter in favor of auto deection - added STRIP flag --- .github/workflows/continuous-build.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 6662fda..b6224e9 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -88,9 +88,7 @@ jobs: run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] - name: Build - run: | - TOOLCHAIN=${{ matrix.toolchain }} - make -j $(getconf _NPROCESSORS_ONLN) ARCH=${TOOLCHAIN/-*/} STATIC=true QUIET=true + run: make STATIC=true STRIP=true QUIET=true - name: Make executable run: chmod +x bin/* From bca35214728ce72b0e47a15df3d1c2ec5a6627e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 15:37:40 +0200 Subject: [PATCH 076/289] updated makefile to add cf-protection for i*86 builds --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3cae977..1bfd42a 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Only enable fcf-protection if on x86_64 -ifeq ($(ARCH),x86_64) +ifneq ($(filter x86_64 i%86, $(ARCH)),) override ADDFLAGS += -fcf-protection endif From 347e135bad49a030d1f66dbd1f4e25e30c64fd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 15:47:48 +0200 Subject: [PATCH 077/289] updated README.md to reflect Makefile changes --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e25e74d..3cd230f 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,10 @@ Also needs a UTF8 locale and a font that covers: Append `QUIET=true` for less verbose output. - Notice! Manually set `$ARCH` variable if cross-compiling + Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). + + Append `ARCH=` to manually set the target architectur. + If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. Use `ADDFLAGS` variable for appending flags to both compiler and linker. From d3c85dad21f63274b2a9acc9d7136a7da39716b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sat, 16 Oct 2021 23:51:12 +0200 Subject: [PATCH 078/289] removed temporary trigger for testing on branch --- .github/workflows/continuous-build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index b6224e9..33d5133 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -5,7 +5,6 @@ on: push: branches: - master - - musl-build tags-ignore: - '*.*' paths: From 16014226134ec9ff70a17298e51579889f2bd61a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 16 Oct 2021 23:52:06 +0200 Subject: [PATCH 079/289] Changed: Reverted mutexes back to custom atomic bool based locks --- src/btop.cpp | 7 +++---- src/btop_config.cpp | 11 +++++------ src/btop_tools.cpp | 15 +++++++-------- src/btop_tools.hpp | 2 +- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index ff35ec0..d58991d 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -28,7 +28,6 @@ tab-size = 4 #include #include #include -#include #include #include @@ -39,7 +38,7 @@ tab-size = 4 #include using std::string, std::string_view, std::vector, std::atomic, std::endl, std::cout, std::min, std::flush, std::endl; -using std::string_literals::operator""s, std::to_string, std::mutex, std::lock_guard; +using std::string_literals::operator""s, std::to_string; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -148,8 +147,8 @@ void argumentParser(const int& argc, char **argv) { //* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true void term_resize(bool force) { - static mutex resizing; - lock_guard lock(resizing); + static atomic resizing (false); + atomic_lock lck(resizing, true); if (auto refreshed = Term::refresh(true); refreshed or force) { if (force and refreshed) force = false; } diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 4ca2ac1..09dead3 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -21,13 +21,12 @@ tab-size = 4 #include #include #include -#include #include #include #include -using std::array, std::atomic, std::string_view, std::string_literals::operator""s, std::mutex, std::lock_guard; +using std::array, std::atomic, std::string_view, std::string_literals::operator""s; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -36,7 +35,7 @@ using namespace Tools; namespace Config { atomic locked (false); - mutex writelock; + atomic writelock (false); bool write_new; const vector> descriptions = { @@ -257,7 +256,7 @@ namespace Config { unordered_flat_map intsTmp; bool _locked(const string& name) { - lock_guard lock(writelock); + atomic_wait(writelock, true); if (not write_new and rng::find_if(descriptions, [&name](const auto& a) { return a.at(0) == name; }) != descriptions.end()) write_new = true; return locked.load(); @@ -335,7 +334,7 @@ namespace Config { } void lock() { - lock_guard lock(writelock); + atomic_wait(writelock); locked = true; } @@ -449,7 +448,7 @@ namespace Config { void unlock() { if (not locked) return; atomic_wait(Runner::active); - lock_guard lock(writelock); + atomic_lock lck(writelock, true); try { if (Proc::shown) { ints.at("selected_pid") = Proc::selected_pid; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 72b7e90..0d8705b 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -24,7 +24,6 @@ tab-size = 4 #include #include #include -#include #include #include @@ -34,8 +33,7 @@ tab-size = 4 #include #include -using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map, - std::mutex, std::lock_guard; +using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map; namespace fs = std::filesystem; namespace rng = std::ranges; @@ -332,9 +330,11 @@ namespace Tools { while (atom.load(std::memory_order_relaxed) == old and (time_ms() - start_time < wait_ms)) sleep_ms(1); } - atomic_lock::atomic_lock(atomic& atom) : atom(atom) { + atomic_lock::atomic_lock(atomic& atom, bool wait) : atom(atom) { active_locks++; - this->atom.store(true); + if (wait) { + while (not this->atom.compare_exchange_strong(this->not_true, true)); + } else this->atom.store(true); } atomic_lock::~atomic_lock() { @@ -384,8 +384,7 @@ namespace Tools { namespace Logger { using namespace Tools; - - mutex logger_mtx; + std::atomic busy (false); bool first = true; const string tdf = "%Y/%m/%d (%T) | "; @@ -398,7 +397,7 @@ namespace Logger { void log_write(const size_t level, const string& msg) { if (loglevel < level or logfile.empty()) return; - lock_guard lock(logger_mtx); + atomic_lock lck(busy, true); std::error_code ec; try { if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 0810adc..d68d1f3 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -290,7 +290,7 @@ namespace Tools { atomic& atom; bool not_true = false; public: - atomic_lock(atomic& atom); + atomic_lock(atomic& atom, bool wait=false); ~atomic_lock(); }; From ac1b6aab47c17319b76df6e5959cc5f4c33b97cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sun, 17 Oct 2021 01:02:37 +0200 Subject: [PATCH 080/289] adopting review comments https://github.com/aristocratos/btop/pull/92#discussion_r730320662 https://github.com/aristocratos/btop/pull/92#discussion_r730320819 --- Makefile | 9 +-------- README.md | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 1bfd42a..e580ee0 100644 --- a/Makefile +++ b/Makefile @@ -33,13 +33,6 @@ ifeq ($(STRIP),true) override ADDFLAGS += -s endif -#? Make sure PLATFORM Darwin is OSX and not Darwin -ifeq ($(PLATFORM_LC),darwin) - ifeq ($(shell sw_vers >/dev/null 2>&1; echo $$?),0) - PLATFORM := OSX - endif -endif - #? Compiler and Linker CXX ?= g++ override CXX_VERSION := $(shell $(CXX) -dumpfullversion -dumpversion || echo 0) @@ -62,7 +55,7 @@ ifeq ($(PLATFORM_LC),linux) else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM_LC),osx) +else ifeq ($(PLATFORM_LC),apple) PLATFORM_DIR := osx THREADS := $(shell sysctl -n hw.ncpu || echo 1) else diff --git a/README.md b/README.md index 3cd230f..1730fad 100644 --- a/README.md +++ b/README.md @@ -261,7 +261,7 @@ Also needs a UTF8 locale and a font that covers: Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). - Append `ARCH=` to manually set the target architectur. + Append `ARCH=` to manually set the target architecture. If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. Use `ADDFLAGS` variable for appending flags to both compiler and linker. From 816270750d6c35a27a1456672825822e4dfbe63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sun, 17 Oct 2021 01:45:26 +0200 Subject: [PATCH 081/289] readability change request in review https://github.com/aristocratos/btop/pull/92#discussion_r730321422 --- src/linux/btop_collect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 6e436e5..9b567df 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -27,7 +27,7 @@ tab-size = 4 #include #include -#if !defined(STATIC_BUILD) || !defined(__GLIBC__) +#if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #include #endif @@ -1437,7 +1437,7 @@ namespace Proc { new_proc.user = uid_user.at(uid); } else { - #if !defined(STATIC_BUILD) || !defined(__GLIBC__) + #if !(defined(STATIC_BUILD) && defined(__GLIBC__)) try { struct passwd* udet; udet = getpwuid(stoi(uid)); From 2ee13332266cfd7cbf9104502532870c85430b27 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 12:11:25 +0200 Subject: [PATCH 082/289] Changed: Removed microblaze platform from build targets because of issue with atomics --- .github/workflows/continuous-build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 33d5133..61c5df3 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,5 +1,5 @@ name: Continuous Build Linux - + on: workflow_dispatch: push: @@ -39,8 +39,6 @@ jobs: - i486-linux-musl - i686-linux-musl - m68k-linux-musl - - microblaze-linux-musl - - microblazeel-linux-musl - mips-linux-musl - mips-linux-musln32sf - mips-linux-muslsf @@ -82,7 +80,7 @@ jobs: - name: Checkout source uses: actions/checkout@v2 - + - name: Fix - Stopping at filesystem boundary run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] From 966c9f5e5e729ca7e1adebf600924c7d85e40a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sun, 17 Oct 2021 16:31:25 +0200 Subject: [PATCH 083/289] improved battery detection - new considering all power supplies (instead of path name filtering) - only consider power supplies that are currently present - only consider power supplies of type Batter or UPS --- src/linux/btop_collect.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 9b567df..22ba5a5 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -477,7 +477,16 @@ namespace Cpu { if (bat_dir.empty() and has_battery) { if (fs::exists("/sys/class/power_supply")) { for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { - if (const string dir_name = d.path().filename(); d.is_directory() and (dir_name.starts_with("BAT") or s_contains(str_to_lower(dir_name), "battery"))) { + //? Only consider online power supplies of type Battery or UPS + //? see kernel docs for details on the file structure and contents + //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power + if (not d.is_directory() + or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "present") + or stoi(readfile(d.path() / "present")) != 1) + continue; + string type = readfile(d.path() / "type"); + if (type == "Battery" or type == "UPS") { bat_dir = d.path(); break; } From 22297f795456e19a68328c7992806f1f0e43dd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sun, 17 Oct 2021 17:06:18 +0200 Subject: [PATCH 084/289] added try catch block as suggested in review https://github.com/aristocratos/btop/pull/97#discussion_r730428842 --- src/linux/btop_collect.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 22ba5a5..a5c745d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -480,15 +480,20 @@ namespace Cpu { //? Only consider online power supplies of type Battery or UPS //? see kernel docs for details on the file structure and contents //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power - if (not d.is_directory() - or not fs::exists(d.path() / "type") - or not fs::exists(d.path() / "present") - or stoi(readfile(d.path() / "present")) != 1) + try { + if (not d.is_directory() + or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "present") + or stoi(readfile(d.path() / "present")) != 1) + continue; + string type = readfile(d.path() / "type"); + if (type == "Battery" or type == "UPS") { + bat_dir = d.path(); + break; + } + } catch (...) { + //? skip power supplies not conforming to the kernel standard continue; - string type = readfile(d.path() / "type"); - if (type == "Battery" or type == "UPS") { - bat_dir = d.path(); - break; } } } From be9086c68f1974dacd8cda3ed554778536eff9f6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 17:48:31 +0200 Subject: [PATCH 085/289] Swap triggers around to see if it triggers... --- .github/workflows/continuous-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 61c5df3..91327d6 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,7 +1,6 @@ name: Continuous Build Linux on: - workflow_dispatch: push: branches: - master @@ -14,6 +13,7 @@ on: - 'include/**' - 'Makefile' - '.github/workflows/continuous-build.yml' + workflow_dispatch: jobs: static-build: From 9da58e0e64419f5268f29f0996b20116be92903f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 17:51:23 +0200 Subject: [PATCH 086/289] Trigger on push to branch "main" not "master" --- .github/workflows/continuous-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build.yml index 91327d6..38f3f2c 100644 --- a/.github/workflows/continuous-build.yml +++ b/.github/workflows/continuous-build.yml @@ -1,9 +1,10 @@ name: Continuous Build Linux on: + workflow_dispatch: push: branches: - - master + - main tags-ignore: - '*.*' paths: @@ -13,7 +14,6 @@ on: - 'include/**' - 'Makefile' - '.github/workflows/continuous-build.yml' - workflow_dispatch: jobs: static-build: From dfef4fdcc8ff362515a257d6d71295db3fc5a5e1 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 20:25:46 +0200 Subject: [PATCH 087/289] Update README.md --- README.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1730fad..88a7efb 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ Also needs a UTF8 locale and a font that covers: ## Installation -**Binary release (statically compiled, for kernel 3.2.0 and newer)** +**Binary release (statically compiled with musl, for kernel 2.6.39 and newer)** 1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** @@ -237,11 +237,14 @@ Also needs a UTF8 locale and a font that covers: The makefile also needs GNU coreutils and `sed` (should already be installed on any modern distribution). + For a `cmake` based build alternative see the [fork](https://github.com/jan-guenter/btop/tree/main) by @jan-guenter + 1. **Install dependencies (example for Ubuntu 21.04 Hirsute)** + Use gcc-10 g++-10 if gcc-11 isn't available + ``` bash sudo apt install coreutils sed git build-essential gcc-11 g++-11 - # use gcc-10 g++-10 if gcc-11 isn't available ``` 2. **Clone repository** @@ -255,7 +258,7 @@ Also needs a UTF8 locale and a font that covers: Append `STATIC=true` to `make` command for static compilation. - Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users when compiling statically. + Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users if compiling statically with glibc. Append `QUIET=true` for less verbose output. @@ -266,7 +269,9 @@ Also needs a UTF8 locale and a font that covers: Use `ADDFLAGS` variable for appending flags to both compiler and linker. - For example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + + If `g++` is linked to an older version of gcc on your system specify the correct version by appending `CXX=g++-10` or `CXX=g++-11`. ``` bash make @@ -274,9 +279,11 @@ Also needs a UTF8 locale and a font that covers: 4. **Install** + Append `PREFIX=/target/dir` to set target, default: `/usr/local` + + Notice! Only use "sudo" when installing to a NON user owned directory. + ``` bash - # use "make install PREFIX=/target/dir" to set target, default: /usr/local - # only use "sudo" when installing to a NON user owned directory sudo make install ``` @@ -284,9 +291,11 @@ Also needs a UTF8 locale and a font that covers: No need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems. + Run after make install and use same PREFIX if any was used at install. + + Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `root` + ``` bash - # run after make install and use same PREFIX if any was used at install - # set SU_USER and SU_GROUP to select user and group, default is root:root sudo make setuid ``` From ebcfd1c36728316c14921f85abf61de384b8bd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=BCnter?= Date: Sun, 17 Oct 2021 20:54:02 +0200 Subject: [PATCH 088/289] added a SVG version of the logo recreated logo.png form logo.svg for optimized png data --- Img/logo.png | Bin 11802 -> 1012 bytes Img/logo.svg | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 Img/logo.svg diff --git a/Img/logo.png b/Img/logo.png index 9704fb57afc7b658b640c95be03368293fde38ec..7e9cb7b88bbd2ae372d7ceb6ce82216dcacc8ad2 100644 GIT binary patch delta 1002 zcmbOg^M!qaL_G^L0|Nu&Us(?z#ggvm>&U>cv7h@-A}f%ukn9oU%fL{j#=y|f!octg zDAe$RfuYoZf#FpG1B2BJ1_tqhIlBUFfD&2(J|V6^`ac6hL_`D!2gh{=20uT)^$ZLy zE-vjr#a34F3=9Sa25M?R;~2_P=ac~{#`=;VzhDN3XE)M7yd-aT7lsa2uwyt2JR*yM zf(c;!A=~LZkilN!>Fdh=luJ;^n052(ci9XKOiMjo978H@y}hwF>yCo}djYG^wi>p;UNRv<>HrgWURi{x^PqS~~gsqSFftbZ4&*TD~H_)5Q1BBGYs0 zt|@j`{Sn^t;ShKJ9P_icSNyd3A5>pGchQN`E#~HnkKepH@48;rP2YKw;~vi4^sVaX z*1`uZ8nYh1$vU4cem36UtLkp>v)8v?$GNTP^;QeHD3Koi`+Mx=d$ac(e_a=!l^ODJ z#?>V}aTO2eUau~4f3o^da^?TK70aXok1o6#@_Su>3D9vL4*mAO*S$zX?bEBPOSWsg z*jboxU;o@2QxI3#+PUX$)~|ivYrj9;+d0>8?>X=1`fJ4-HZPY79w&v>$SQ*rB_^x*PWbt_wptayY+9cpT3v!solFe<}4^AKJZm;_LVl> zf79hc#QM0qM?TD&uO71d<0*N$xrN7H-wW@!xaVAbZJt5@&)ZT5KKJ+GsmxAh9FH})7eBdW)<2n7#Jolyn2=RVTq8#4iU>$a=n#7Ey-U%MgbslaiuB&QNRwWrD+1C%L5fI|A|fCN zNS7u}+6(GE$8+C#_xzm)4YnHXM_fDj?rV`;*nyUZ+fKWwQUKaqs zFh?I-;^Cmb_eKHU0Kg4OFMVT_F2sY;8Hup6b$~OX9yr4p;hwfu0D$LIWrl4MT_ZB& zVu1pTS>J)AtFUScjH@2fQ9$+zvq+>zYPbvA_sJ`I9tClEoUcn&pAes?QEt_Y8+vhM zOEoSt;I<1~9FKlFoZCA&Kc755zwYNh{piS7Z!xcH=-V-ZJ|_pV-EijB8Sff$e6mpG zn-jU|ox8o)v8DAcegEWqo%w;d9|Q5Rcdnmgd-Cksy;N{J?%hu}+KPNGmU8;PpAKKl zAc*zLYGcWZsI;#3?MW1GT}?U<6*&5E#Gp62e)Mi@yp_$*jO@zs=C0rAxAW>N-z$5i z{9OGFrQWv#{pda!6-wEevM`TH%WInOa!ldbG327?C zi|N?t@vK~)_onIH85!^Gb#|K7>-2W4HO^-Udu$U@lys+c)pocdlkjwGx?}h$?8AM* z@`+40TGmHq70J5M%1&eYu61|qDk~4bckLQYI4kQXyl5p3uyOAKTMs6@Z?ZJKjKt}o zY4O|cjo}{t6 zkMn<$9n{Iv8}f<27OHUFb}ja!41Gc9afprZ>Bda;;F+nf>%@6w+v|%;SIx?kiq(zGt5mDv*P}D;o}It8QxRXXW~iGqmJax%$G- zdU(jot7&_T5bi?QX)a${WQv7&o>76cONZ@6 zqYELKcDl_qjS=1sUNk;znGzu37o{nC8(r%XOB}4uu)&ror-JUgws1nBVMI{F)2vPP$PJ)(?veaUt7BOn7Zm z`R$WNjLIhm_)6VR;8o`#PZJ(Qj4fY~-v{Pm zdSbkK!qz$nMPHu8-(90&RFHs*NZ<^QCl|Y!y!IK-!7wBELa=N7uDwB&?BQMEJ4$-p z-Pw|3pxXiS8igkxAp@?{8d^qE6^89x6x;cZCNm&SOi5j@(*xCe>OXMv%s=NPxzpS0X7u3YE`MD(s#;0A%xzCNN} zXqbC3Z&)-zuTnf6ejJ|G1Cy{Hd8t0%nK=fQwR*dFg_>e6RJ5+teKLe|5c zdCs)Lu20QG@S22fzY*Xir7D&i)~#0@2`DI}5PrQPXg8duN;jwaIut)~(&phhz=;we zC*`7c$7JKI&`%mK@>-bFP3!GC9+wGCKS*ybpP_sSRm&8%@_^VvI+7`5DLv|xB-$8y z@VqpvCkev%P`SQSy+E(vv4=~Tc-)od4pnYUB|AZ$Zc8a|S&l+pqtPo#7MK^o)y-6%YdIuSrA#MNjolxyDn_HWW~x9 zE@SuwWHdzGZpXi&X@|kfi&Nf}+b1R**3DJ5&S%X#NU#7Po=sTh@GPOq1L3hlHp3qIdt4C{!RW194ygrvxzPPNvIe$;_Tf~cWQE~ zKo0qljb{(MsIJyDV{wG85@ZDJea5eeD+uF?xHTQA{b9J%Iv#3wr+7}mXkI>XG+Sxb zvapq?H><%lsw1GDGWk6T6^#NF^XQUqIsuQPOsFd6!g1WV>aEmF6{DL)o_$znF{TO*SAW-?@wbFD7YvSEL1$^Ff&mL=lE_dE0`c2JuR3i>&oad%B=n<>nJsinIZJ z&x+$xR&}H9j2ec5_l&uGbdBT~1Kr?;jJj#0A901czHuv^%6tehS;8jNJoi**G@=yh zR>GlWEa@wB$f9>n%4Et{v1r*lzV_yb?@<|c>Jb(t(ON_P2#2g4b^1~Q1=EwYtNFJ| zdV{uv40DCNY`RW6Mv}X0n3DlnP+ZL2C|U56e83Saf?;}3#5=J3#{Y; zEIeC=-%(>DQRfA2c6?;gb$%I}IH7;7H9^5BkD_OCo+-gO=*?sP7A)L5!V0`Kc#*8t ztW^ToN)wfL(_+WFmy1f@+&+95c`WDRn}W5vBoNAwnULx{6fE${Cxmlh-R5!d^IiHl z*3WTRK3MbbFuFfPYKaJ353h@|N};}Gx=SRI%xMZR_QQ--uMQhUWKPHXHHWPpyVD&} z3~;C$Wz)qd`{?+oSYyZMx`}q_%g{_@W8WJd4hVi@NH0$p(i95zu}c<{NmhF^y6mRS zmY+WTOkc60W(T#WMeW4Xq8><;T5$j9-IzLdHObTn)j^>|7|VOY*mT2JOxs-eIfj9! zAHDF+XyijpyulVs@xg!Js)1lUuDSaVvKkUGzWnrBDgrDv3g z0T!_#u+KycY9SFOUCEG(ox+%7dJLyk??Mqa1M8?x>^;iet!+9hDomN?d8*Bu?`D`u z?&nHNl3T3FLbMZgq|HkXa;rcI6acGtDPcJD19R`nSH$`PDHjRai3>G_{0kc!TsFxW z-vE#*nZ2@SuY%TBG<&AL%EeJMVX#R8L8TAj+hQn{ihL=RbXWWc@_^!DJuSlN zBrh#l#>TK6UQC0|hjl(g)o;B`#DWQ73o`=uIJtIfLI?1pZdU(n4(3EWvA^yP;?mB1Lw z1qJB@_>>Ah+;a(MASqyVjLs&BfyQ-`bH6HUQXAVQTV_NgybLiB;D6%qxDan;dw7{F zA8COoysgy&r&E4obQ|-+#n*axOMfsdb3|BNJJ3e9Oj*%dc1|`bNS;py((&K{x+%hq zNJGC)32r)9NP<-ra4EasGgsZW?P!UdNcK8p<=zTD1DfozZyZ$2=0}5IM;p7Xci`BY zuV%Fw0qwo)M1=Ifbw^g1C!5}5&l?u0Wh|HwpL$XA;}#gnH)_GFxL+`93-tYIYGnsD zjx4f)5%Z2@gwm|uuWeo4JXU-4JyBgJGS>lMEhLhWn+QLy-PxzZWr?G0&EeM6FY$ld zExjN!7%5{~5u))8Un>WTL@$VxIHQ9|XPD1VxAf6r=JCt=`xd$HDX7J8GL=iYxp8k( zoHg8X43+&JZ|=TWc(On%1tj4uXv^?d1PAK6?Ct zxgTgcf#`rDtMlo-R;%Cxk2B=$qTY)+1WTqAR6desYvi>ZmJII3%iwNvZD+<3>#~oN z+(+g9!?(cg*ub$ko5=V=x~bq+otURrlcZ{G<7U9=r}89qLt%B$kWP<~{$t*kIk6&k zU#LkOg4~^Cu*jPTr-s}10>%qIlV(yWFYzSH2!(1V${piYr7_~{)x9ja#&6@V_~{XG`Gm4+Urz;xEt=` z2A$Aa&0f?pU!{wxFN|dBIzf^6gt?Q;((sbc2F9hG=KG3$4@+DNu}m(MdjA;5yfFM| zt<@ybM@9cO2JnkbWy1EIDF~l_BS@1MP~I|5NF})lJJ-`6Xydtmt}@F+j;>j9-x#8f_ZKX!Xq6n}7&Ui3K=IELfvQ+rcdTKzJsK<7zQdG%f# zJT9iZ#pT8XdaYT$@X{~&lwK*uef`Zsj2Kk*Met;X0YaA|Vnu?;41!N--i6Pet`&-O zMFb=j&h0m7H(RO`z@ukSFR+swr`GW+4C&s*@rjh1-7U)lk6F64)759nSn+00%!kxH z#??!h7VwG4zEe_Z0v<)^_}rJd85W>2XdU0I$TrPvOqqH`?@ns2kr*$L*Rh(1Epm|1d+3v{$!cTJGn@(>%3NC z*$>FEq+|O}o+v(ui|*BG`9Pb;TcP~0LfT*<{jMXq{N}wLA2Vzq!uwj|9dFpTwHiZK zgJ64`(J{?xccvWt(Ku4)MN3$FT~^2AJF9pbhLMAYFh7gd6+M9vtQl?SsqSbB#X$m> zM=eK}0a+1#Z9nFLt+JAl2Y%eqG-#8-_c*IpBn@C(++#AgshjYPw>ru`zY>}&{-BGk zE5v_~V#JiGCY9@9OWmW_2^KR6>v%X}>RfL=V2JI7S}H#yx;7rLkPXZD+Nsc-1(SIcG(VZrvHKxv=zdzNOzJIoL?dU0 zMDZ)mUfaAnnH=*DA&;_Hy^(^#Ez|-!jVGZ+YoQ^H?OX0bVU}@nK4XtVnDDHx&T=v;VsH?Nqy4BU-f(0 zroN3kT1;Nymv_$vKjop2o!FZ*Z>B#Y1Ld05oHy?pr*6mX5Ni_&%7#a?NI-%MoH|!W zS#*T09v;v?LbkZi)fN<+dknn|530Ov&a|~X#Iz?Hh%d{zzePLXV2 z^nlmorozIEh~P@Bynwjo_27N;n|Ecd--t~JrV`=n!JEopViAt)jxiCl&s+a;uj8fv zSIO+gB!|^QmaB)pW?_m^lZ)I6*Pn2X5KbV%8ooZEt;;b@={O46drv!#SNqlX!t=B5 z_ic&8>_AlY7hRGrnzncq_9=V&nz_~>5iauV5wA~qRGRlVop+vtTkry=rv~1WF*z}B z%hu-wVsLArLa^r87X9HQ5`qwIgQ|1Y#F|?l$qI19*tAWh4x=g9NQYxhKr=UTRjE7U zt%~x9!x(e5uY7x_gX>_VbIZ*WiTz;J(0-&&qx*4$t?JxCgMUV zv{Oo$u8MpUzL{SuWar(Kf-)jqRy-hTVZ2>zXd@;Y;4U~E28$tCFv0(PzaT#c-(F7{ zw&Pgb>>rXQIVhyYar1FWbclE)=hQW0;%hgI;taMVcsQGCnEKHVt`c^d0k1TRAyx z6*;+o+#pBa7SHrelu+)}rU=yR0=CM! zW^`BH2L($-8{posHm5hcBD0O#H87wuqM+IW zba&Fy1}dXws_`tTu=Ft^)4iBm(*l>jH-*P`ECu3moIAI9LawcEvCJ`gR}Ft zxX5*ujp%t&AxRE-Jnb0c4$FIZ>L-yK^w&MDCVLCNM0R#rJ_}wVvSO8E&AuJSUZ!{~ zI{^>fyKY^l3$2tqCXjpJ$U5LwM%wi(1Urd@sUVE+&Qp>ibC%cgQG-y1bEcl0TdC?* zd{m;>wL`D=?F3)E-1?9aTB;(eOjy(S36Fqef5Y|+OK#`OgGjIx_k$~Yz+H_ zJ61hbK#21vtM4sK(s?1hBud1>lHz3ic) zFlH&qtKyzuG=U==1!44bbZ~M7drC0>;02?PFU3G+#vc%ry#%wdhBl)d0tsgn;1S>f zaVvP*y7MthUS$+V!mPl$@`}GG&?5T%$JrF>z2Mqx7fj}bMAUcU+SZb&Fx!5!{|V)@;uvxA%K?>60B;g_NxemlUdfM}}TH880|IoNZ|Bi$~|G+uBAsv2TU{E030q%%)#1+lV`xiV~{||+~ zUCs~kAAthPBcN`VEGqI6%$E*;VF;)#4E*Cz7|zEF6BH2UhKY*8xdlXc1-KzFK|XE} z2m%x46SCsv7ZUi5O2x?)1#yDHFR9SvJho^aD-m9}5Fa0e8_o|E;ue6wg}6mP`~uuU zB0|FaFiQvwCdBs}g%;8lUD^XQ=HmhVDbaR-psWx`M|8i~I>8Vgu76JH+d9JaP>{>8 z@e1*Sct!XG_(k|c1O<3S{sbAqk*?^vy=3JD@$mg*hC#uKXif;aerz2f)^MP+ll2c3 zwAWxcBpiZ5AoURl2MOj&uNW^?e{=(*_^&z#t0SP0%YOI)hQlsfwm(9}$oQjw!4T+W6eXBlA?|S4j})Ne_;U(s197s3 zqc_T5UGfjP?cWqEFBD`c$P2gPh6wP3xCP+CqTHgwf-r7~DEbWniSk1rR)1x8MOdLc zAV|23HM)(^c}6$Uk32K7|Ee>Nzv4Y?;Fm=N;^XB;Z(w{P`h0v~K4CDr)P820Q5<-= zHU49@;+LC;h6ecec!*zaE?||*g41(zc6P9ZBmWwwf7H$Yfcs7VSB?H}>c7K&YRe&< zAE3L{2BqcU^e@f-4e%#}x-As$U|m0UK` z|KaOb_5B}OKvVz6$iEfe|Agy5;rh2C@Na?tQ(gZF*S{5ke+&Gd>iYi{uB(4uE5n`8 zzxzDUSHcW>JtgR?XdFv5C3%4K<-6nni2ffS0N+{J#1#M_Aiw-z05USE&_Z04iiQI2 z5*{4|E!n&*A3gwZC0RvYM&Hw7bGqG$R*9r%M<*dj>m?7So(V+dNp#0xh^`689#v^j zvfni$oiY+G{1i;JFmvNQCTtINNRC@!+{u=^Qgi93F#*!zAv^$fW)y}rX&wO}3eOy%Ex&>pkiX?f zfc&<-y}d@7+tbq%?LS?7&^Uav%#}nmd0UX`T3lNb&je5Xd+xLHOSzr)V%FEQv$Gfe z*+a`=k5Y?%2`@&ohL+8e>Fsg|&hl^+!gv75QNvdN3V*Q~$Ix=F_3D8B%og;Nd*@(l zd8nQ>%MUgA5GC}OKBd1%y+qH1C$)Y_G0&|y&7@$}9-Q^Y@>v5}-}-b$$lxey)^$xn z!Ji{!P`z36p_%ub<_!P^X%iqf;=ftS|H>znrRk_P&3(O|GRx}uhw>izjGp4AZ&jjC z2Nky#ICaYTowM7PXOzZf`8R;Yx@!U|Gje0Yl!>!LtwNGh*E3zbd`4++D^}*Y)xUls z7p$0-xA#qSi^+07+ur|KvTljW8bf|~m2x37))wAWk5H>l{un!%*>b7P{;iaj!Hx$_ z*@u$(-?Cl&d4GbFLaLN6KJLT^wrjk**7pr()zs9~Cd=G%;*stfu-x)0au&Ms(fjM! zzJY4i?NaZ#V1b|cVV3=UkxE*?jls&Aqw)_dsAmbEEZT5=RX>8pcgs5^ONNGqls@U< zXPE?p(oM%1QOWzHyt`J>mC1)1OOl z$}ukK9u+u`RA{XFlwfogxYe#_(Sw@X_ewuVxP?;qe(~u1?ENRu-Z-}7h71PtS@rsh z&!!$|rs%C_Lp#1%blxQMm)TZ8cjI6E*EtwH8{RN&wCE=We)9H3+LSFJ!q0ddz3+CD zfuDyNW(`Po3JVK|&p5Faj3~P|1IPVA8)6xsr!xvgwu&+fGSjMV+z@@s^`4<&^q+h2 zkN$_z&e~ALD%P`tj)dAbCt5)KnTIcQI;UM%@>Yf^NvoH?Zs$w9@Cb8j{M@o$2AOUA zrtPy5wYW1{eyjS6!DN5qL~eF4jK>4>{0{_r!~ElQ Z|3JzzZ_hlf4!L_NQ&G^AuadnV^j~=cNj?Ao diff --git a/Img/logo.svg b/Img/logo.svg new file mode 100644 index 0000000..951858f --- /dev/null +++ b/Img/logo.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4cacdf28fed74c97206b5c54d83889b246f306c6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 22:26:43 +0200 Subject: [PATCH 089/289] Added: Displayed battery selectable in options menu --- src/btop_config.cpp | 5 ++ src/btop_config.hpp | 1 + src/btop_menu.cpp | 10 +++- src/linux/btop_collect.cpp | 100 +++++++++++++++++++++++-------------- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 09dead3..ca3e66a 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -170,6 +170,8 @@ namespace Config { {"show_battery", "#* Show battery stats in top right if battery is present."}, + {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, + {"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n" "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."} }; @@ -187,6 +189,7 @@ namespace Config { {"cpu_graph_upper", "total"}, {"cpu_graph_lower", "total"}, {"cpu_sensor", "Auto"}, + {"selected_battery", "Auto"}, {"cpu_core_map", ""}, {"temp_scale", "celsius"}, {"clock_format", "%X"}, @@ -265,6 +268,8 @@ namespace Config { fs::path conf_dir; fs::path conf_file; + vector available_batteries = {"Auto"}; + vector current_boxes; vector preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"}; int current_preset = -1; diff --git a/src/btop_config.hpp b/src/btop_config.hpp index fd08d92..b99e26f 100644 --- a/src/btop_config.hpp +++ b/src/btop_config.hpp @@ -45,6 +45,7 @@ namespace Config { extern vector current_boxes; extern vector preset_list; + extern vector available_batteries; extern int current_preset; //* Check if string only contains space seperated valid names for boxes diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 6c9eb8d..500a86e 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -270,6 +270,13 @@ namespace Menu { "", "Show battery stats in the top right corner", "if a battery is present."}, + {"selected_battery", + "Select battery.", + "", + "Which battery to use if multiple are present.", + "Can be both batteries and UPS.", + "", + "\"Auto\" for auto detection."}, {"log_level", "Set loglevel for error.log", "", @@ -962,7 +969,8 @@ namespace Menu { {"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)}, {"cpu_graph_upper", std::cref(Cpu::available_fields)}, {"cpu_graph_lower", std::cref(Cpu::available_fields)}, - {"cpu_sensor", std::cref(Cpu::available_sensors)} + {"cpu_sensor", std::cref(Cpu::available_sensors)}, + {"selected_battery", std::cref(Config::available_batteries)}, }; auto& tty_mode = Config::getB("tty_mode"); auto& vim_keys = Config::getB("vim_keys"); diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index a5c745d..fdaaf9a 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -468,75 +468,99 @@ namespace Cpu { return core_map; } + struct battery { + fs::path base_dir, energy_now, energy_full, power_now, status, online; + string device_type; + bool use_energy = true; + }; + auto get_battery() -> tuple { if (not has_battery) return {0, 0, ""}; - static fs::path bat_dir, energy_now_path, energy_full_path, power_now_path, status_path, online_path; - static bool use_energy = true; + static string auto_sel; + static unordered_flat_map batteries; //? Get paths to needed files and check for valid values on first run - if (bat_dir.empty() and has_battery) { + if (batteries.empty() and has_battery) { if (fs::exists("/sys/class/power_supply")) { for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { //? Only consider online power supplies of type Battery or UPS //? see kernel docs for details on the file structure and contents //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power + battery new_bat; + fs::path bat_dir; try { if (not d.is_directory() - or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "type") or not fs::exists(d.path() / "present") or stoi(readfile(d.path() / "present")) != 1) continue; - string type = readfile(d.path() / "type"); - if (type == "Battery" or type == "UPS") { + string dev_type = readfile(d.path() / "type"); + if (is_in(dev_type, "Battery", "UPS")) { bat_dir = d.path(); - break; + new_bat.base_dir = d.path(); + new_bat.device_type = dev_type; } } catch (...) { //? skip power supplies not conforming to the kernel standard continue; } + + if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; + else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; + else new_bat.use_energy = false; + + if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; + else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; + else new_bat.use_energy = false; + + if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { + continue; + } + + if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; + else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; + + if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; + else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; + + batteries[bat_dir.filename()] = new_bat; + Config::available_batteries.push_back(bat_dir.filename()); } } - if (bat_dir.empty()) { + if (batteries.empty()) { has_battery = false; return {0, 0, ""}; } - else { - if (fs::exists(bat_dir / "energy_now")) energy_now_path = bat_dir / "energy_now"; - else if (fs::exists(bat_dir / "charge_now")) energy_now_path = bat_dir / "charge_now"; - else use_energy = false; - - if (fs::exists(bat_dir / "energy_full")) energy_full_path = bat_dir / "energy_full"; - else if (fs::exists(bat_dir / "charge_full")) energy_full_path = bat_dir / "charge_full"; - else use_energy = false; - - if (not use_energy and not fs::exists(bat_dir / "capacity")) { - has_battery = false; - return {0, 0, ""}; - } - - if (fs::exists(bat_dir / "power_now")) power_now_path = bat_dir / "power_now"; - else if (fs::exists(bat_dir / "current_now")) power_now_path = bat_dir / "current_now"; - - if (fs::exists(bat_dir / "AC0/online")) online_path = bat_dir / "AC0/online"; - else if (fs::exists(bat_dir / "AC/online")) online_path = bat_dir / "AC/online"; - } } + auto& battery_sel = Config::getS("selected_battery"); + + if ((battery_sel == "Auto" and auto_sel.empty())) { + for (auto& [name, bat] : batteries) { + if (bat.device_type == "Battery") { + auto_sel = name; + break; + } + } + if (auto_sel.empty()) auto_sel = batteries.begin()->first; + } + + auto& b = (battery_sel != "Auto" and batteries.contains(battery_sel) ? batteries.at(battery_sel) : batteries.at(auto_sel)); + int percent = -1; long seconds = -1; //? Try to get battery percentage - if (use_energy) { + if (b.use_energy) { try { - percent = round(100.0 * stoll(readfile(energy_now_path, "-1")) / stoll(readfile(energy_full_path, "1"))); + percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1"))); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } if (percent < 0) { try { - percent = stoll(readfile(bat_dir / "capacity", "-1")); + percent = stoll(readfile(b.base_dir / "capacity", "-1")); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } @@ -547,9 +571,9 @@ namespace Cpu { } //? Get charging/discharging status - string status = str_to_lower(readfile(bat_dir / "status", "unknown")); - if (status == "unknown" and not online_path.empty()) { - const auto online = readfile(online_path, "0"); + string status = str_to_lower(readfile(b.base_dir / "status", "unknown")); + if (status == "unknown" and not b.online.empty()) { + const auto online = readfile(b.online, "0"); if (online == "1" and percent < 100) status = "charging"; else if (online == "1") status = "full"; else status = "discharging"; @@ -557,16 +581,16 @@ namespace Cpu { //? Get seconds to empty if (not is_in(status, "charging", "full")) { - if (use_energy and not power_now_path.empty()) { + if (b.use_energy and not b.power_now.empty()) { try { - seconds = round((double)stoll(readfile(energy_now_path, "0")) / stoll(readfile(power_now_path, "1")) * 3600); + seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } - if (seconds < 0 and fs::exists(bat_dir / "time_to_empty")) { + if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { try { - seconds = stoll(readfile(bat_dir / "time_to_empty", "0")) * 60; + seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } From 7d89c75abb3771005ed6fbbb56aa75859cf4f00b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 17 Oct 2021 22:55:36 +0200 Subject: [PATCH 090/289] FIxed: Battery error if non existant battery named is entered --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index fdaaf9a..2a5a31d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -535,7 +535,7 @@ namespace Cpu { auto& battery_sel = Config::getS("selected_battery"); - if ((battery_sel == "Auto" and auto_sel.empty())) { + if (auto_sel.empty()) { for (auto& [name, bat] : batteries) { if (bat.device_type == "Battery") { auto_sel = name; From 997bfd2712c87200019e91204952beda2db0498e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 18 Oct 2021 18:56:27 +0200 Subject: [PATCH 091/289] v1.0.17 New features and bug fixes --- CHANGELOG.md | 12 ++++++++++++ src/btop.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f1507..7fdd495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v1.0.17 + +* Changed: Reverted mutexes back to custom atomic bool based locks + +* Added: Static binaries switched to building with musl + more platforms, by @jan-guenter + +* Fixed: Improved battery detection, by @jan-guenter + +* Added: Displayed battery selectable in options menu + +* Fixed: Battery error if non existent battery named is entered + ## v1.0.16 * Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep diff --git a/src/btop.cpp b/src/btop.cpp index d58991d..872c9b1 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.16"; + const string Version = "1.0.17"; int coreCount; string overlay; From f15c2fdcf6d9a40da84387871045f91249086bb7 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 18 Oct 2021 20:55:06 +0200 Subject: [PATCH 092/289] Fixed: Makefile g++ -dumpmachine failure to get platform on some distros --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e580ee0..3db602a 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,11 @@ endif PREFIX ?= /usr/local -#? Detect PLATFORM and ARCH from gcc if not set -PLATFORM ?= $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') +#? Detect PLATFORM and ARCH from uname/gcc if not set +PLATFORM ?= $(shell uname -s || echo unknown) +ifneq ($(filter unknown darwin, $(PLATFORM)),) + override PLATFORM := $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') +endif ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') From a0ee4046c6e98e8f215400ea905e975551f8e23b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 19 Oct 2021 17:29:57 +0200 Subject: [PATCH 093/289] v1.0.18 Fix for build platform detection --- CHANGELOG.md | 4 ++++ src/btop.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fdd495..197882f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.18 + +* Fixed: Makefile g++ -dumpmachine failure to get platform on some distros + ## v1.0.17 * Changed: Reverted mutexes back to custom atomic bool based locks diff --git a/src/btop.cpp b/src/btop.cpp index 872c9b1..cbc37b0 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.17"; + const string Version = "1.0.18"; int coreCount; string overlay; From a046f759497e6c05b3b9299b9f435cf219b50097 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 21 Oct 2021 08:16:52 +0200 Subject: [PATCH 094/289] Fixed: Makefile now tests compiler flag compatibility --- Makefile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 3db602a..af21247 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -#* Btop++ makefile v1.2 +#* Btop++ makefile v1.4 -BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.3\033[0m +BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.4\033[0m override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") @@ -23,17 +23,15 @@ ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') -#? Only enable fcf-protection if on x86_64 -ifneq ($(filter x86_64 i%86, $(ARCH)),) - override ADDFLAGS += -fcf-protection -endif +#? Any flags added to TESTFLAGS must not contain whitespace for the testing to work +override TESTFLAGS := -fexceptions -fcf-protection -fstack-protector -fstack-clash-protection -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS ifeq ($(STATIC),true) - override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings + override TESTFLAGS += -DSTATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings endif ifeq ($(STRIP),true) - override ADDFLAGS += -s + override TESTFLAGS += -s endif #? Compiler and Linker @@ -66,7 +64,7 @@ $(error $(shell printf "\033[1;91mERROR: \033[97mUnsupported platform ($(PLATFOR endif #? Use all CPU cores (will only be set if using Make 4.3+) -MAKEFLAGS := --jobs=$(THREADS) +MAKEFLAGS := --jobs=$(THREADS) ifeq ($(THREADS),1) override THREADS := auto endif @@ -80,11 +78,14 @@ SRCEXT := cpp DEPEXT := d OBJEXT := o +#? Filter out unsupported compiler flags +override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main() {}" | $(CXX) -o /dev/null $(flag) -x c++ - >/dev/null 2>&1 && echo $(flag) || true))) + #? Flags, Libraries and Includes override REQFLAGS := -std=c++20 WARNFLAGS := -Wall -Wextra -pedantic OPTFLAGS ?= -O2 -ftree-loop-vectorize -flto=$(THREADS) -LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector -fstack-clash-protection $(ADDFLAGS) +LDCXXFLAGS := -pthread $(GOODFLAGS) $(ADDFLAGS) override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) INC := -I$(INCDIR) -I$(SRCDIR) @@ -114,7 +115,6 @@ info: @printf "\033[1;95mLDFLAGS \033[1;92m+| \033[0;37m\$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n" info-quiet: - @printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n" help: From a1ba01980f877c33dcb0a2f9855ac664c1b5a522 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 21 Oct 2021 16:54:18 +0200 Subject: [PATCH 095/289] v1.0.19 Improved build system --- CHANGELOG.md | 4 ++++ src/btop.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 197882f..6826ef8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.19 + +* Fixed: Makefile now tests compiler flag compatibility + ## v1.0.18 * Fixed: Makefile g++ -dumpmachine failure to get platform on some distros diff --git a/src/btop.cpp b/src/btop.cpp index cbc37b0..bfd1cb7 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.18"; + const string Version = "1.0.19"; int coreCount; string overlay; From 496283ea1a36a81ad1d09fbc8673015e9cf2c50f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 24 Oct 2021 01:16:15 +0200 Subject: [PATCH 096/289] Moved flags not needing to be tested --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index af21247..7fe9f4d 100644 --- a/Makefile +++ b/Makefile @@ -24,14 +24,14 @@ ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Any flags added to TESTFLAGS must not contain whitespace for the testing to work -override TESTFLAGS := -fexceptions -fcf-protection -fstack-protector -fstack-clash-protection -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS +override TESTFLAGS := -fexceptions -fcf-protection -fstack-protector -fstack-clash-protection ifeq ($(STATIC),true) - override TESTFLAGS += -DSTATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings + override ADDFLAGS += -DSTATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings endif ifeq ($(STRIP),true) - override TESTFLAGS += -s + override ADDFLAGS += -s endif #? Compiler and Linker @@ -84,8 +84,8 @@ override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main #? Flags, Libraries and Includes override REQFLAGS := -std=c++20 WARNFLAGS := -Wall -Wextra -pedantic -OPTFLAGS ?= -O2 -ftree-loop-vectorize -flto=$(THREADS) -LDCXXFLAGS := -pthread $(GOODFLAGS) $(ADDFLAGS) +OPTFLAGS := -O2 -ftree-loop-vectorize -flto=$(THREADS) +LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS $(GOODFLAGS) $(ADDFLAGS) override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) INC := -I$(INCDIR) -I$(SRCDIR) From 602cef87600437a6812b399e0a443bf68847fa95 Mon Sep 17 00:00:00 2001 From: CS Adnan Date: Mon, 25 Oct 2021 00:17:54 +0600 Subject: [PATCH 097/289] add support for AMD Ryzen 5000 temp sensor --- src/linux/btop_collect.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 2a5a31d..dee61e6 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -317,6 +317,11 @@ namespace Cpu { cpu_sensor = name; break; } + if (s_contains(str_to_lower(name), "k10temp")) { + Logger::warning("Using k10temp sensors for AMD."); + cpu_sensor = name; + break; + } } if (cpu_sensor.empty()) { cpu_sensor = found_sensors.begin()->first; From 73a0ad73c0c59c8dc942b92917ae0af3f32b131e Mon Sep 17 00:00:00 2001 From: CS Adnan Date: Tue, 26 Oct 2021 11:26:52 +0600 Subject: [PATCH 098/289] remove log warning + extra if for k10temp --- src/linux/btop_collect.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index dee61e6..761e7e4 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -313,12 +313,7 @@ namespace Cpu { if (not got_coretemp or core_sensors.empty()) cpu_temp_only = true; if (cpu_sensor.empty() and not found_sensors.empty()) { for (const auto& [name, sensor] : found_sensors) { - if (s_contains(str_to_lower(name), "cpu")) { - cpu_sensor = name; - break; - } - if (s_contains(str_to_lower(name), "k10temp")) { - Logger::warning("Using k10temp sensors for AMD."); + if (s_contains(str_to_lower(name), "cpu") or s_contains(str_to_lower(name), "k10temp")) { cpu_sensor = name; break; } From 1e374b1edea74692f377b67a084875985e7c1575 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 Oct 2021 17:31:13 +0200 Subject: [PATCH 099/289] Removed bad code --- src/btop_tools.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 0d8705b..dec631b 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -46,7 +46,6 @@ namespace Term { atomic width = 0; atomic height = 0; string current_tty; - char* custombuf; namespace { struct termios initial_settings; @@ -122,9 +121,6 @@ namespace Term { linebuffered(false); refresh(); - //? Set 1MB buffer for cout - std::cout.rdbuf()->pubsetbuf(custombuf, 1048576); - cout << alt_screen << hide_cursor << mouse_on << flush; Global::resized = false; } From 36c74fb08a9f64500a7339fc400fdbb74d3166b7 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 Oct 2021 22:56:19 +0200 Subject: [PATCH 100/289] Changed: Regex for Fx::uncolor() changed to string search and replace --- src/btop_tools.cpp | 19 +++++++++++++++++++ src/btop_tools.hpp | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index dec631b..977aa5f 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -139,6 +139,25 @@ namespace Term { //? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- +namespace Fx { + string uncolor(const string& s) { + string out = s; + for (size_t offset = 0, start_pos = 0, end_pos = 0, next_pos = 0;;) { + if ((start_pos = next_pos > 0 ? next_pos : out.find('\x1b', offset)) == string::npos) + break; + offset = start_pos; + if ((end_pos = out.find('m', offset)) == string::npos) + break; + else if (next_pos = out.find('\x1b', offset + 1); end_pos - start_pos > next_pos - start_pos) + continue; + out.replace(start_pos, (end_pos - start_pos) + 1, ""); + next_pos = 0; + } + out.shrink_to_fit(); + return out; + } +} + namespace Tools { atomic active_locks (0); diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index d68d1f3..f802c77 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -64,7 +64,7 @@ namespace Fx { const regex color_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m){1}"); //* Return a string with all colors and text styling removed - inline string uncolor(const string& s) { return regex_replace(s, color_regex, ""); } + string uncolor(const string& s); } From 587005f094ba1b1b4b7da6f8289d621138f01815 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 Oct 2021 23:41:40 +0200 Subject: [PATCH 101/289] v1.0.20 Bug fixes --- CHANGELOG.md | 10 ++++++++++ src/btop.cpp | 2 +- src/btop_tools.cpp | 6 +++--- src/btop_tools.hpp | 9 +-------- src/linux/btop_collect.cpp | 6 ++---- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6826ef8..46c4310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.0.20 + +* Added: Improved cpu sensor detection for Ryzen Mobile, by @adnanpri + +* Changed: Updated makefile + +* Changed: Regex for Fx::uncolor() changed to string search and replace + +* Changed: Removed all use of regex with dedicated string functions + ## v1.0.19 * Fixed: Makefile now tests compiler flag compatibility diff --git a/src/btop.cpp b/src/btop.cpp index bfd1cb7..208da4a 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.19"; + const string Version = "1.0.20"; int coreCount; string overlay; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 977aa5f..8778dbe 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -145,12 +145,12 @@ namespace Fx { for (size_t offset = 0, start_pos = 0, end_pos = 0, next_pos = 0;;) { if ((start_pos = next_pos > 0 ? next_pos : out.find('\x1b', offset)) == string::npos) break; - offset = start_pos; + offset = ++start_pos; if ((end_pos = out.find('m', offset)) == string::npos) break; - else if (next_pos = out.find('\x1b', offset + 1); end_pos - start_pos > next_pos - start_pos) + else if (next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos - start_pos > next_pos - start_pos) continue; - out.replace(start_pos, (end_pos - start_pos) + 1, ""); + out.replace(start_pos, end_pos - start_pos, ""); next_pos = 0; } out.shrink_to_fit(); diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index f802c77..c9f9b74 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -21,7 +21,6 @@ tab-size = 4 #include #include #include -#include #include #include #include @@ -30,7 +29,7 @@ tab-size = 4 #include #include -using std::string, std::vector, std::atomic, std::to_string, std::regex, std::tuple, std::array; +using std::string, std::vector, std::atomic, std::to_string, std::tuple, std::array; //? ------------------------------------------------- NAMESPACES ------------------------------------------------------ @@ -57,12 +56,6 @@ namespace Fx { //* Reset text effects and restore theme foregrund and background color extern string reset; - //* Regex for matching color, style and cursor move escape sequences - const regex escape_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m|f|s|u|C|D|A|B){1}"); - - //* Regex for matching only color and style escape sequences - const regex color_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m){1}"); - //* Return a string with all colors and text styling removed string uncolor(const string& s); diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 761e7e4..1e5c0dc 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -21,7 +21,6 @@ tab-size = 4 #include #include #include -#include #include #include #include @@ -217,9 +216,8 @@ namespace Cpu { name += n + ' '; } name.pop_back(); - for (const auto& reg : {regex("Processor"), regex("CPU"), regex("\\(R\\)"), regex("\\(TM\\)"), regex("Intel"), - regex("AMD"), regex("Core"), regex("\\d?\\.?\\d+[mMgG][hH][zZ]")}) { - name = std::regex_replace(name, reg, ""); + for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) { + name = s_replace(name, replace, ""); } name = trim(name); } From 9ecea2c94e9d5c410aa5e571b11c203d9baf7928 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 Oct 2021 23:50:28 +0200 Subject: [PATCH 102/289] Fixed: Removed extra spaces in cpu name --- src/linux/btop_collect.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 1e5c0dc..50a41d6 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -218,6 +218,7 @@ namespace Cpu { name.pop_back(); for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) { name = s_replace(name, replace, ""); + name = s_replace(name, " ", " "); } name = trim(name); } From a6fd835ff3d178c07deeaa6a4bfb8e8956d33ce6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 27 Oct 2021 20:19:43 +0200 Subject: [PATCH 103/289] Added: / as alternative bind for filter --- src/btop_input.cpp | 2 +- src/btop_menu.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index df9e35a..2d2a854 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -266,7 +266,7 @@ namespace Input { cur_i = 0; Config::set("proc_sorting", Proc::sort_vector.at(cur_i)); } - else if (key == "f") { + else if (is_in(key, "f", "/")) { Config::flip("proc_filtering"); Proc::filter = { Config::getS("proc_filter") }; old_filter = Proc::filter.text; diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 500a86e..f4bcc11 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -126,7 +126,7 @@ namespace Menu { {"z", "Toggle totals reset for current network device"}, {"a", "Toggle auto scaling for the network graphs."}, {"y", "Toggle synced scaling mode for network graphs."}, - {"f", "To enter a process filter."}, + {"f, /", "To enter a process filter."}, {"delete", "Clear any entered filter."}, {"c", "Toggle per-core cpu usage of processes."}, {"r", "Reverse sorting order in processes box."}, From 98ae5e8f460769a12253c40566b0b609213e5093 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 30 Oct 2021 18:17:18 +0200 Subject: [PATCH 104/289] Updated README.md --- README.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 88a7efb..c6f6c68 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,38 @@ ### Under development +##### 30 October 2021 + +Work on the OSX and FreeBSD branches, both initiated and mostly worked on by [@joske](https://github.com/joske), will likely be completed in the coming weeks. +The OSX branch has some memory leaks that needs to be sorted out and both have some issues with the processes cpu usage calculation and other smaller issues that needs fixing. + +If you want to help out, test for bugs/fix bugs or just try out the branches: + +**OSX** +```bash +# Install and use Homebrew or MacPorts package managers for easy dependency installation +brew install coreutils make gcc@11 +git clone https://github.com/aristocratos/btop.git +cd btop +git checkout osx +gmake +``` + +**FreeBSD** +```bash +sudo pkg install gmake gcc11 coreutils git +git clone https://github.com/aristocratos/btop.git +cd btop +git checkout freebsd +gmake +``` + +Note that GNU make (`gmake`) is recommended but not required for OSX but it is required on FreeBSD. + + ##### 6 October 2021 -OsX development have been started by @joske , big thanks :) +OsX development have been started by [@joske](https://github.com/joske), big thanks :) See branch [OSX](https://github.com/aristocratos/btop/tree/OSX) for current progress. ##### 18 September 2021 From 0f566ae688f4b58f6b0dc52a7ec80f870f00a69a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 2 Nov 2021 21:10:41 +0100 Subject: [PATCH 105/289] Fixed: Security issue when running with SUID bit set --- src/btop.cpp | 27 +++++++++++++++++++++++++++ src/btop_config.cpp | 1 + src/btop_shared.hpp | 2 ++ src/btop_tools.cpp | 13 +++++++++++++ 4 files changed, 43 insertions(+) diff --git a/src/btop.cpp b/src/btop.cpp index 208da4a..c6a7b9c 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -64,6 +64,7 @@ namespace Global { string fg_green = "\x1b[1;92m"; string fg_red = "\x1b[0;91m"; + uid_t real_uid, set_uid; fs::path self_path; @@ -298,6 +299,18 @@ namespace Runner { ~thread_lock() { if (status == 0) pthread_mutex_unlock(&pt_mutex); } }; + //* Wrapper for raising priviliges when using SUID bit + class gain_priv { + int status = -1; + public: + gain_priv() { + if (Global::real_uid != Global::set_uid) this->status = seteuid(Global::set_uid); + } + ~gain_priv() { + if (status == 0) status = seteuid(Global::real_uid); + } + }; + string output; string empty_bg; bool pause_output = false; @@ -385,6 +398,9 @@ namespace Runner { //? Atomic lock used for blocking non thread-safe actions in main thread atomic_lock lck(active); + //? Set effective user if SUID bit is set + gain_priv powers{}; + auto& conf = current_conf; //! DEBUG stats @@ -616,6 +632,17 @@ int main(int argc, char **argv) { Global::start_time = time_s(); + //? Save real and effective userid's and drop priviliges until needed if running with SUID bit set + Global::real_uid = getuid(); + Global::set_uid = geteuid(); + if (Global::real_uid != Global::set_uid) { + if (seteuid(Global::real_uid) != 0) { + Global::real_uid = Global::set_uid; + Global::exit_error_msg = "Failed to change effective user ID. Unset btop SUID bit to ensure security on this system. Quitting!"; + clean_quit(1); + } + } + //? Call argument parser if launched with arguments if (argc > 1) argumentParser(argc, argv); diff --git a/src/btop_config.cpp b/src/btop_config.cpp index ca3e66a..b0edcde 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -589,6 +589,7 @@ namespace Config { void write() { if (conf_file.empty() or not write_new) return; Logger::debug("Writing new config file"); + if (geteuid() != Global::real_uid and seteuid(Global::real_uid) != 0) return; std::ofstream cwrite(conf_file, std::ios::trunc); if (cwrite.good()) { cwrite << "#? Config file for btop v. " << Global::Version; diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 832208c..b5eaf6b 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -27,6 +27,7 @@ tab-size = 4 #include #include #include +#include using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std::atomic, std::array, std::tuple; @@ -43,6 +44,7 @@ namespace Global { extern atomic resized; extern string overlay; extern string clock; + extern uid_t real_uid, set_uid; } namespace Runner { diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 8778dbe..061e43f 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -406,6 +406,18 @@ namespace Logger { size_t loglevel; fs::path logfile; + //* Wrapper for lowering priviliges if using SUID bit and currently isn't using real userid + class lose_priv { + int status = -1; + public: + lose_priv() { + if (geteuid() != Global::real_uid) this->status = seteuid(Global::real_uid); + } + ~lose_priv() { + if (status == 0) status = seteuid(Global::set_uid); + } + }; + void set(const string& level) { loglevel = v_index(log_levels, level); } @@ -413,6 +425,7 @@ namespace Logger { void log_write(const size_t level, const string& msg) { if (loglevel < level or logfile.empty()) return; atomic_lock lck(busy, true); + lose_priv neutered{}; std::error_code ec; try { if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) { From 6383ef8704b01e331121bda16a83472ead99ae21 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 2 Nov 2021 21:18:44 +0100 Subject: [PATCH 106/289] v1.0.21 Security and bug fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46c4310..56e530f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.0.21 + +* Fixed: Removed extra spaces in cpu name + +* Added: / as alternative bind for filter + +* Fixed: Security issue when running with SUID bit set + ## v1.0.20 * Added: Improved cpu sensor detection for Ryzen Mobile, by @adnanpri diff --git a/src/btop.cpp b/src/btop.cpp index c6a7b9c..ee95cfb 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.20"; + const string Version = "1.0.21"; int coreCount; string overlay; From 77244dd65f5528f5a9ade3cd7d04c0120f763c8b Mon Sep 17 00:00:00 2001 From: Denis Yaremov Date: Wed, 3 Nov 2021 14:04:31 +0200 Subject: [PATCH 107/289] Update to Readme.md There seems to be a problem with `osx => OSX` branch casing, the command doesn't work by just copy and pasting on osx --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6f6c68..0ae48df 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ If you want to help out, test for bugs/fix bugs or just try out the branches: brew install coreutils make gcc@11 git clone https://github.com/aristocratos/btop.git cd btop -git checkout osx +git checkout OSX gmake ``` From 156998073a9710a288fcb6ca8fe4fee226b04bc4 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 3 Nov 2021 21:01:34 +0100 Subject: [PATCH 108/289] Fixed: Bad values for disks and network on 32-bit --- src/linux/btop_collect.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 50a41d6..7e34de7 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -904,8 +904,8 @@ namespace Mem { //? Get disk/partition stats for (auto& [mountpoint, disk] : disks) { if (std::error_code ec; not fs::exists(mountpoint, ec)) continue; - struct statvfs vfs; - if (statvfs(mountpoint.c_str(), &vfs) < 0) { + struct statvfs64 vfs; + if (statvfs64(mountpoint.c_str(), &vfs) < 0) { Logger::warning("Failed to get disk/partition stats with statvfs() for: " + mountpoint); continue; } @@ -1065,7 +1065,7 @@ namespace Net { auto& bandwidth = net.at(iface).bandwidth.at(dir); uint64_t val = saved_stat.last; - try { val = max((uint64_t)stoul(readfile(sys_file, "0")), val); } + try { val = max((uint64_t)stoull(readfile(sys_file, "0")), val); } catch (const std::invalid_argument&) {} catch (const std::out_of_range&) {} From 2107f70e716fd3eb9b229eb6b8c56398cd5228d6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 3 Nov 2021 22:01:49 +0100 Subject: [PATCH 109/289] Updated README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0ae48df..3286929 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,8 @@ Also needs a UTF8 locale and a font that covers: 1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** + **Notice! Use x86_64 for 64-bit x86 systems, i486 and i686 are 32-bit!** + 2. **Install (from created folder)** * **Run install.sh or:** From 45169223ebb6ed792b92e8c74bdf5b281712d1e0 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 3 Nov 2021 22:11:31 +0100 Subject: [PATCH 110/289] v1.0.22 Fixed 32-bit --- CHANGELOG.md | 4 ++++ src/btop.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56e530f..4d03067 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.22 + +* Fixed: Bad values for disks and network on 32-bit + ## v1.0.21 * Fixed: Removed extra spaces in cpu name diff --git a/src/btop.cpp b/src/btop.cpp index ee95cfb..5034629 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.21"; + const string Version = "1.0.22"; int coreCount; string overlay; From 9af8e0074d8e1c81bbde6b973f5c9dddb8e577c0 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 4 Nov 2021 12:36:23 +0100 Subject: [PATCH 111/289] Fixed: Config parser missing first value when not including version header --- src/btop_config.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index b0edcde..6284084 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -530,9 +530,8 @@ namespace Config { vector valid_names; for (auto &n : descriptions) valid_names.push_back(n[0]); - string v_string; - getline(cread, v_string, '\n'); - if (not s_contains(v_string, Global::Version)) + + if (string v_string; cread.peek() != '#' or (getline(cread, v_string, '\n') and not s_contains(v_string, Global::Version))) write_new = true; while (not cread.eof()) { cread >> std::ws; From a6dba19817f8f69ca8b07384eb4524fbde5d9725 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 4 Nov 2021 12:44:11 +0100 Subject: [PATCH 112/289] Fixed: Vim keys menu lists selection --- src/btop_menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index f4bcc11..fa7f6a5 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -1142,8 +1142,8 @@ namespace Menu { auto& optList = optionsList.at(option).get(); int i = v_index(optList, Config::getS(option)); - if (key == "right" and ++i >= (int)optList.size()) i = 0; - else if (key == "left" and --i < 0) i = optList.size() - 1; + if ((key == "right" or (vim_keys and key == "l")) and ++i >= (int)optList.size()) i = 0; + else if ((key == "left" or (vim_keys and key == "h")) and --i < 0) i = optList.size() - 1; Config::set(option, optList.at(i)); if (option == "color_theme") From e4ac3d9b21549c8808ea5e3ada23924b91f72447 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 12:46:18 +0100 Subject: [PATCH 113/289] Fixed: Stall when clearing input queue on exit and queue is >1 --- src/btop.cpp | 2 +- src/btop_input.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 5034629..f49189e 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -208,7 +208,6 @@ void clean_quit(int sig) { } Config::write(); - Input::clear(); //? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms for (int i = 0; Tools::active_locks > 0 and i < 100; i++) { @@ -216,6 +215,7 @@ void clean_quit(int sig) { } if (Term::initialized) { + Input::clear(); Term::restore(); } diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 2d2a854..a69e4bd 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -95,7 +95,7 @@ namespace Input { string get() { string key; while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get(); - if (cin.rdbuf()->in_avail() > 0) cin.ignore(cin.rdbuf()->in_avail()); + if (cin.rdbuf()->in_avail() > 0) clear(); if (not key.empty()) { //? Remove escape code prefix if present if (key.substr(0, 2) == Fx::e) { @@ -175,7 +175,12 @@ namespace Input { } void clear() { - if (cin.rdbuf()->in_avail() > 0) cin.ignore(SSmax); + auto first_num = cin.rdbuf()->in_avail(); + while (cin.rdbuf()->in_avail() == first_num) { + if (first_num-- == 0) break; + cin.ignore(1); + + } } void process(const string& key) { From c133997b210001c7ec9f556da438a71ebbd7edde Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 18:48:11 +0100 Subject: [PATCH 114/289] Fixed: Inconsistent behaviour of "q" key in the menus --- src/btop_input.cpp | 1 - src/btop_menu.cpp | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index a69e4bd..885121f 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -179,7 +179,6 @@ namespace Input { while (cin.rdbuf()->in_avail() == first_num) { if (first_num-- == 0) break; cin.ignore(1); - } } diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index fa7f6a5..891ea1f 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -892,10 +892,7 @@ namespace Menu { }; } } - else if (key == "q") { - exit(0); - } - else if (is_in(key, "escape", "m", "mouse_click")) { + else if (is_in(key, "escape", "q", "m", "mouse_click")) { return Closed; } else if (key.starts_with("button_")) { From 0201b5f859c530f8382a74e47e93c85c5ca7d4f1 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 18:58:25 +0100 Subject: [PATCH 115/289] v1.0.23 Bug fixes --- CHANGELOG.md | 10 ++++++++++ src/btop.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d03067..6bce917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.0.23 + +* Fixed: Config parser missing first value when not including version header + +* Fixed: Vim keys menu lists selection + +* Fixed: Stall when clearing input queue on exit and queue is >1 + +* Fixed: Inconsistent behaviour of "q" key in the menus + ## v1.0.22 * Fixed: Bad values for disks and network on 32-bit diff --git a/src/btop.cpp b/src/btop.cpp index f49189e..b7fea4b 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.22"; + const string Version = "1.0.23"; int coreCount; string overlay; From e717606938526404ed77cb5c51b8657a21b43bcb Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 19:29:02 +0100 Subject: [PATCH 116/289] Changed: Collection ordering --- src/btop.cpp | 73 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index b7fea4b..273bc83 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -414,44 +414,23 @@ namespace Runner { //* Run collection and draw functions for all boxes try { - //? PROC - if (v_contains(conf.boxes, "proc")) { + //? CPU + if (v_contains(conf.boxes, "cpu")) { try { - if (Global::debug) debug_timer("proc", collect_begin); + if (Global::debug) debug_timer("cpu", collect_begin); //? Start collect - auto proc = Proc::collect(conf.no_update); + auto cpu = Cpu::collect(conf.no_update); - if (Global::debug) debug_timer("proc", draw_begin); + if (Global::debug) debug_timer("cpu", draw_begin); //? Draw box - if (not pause_output) output += Proc::draw(proc, conf.force_redraw, conf.no_update); + if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update); - if (Global::debug) debug_timer("proc", draw_done); + if (Global::debug) debug_timer("cpu", draw_done); } catch (const std::exception& e) { - throw std::runtime_error("Proc:: -> " + (string)e.what()); - } - } - - - //? NET - if (v_contains(conf.boxes, "net")) { - try { - if (Global::debug) debug_timer("net", collect_begin); - - //? Start collect - auto net = Net::collect(conf.no_update); - - if (Global::debug) debug_timer("net", draw_begin); - - //? Draw box - if (not pause_output) output += Net::draw(net, conf.force_redraw, conf.no_update); - - if (Global::debug) debug_timer("net", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Net:: -> " + (string)e.what()); + throw std::runtime_error("Cpu:: -> " + (string)e.what()); } } @@ -475,23 +454,43 @@ namespace Runner { } } - //? CPU - if (v_contains(conf.boxes, "cpu")) { + //? NET + if (v_contains(conf.boxes, "net")) { try { - if (Global::debug) debug_timer("cpu", collect_begin); + if (Global::debug) debug_timer("net", collect_begin); //? Start collect - auto cpu = Cpu::collect(conf.no_update); + auto net = Net::collect(conf.no_update); - if (Global::debug) debug_timer("cpu", draw_begin); + if (Global::debug) debug_timer("net", draw_begin); //? Draw box - if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update); + if (not pause_output) output += Net::draw(net, conf.force_redraw, conf.no_update); - if (Global::debug) debug_timer("cpu", draw_done); + if (Global::debug) debug_timer("net", draw_done); } catch (const std::exception& e) { - throw std::runtime_error("Cpu:: -> " + (string)e.what()); + throw std::runtime_error("Net:: -> " + (string)e.what()); + } + } + + //? PROC + if (v_contains(conf.boxes, "proc")) { + try { + if (Global::debug) debug_timer("proc", collect_begin); + + //? Start collect + auto proc = Proc::collect(conf.no_update); + + if (Global::debug) debug_timer("proc", draw_begin); + + //? Draw box + if (not pause_output) output += Proc::draw(proc, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("proc", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Proc:: -> " + (string)e.what()); } } } From eb19bb3fd6a81cddbbccacadcd0bc05a613116ad Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 19:39:16 +0100 Subject: [PATCH 117/289] Fixed: Restore all escape seq mouse modes on exit --- src/btop_tools.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index c9f9b74..218fbca 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -100,7 +100,7 @@ namespace Term { const string clear_end = Fx::e + "0J"; const string clear_begin = Fx::e + "1J"; const string mouse_on = Fx::e + "?1002h" + Fx::e + "?1015h" + Fx::e + "?1006h"; //? Enable reporting of mouse position on click and release - const string mouse_off = Fx::e + "?1002l"; + const string mouse_off = Fx::e + "?1002l" + Fx::e + "?1015l" + Fx::e + "?1006l"; const string mouse_direct_on = Fx::e + "?1003h"; //? Enable reporting of mouse position at any movement const string mouse_direct_off = Fx::e + "?1003l"; const string sync_start = Fx::e + "?2026h"; //? Start of terminal synchronized output From 41f1e9e0a746c0ab93af226920a060072de5c708 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 8 Nov 2021 20:35:16 +0100 Subject: [PATCH 118/289] Fixed: SIGINT not cleaning up on exit --- src/btop.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 273bc83..44565b7 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -79,6 +79,8 @@ namespace Global { atomic resized (false); atomic quitting (false); + atomic should_quit (false); + atomic should_sleep (false); atomic _runner_started (false); bool arg_tty = false; @@ -254,10 +256,24 @@ void _exit_handler() { void _signal_handler(const int sig) { switch (sig) { case SIGINT: - clean_quit(0); + if (Runner::active) { + Global::should_quit = true; + Runner::stopping = true; + Input::interrupt = true; + } + else { + clean_quit(0); + } break; case SIGTSTP: - _sleep(); + if (Runner::active) { + Global::should_sleep = true; + Runner::stopping = true; + Input::interrupt = true; + } + else { + _sleep(); + } break; case SIGCONT: _resume(); @@ -363,10 +379,10 @@ namespace Runner { //? ------------------------------- Secondary thread: async launcher and drawing ---------------------------------- void * _runner(void * _) { (void)_; - //? Block all signals in this thread to avoid deadlock from any signal handlers trying to stop this thread + //? Block some signals in this thread to avoid deadlock from any signal handlers trying to stop this thread sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGTSTP); + // sigaddset(&mask, SIGINT); + // sigaddset(&mask, SIGTSTP); sigaddset(&mask, SIGWINCH); sigaddset(&mask, SIGTERM); pthread_sigmask(SIG_BLOCK, &mask, NULL); @@ -842,6 +858,8 @@ int main(int argc, char **argv) { while (not true not_eq not false) { //? Check for exceptions in secondary thread and exit with fail signal if true if (Global::thread_exception) exit(1); + else if (Global::should_quit) exit(0); + else if (Global::should_sleep) { Global::should_sleep = false; _sleep(); } //? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly) term_resize(); From 81df582687895646649100df2150e064334d1fd8 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 9 Nov 2021 10:03:37 +0100 Subject: [PATCH 119/289] v1.0.24 Bug fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bce917..d134d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.0.24 + +* Changed: Collection ordering + +* Fixed: Restore all escape seq mouse modes on exit + +* Fixed: SIGINT not cleaning up on exit + ## v1.0.23 * Fixed: Config parser missing first value when not including version header diff --git a/src/btop.cpp b/src/btop.cpp index 44565b7..fd9b5f2 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.23"; + const string Version = "1.0.24"; int coreCount; string overlay; From 7ca4940debb80f642da07caaee580f8cf11b8ebd Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 13 Nov 2021 21:19:18 +0100 Subject: [PATCH 120/289] Added OSX fixes for upcoming merge --- Makefile | 46 ++++++++++++++++++++++++++++++++++++---------- src/btop.cpp | 13 ++++++++++++- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 7fe9f4d..72afbff 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,11 @@ BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m█ override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") +ifeq ($(shell command -v gdate >/dev/null; echo $$?),0) + DATE_CMD := gdate +else + DATE_CMD := date +endif ifneq ($(QUIET),true) override PRE := info info-quiet @@ -16,15 +21,25 @@ PREFIX ?= /usr/local #? Detect PLATFORM and ARCH from uname/gcc if not set PLATFORM ?= $(shell uname -s || echo unknown) -ifneq ($(filter unknown darwin, $(PLATFORM)),) +ifneq ($(filter unknown Darwin, $(PLATFORM)),) override PLATFORM := $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') + ifeq ($(PLATFORM),apple) + override PLATFORM := macos + endif +endif +ifeq ($(shell uname -v | grep ARM64 >/dev/null 2>&1; echo $$?),0) + ARCH ?= arm64 +else + ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) endif -ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Any flags added to TESTFLAGS must not contain whitespace for the testing to work -override TESTFLAGS := -fexceptions -fcf-protection -fstack-protector -fstack-clash-protection +override TESTFLAGS := -fexceptions -fstack-clash-protection -fcf-protection +ifneq ($(PLATFORM) $(ARCH),macos arm64) + override TESTFLAGS += -fstack-protector +endif ifeq ($(STATIC),true) override ADDFLAGS += -DSTATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings @@ -35,12 +50,22 @@ ifeq ($(STRIP),true) endif #? Compiler and Linker -CXX ?= g++ +ifeq ($(shell command -v g++-11 >/dev/null; echo $$?),0) + CXX := g++-11 +else ifeq ($(shell command -v g++11 >/dev/null; echo $$?),0) + CXX := g++11 +else ifeq ($(shell command -v g++ >/dev/null; echo $$?),0) + CXX := g++ +endif override CXX_VERSION := $(shell $(CXX) -dumpfullversion -dumpversion || echo 0) #? Try to make sure we are using GCC/G++ version 11 or later if not instructed to use g++-10 ifeq ($(CXX),g++) - V_MAJOR := $(shell echo $(CXX_VERSION) | cut -f1 -d".") + ifeq ($(shell g++ --version | grep clang >/dev/null 2>&1; echo $$?),0) + V_MAJOR := 0 + else + V_MAJOR := $(shell echo $(CXX_VERSION) | cut -f1 -d".") + endif ifneq ($(shell test $(V_MAJOR) -ge 11; echo $$?),0) ifeq ($(shell command -v g++-11 >/dev/null; echo $$?),0) override CXX := g++-11 @@ -115,6 +140,7 @@ info: @printf "\033[1;95mLDFLAGS \033[1;92m+| \033[0;37m\$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n" info-quiet: + @sleep 0.1 2>/dev/null || true @printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n" help: @@ -176,17 +202,17 @@ uninstall: #? Link .ONESHELL: btop: $(OBJECTS) - @sleep 0.1 2>/dev/null || true + @sleep 0.2 2>/dev/null || true @TSTAMP=$$(date +%s 2>/dev/null || echo "0") @$(QUIET) || printf "\n\033[1;92mLinking and optimizing binary\033[37m...\033[0m\n" @$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS) || exit 1 - @printf "\033[1;92m-> \033[1;37m$(TARGETDIR)/btop \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" - printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n" + @printf "\033[1;92m-> \033[1;37m$(TARGETDIR)/btop \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" + @printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n" #? Compile .ONESHELL: $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) - @sleep 0.1 2>/dev/null || true + @sleep 0.3 2>/dev/null || true @TSTAMP=$$(date +%s 2>/dev/null || echo "0") @$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n" @$(CXX) $(CXXFLAGS) $(INC) -c -o $@ $< || exit 1 @@ -195,7 +221,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp - @printf "\033[1;92m-> \033[1;37m$@ \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" + @printf "\033[1;92m-> \033[1;37m$@ \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" #? Non-File Targets .PHONY: all msg help pre diff --git a/src/btop.cpp b/src/btop.cpp index fd9b5f2..b9be5e8 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -201,12 +201,19 @@ void clean_quit(int sig) { Global::quitting = true; Runner::stop(); if (Global::_runner_started) { + #ifdef __APPLE__ + if (pthread_join(Runner::runner_id, NULL) != 0) { + Logger::error("Failed to join _runner thread!"); + pthread_cancel(Runner::runner_id); + } + #else struct timespec ts; ts.tv_sec = 5; if (pthread_timedjoin_np(Runner::runner_id, NULL, &ts) != 0) { Logger::error("Failed to join _runner thread!"); pthread_cancel(Runner::runner_id); } + #endif } Config::write(); @@ -229,9 +236,11 @@ void clean_quit(int sig) { Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor +#ifndef __APPLE__ if (Tools::active_locks > 0) { quick_exit((sig != -1 ? sig : 0)); } +#endif if (sig != -1) exit(sig); } @@ -311,7 +320,7 @@ namespace Runner { pthread_mutex_t& pt_mutex; public: int status; - thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { status = pthread_mutex_lock(&pt_mutex); } + thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { pthread_mutex_init(&mtx, NULL); status = pthread_mutex_lock(&pt_mutex); } ~thread_lock() { if (status == 0) pthread_mutex_unlock(&pt_mutex); } }; @@ -778,10 +787,12 @@ int main(int argc, char **argv) { Config::set("tty_mode", true); Logger::info("Forcing tty mode: setting 16 color mode and using tty friendly graph symbols"); } +#ifndef __APPLE__ else if (not Global::arg_tty and Term::current_tty.starts_with("/dev/tty")) { Config::set("tty_mode", true); Logger::info("Real tty detected: setting 16 color mode and using tty friendly graph symbols"); } +#endif //? Check for valid terminal dimensions { From 4926acda5f32dd342060cac9832ad67983d50fc4 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 13 Nov 2021 21:25:08 +0100 Subject: [PATCH 121/289] Makefile OSX and freebsd fixes --- Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 72afbff..42ff6c1 100644 --- a/Makefile +++ b/Makefile @@ -78,12 +78,18 @@ endif ifeq ($(PLATFORM_LC),linux) PLATFORM_DIR := linux THREADS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) + SU_GROUP := root else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM_LC),apple) + SU_GROUP := root + override ADDFLAGS += -lstdc++ -lm -lkvm -Wl,-rpath=/usr/local/lib/gcc11 + export MAKE = gmake +else ifeq ($(PLATFORM_LC),macos) PLATFORM_DIR := osx THREADS := $(shell sysctl -n hw.ncpu || echo 1) + override ADDFLAGS += -framework IOKit -framework CoreFoundation -Wno-format-truncation + SU_GROUP := wheel else $(error $(shell printf "\033[1;91mERROR: \033[97mUnsupported platform ($(PLATFORM))\033[0m")) endif @@ -115,7 +121,6 @@ override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) INC := -I$(INCDIR) -I$(SRCDIR) SU_USER := root -SU_GROUP := root SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)) From c0e17a64d32ee313b27048a182fea9d737e3e177 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 13 Nov 2021 23:31:01 +0100 Subject: [PATCH 122/289] Squashed commit of the following: commit c2c4fe47db3002c3433114954c22bd92b149bea0 Author: aristocratos Date: Sat Nov 13 23:15:53 2021 +0100 Changes from main + fixes commit bd5d86708907397f7fc40868ff3665e23f24bb8a Author: aristocratos Date: Sat Nov 13 21:24:01 2021 +0100 Fixes commit dc5f0606cbe6f4d61bec3621c25190f1241b3fce Author: aristocratos Date: Sat Nov 13 20:51:06 2021 +0100 Fixed leak in Proc::collect() commit 8b59ab6e1120439a070b07a4255b10bd7d5197cf Author: aristocratos Date: Sat Nov 13 19:59:56 2021 +0100 Fixed process cpu usage calculation commit 53c8a0325b7567b84da2f01ebd5acad33db4c0cb Author: aristocratos Date: Mon Oct 25 13:01:53 2021 +0200 Cpu temp set to average of pACC and eACC for mac m1 commit 940cd0a5131253b0595b233f9da350101211d3cb Author: Jos Dehaes Date: Sun Oct 24 21:12:16 2021 +0200 limit cpu temp to 20 commit 254ceb9c2df0374ad07a6ca1e867ef40a60efc24 Author: aristocratos Date: Sun Oct 24 11:24:04 2021 +0200 Fixed up Makefile commit 6fa3bf41d757edbb311b99292b26aa45e83d9b9d Author: aristocratos Date: Thu Oct 21 13:12:45 2021 +0200 Makefile fixed WARNFLAGS commit 2c98e2ca2927d772674c130dcc527f3318daf150 Author: aristocratos Date: Thu Oct 21 13:08:12 2021 +0200 Updated Makefile commit e69780e9bce7af37ba6a85843db0e97c55c61395 Author: Jos Dehaes Date: Wed Oct 20 23:26:09 2021 +0200 fix build commit de6216792154477a5ab7f564c9467761daf842e2 Merge: a590dd3 a0ee404 Author: Jos Dehaes Date: Wed Oct 20 23:10:36 2021 +0200 Merge branch 'main' into OSX commit a590dd3f67c9f2f8f8dc3fa49920a40a5e8b369d Author: aristocratos Date: Mon Oct 18 11:20:12 2021 +0200 Ignore format-truncation commit 4c30742d412cf552de22b3746a68cd62bfe867f2 Author: Jos Dehaes Date: Mon Oct 18 10:08:01 2021 +0200 comments about temp sensors commit 46030de77cb1409eb8b0247c331408a240b0227a Author: Jos Dehaes Date: Mon Oct 18 08:10:37 2021 +0200 available = total - used commit 4c228de0ef8a75275178bad081e568f85fc579fd Author: Jos Dehaes Date: Sun Oct 17 22:19:41 2021 +0200 use sysconf to get arg_max - seems simpler commit c60fc29f0f62831730c04c23cd9ffbefef50a1d8 Author: Jos Dehaes Date: Sun Oct 17 22:10:50 2021 +0200 arg_max should be int on macos commit 0b5a931a6d5e8d1a434e88e8fd0613ab948995fa Author: Jos Dehaes Date: Sun Oct 17 22:01:42 2021 +0200 only fetch max_args once commit 71d5cd5fd91511a90e43e5e6dbf7a1b6a3c3f9c8 Author: aristocratos Date: Sat Oct 16 23:24:07 2021 +0200 Reverted mutexes back to custom atomic bool based locks commit 3f34a67df68f3f451cb48b023b7cd42ccf933ce4 Author: Jos Dehaes Date: Sat Oct 16 21:47:55 2021 +0200 these helpers can be static commit fc19c46c8aab03e252f60f6f9447d7e1861cbcb9 Author: Jos Dehaes Date: Sat Oct 16 21:44:49 2021 +0200 code cleanup: put the code in .cpp to enable incremental build commit c252c618c043c4b85783f56363121877d0db0727 Author: Jos Dehaes Date: Sat Oct 16 21:09:21 2021 +0200 don't crash on intel commit 9f88187c29821148c7a5272926d204bd3eb39f89 Author: Jos Dehaes Date: Sat Oct 16 21:06:18 2021 +0200 small improvement commit 808f09c97465e8cf511f7690b40a69cd8a2efa15 Author: Jos Dehaes Date: Sat Oct 16 20:59:48 2021 +0200 don't iterate 3 times commit d8408336e3b8336025a087a2bf79a2d15f51ee66 Author: Jos Dehaes Date: Sat Oct 16 20:59:27 2021 +0200 remove debug commit 4f078c3beb960fe06f4d8b44b9c913e2aacf7625 Author: Jos Dehaes Date: Wed Oct 13 23:38:27 2021 +0200 more temperature (M1 + intel) commit 289880aaa6d1a3625c01e9d7643138343b29db53 Merge: 88a2528 3ffb212 Author: aristocratos Date: Sat Oct 16 19:37:09 2021 +0200 Merge branch 'OSX' of github.com:aristocratos/btop into OSX commit 88a2528ca3a2390f2c94c7f1a18ba982a5e5f2b2 Author: aristocratos Date: Sat Oct 16 19:34:10 2021 +0200 Merge changes from main commit 3ffb21203aa3f4ad978533a3f2b1e67e636381ea Author: Jos Dehaes Date: Sat Oct 16 19:20:45 2021 +0200 release a bit more - still has negative temps for 2 cores on my system commit 70b48710626ba22df496ba741625ce03cba6abbd Author: aristocratos Date: Sat Oct 16 01:59:44 2021 +0200 Fixed leaks in Mem and attempt at fixing leaks in sensors.cpp commit fbae907720afbae47162666b6b0aea974be80c07 Author: Jos Dehaes Date: Fri Oct 15 23:41:37 2021 +0200 temperature sensors via IOKit commit cef0f0a68daa88a380000ce200a364e4701ba93a Author: aristocratos Date: Fri Oct 15 18:39:17 2021 +0200 Process command line arguments commit 921cfa01ffc104c57f2825d0bca648233ddff191 Author: aristocratos Date: Wed Oct 13 23:20:15 2021 +0200 Re-enable setuid and set default SU_GROUP to wheel for OSX commit a416c888c7356634ef7a5286130a56160d72f50a Author: Jos Dehaes Date: Wed Oct 13 21:16:41 2021 +0200 temperature commit e7afe00ce7960bfe6fb6ba2a9a2f5d498c5b4fca Author: aristocratos Date: Wed Oct 13 12:54:43 2021 +0200 Cpu usage working again commit 4193ef8921617e48ce07ce95d898386f7dd77f43 Author: aristocratos Date: Wed Oct 13 10:36:51 2021 +0200 Fixed cpu lazy sorting commit 93fcb6ff04d84c008ed9f7d28918eb9eb8adf740 Author: aristocratos Date: Tue Oct 12 22:22:45 2021 +0200 Update README.md commit 683354cd2ed8add79c6940e51800431e8b020635 Merge: 8a399c4 6d724d6 Author: aristocratos Date: Tue Oct 12 22:19:30 2021 +0200 Merge pull request #80 from ShrirajHegde/OSX Add github workflow for MacOS commit 8a399c499af87883a7e4b2cf7f6d193f76909923 Author: aristocratos Date: Tue Oct 12 21:50:46 2021 +0200 pointer to smart pointer, first pass commit 772605003af9c1c00f163ff75279cd0055074c96 Author: aristocratos Date: Tue Oct 12 18:54:38 2021 +0200 Fixed detailed memory not updating commit 28cb67753332fe8c93d23cbf8e4db636fc6823d6 Author: Jos Dehaes Date: Mon Oct 11 22:19:25 2021 +0200 more memory free-up - still leaks like crazy commit 304457863f6cdccf82fbe1cca3078c7f5d9f97cd Author: Jos Dehaes Date: Mon Oct 11 21:48:07 2021 +0200 more RAII cleanup commit 82e2e3c55c23e37dbf226952cca4587df3522fa3 Author: aristocratos Date: Mon Oct 11 12:40:25 2021 +0200 Removed non present cpu fields and fixed calculation for selectable cpu field graphs commit 68603f2b37e34828f78f0f675f66bd835dae8325 Author: aristocratos Date: Mon Oct 11 10:57:04 2021 +0200 RAII Wrappers for Cpu::get_battery() commit d5cb24fbeb19ae57507e1715aa402b2dc33f9b6b Author: Jos Dehaes Date: Sun Oct 10 20:23:11 2021 +0200 RAII commit 8fad5a61bee973c22f3a11fd7fee2c4e40390bbb Author: Jos Dehaes Date: Sat Oct 9 21:44:16 2021 +0200 get more disk IO stats commit 7fa903cf160b391fb316ea32a60984921a174066 Author: Jos Dehaes Date: Sat Oct 9 21:43:48 2021 +0200 fix build commit 98036db660e306626d41fb1b67d9938d9ffe168a Author: Jos Dehaes Date: Sat Oct 9 21:18:25 2021 +0200 remove unnecessary uptime param commit aae7ae35caec64ba611d9b78b24c0ad2716f333e Author: Jos Dehaes Date: Sat Oct 9 21:07:23 2021 +0200 remove debug logging commit 5187420b04973edcdd25c1b639795a2c8539b2d9 Author: Jos Dehaes Date: Sat Oct 9 21:06:43 2021 +0200 fix process elapsed time commit 89582c0ea6e9bdd7a658b5583d2ce2c5deeee8b0 Author: Jos Dehaes Date: Sat Oct 9 21:06:29 2021 +0200 don't double free commit 6d724d6155bad8c084e4c9bdb1d7dda13543a5ac Author: Shriraj Hegde Date: Sat Oct 9 21:46:33 2021 +0530 Change Upload filename commit 4f94ecc8ad7d7cdb7daed82fd98a5634d723ec6b Author: Shriraj Hegde Date: Sat Oct 9 21:40:11 2021 +0530 Fix upload path commit e1d6d0a1f224474417078a0a1b98a6c4b5c94a53 Author: Shriraj Hegde Date: Sat Oct 9 21:36:13 2021 +0530 Skip installing gcc via Homebrew Change job name commit 02cdd9d759d163519048d24746273e4eda2149d0 Author: Shriraj Hegde Date: Sat Oct 9 21:30:40 2021 +0530 Fix uploading Remove distclean commit 39eb6c396fc31f798d23c21e7f4b313930dca982 Author: Shriraj Hegde Date: Sat Oct 9 21:26:57 2021 +0530 Disable static compilation commit 099592bccdafe8d8d8c421bcad3e036cbea580ce Author: aristocratos Date: Sat Oct 9 17:52:10 2021 +0200 Ignore empty pid 0 to fix tree mode commit a28e17556e74bb618fc2b6eb74f250b139406cdd Author: Shriraj Hegde Date: Sat Oct 9 21:17:11 2021 +0530 Add workflow for MacOS commit aee9179c0a98bce54b55c8bb8ebdc1ac99bad69e Author: aristocratos Date: Sat Oct 9 17:36:46 2021 +0200 Disable failed tty mode detection for OSX commit 4b7b98058d7190a494fa522834217d786d71e5fb Author: aristocratos Date: Sat Oct 9 11:28:32 2021 +0200 Fixed disk io and added io activity based on read/write commit bfa0629e7d1e50f88d9a1207930e2f39270fc189 Author: Jos Dehaes Date: Fri Oct 8 22:28:10 2021 +0200 fill in 0 for ioticks commit a016ff8a039634bc37a22a4a84b31055b3cfab37 Author: Jos Dehaes Date: Fri Oct 8 22:16:01 2021 +0200 disk io from IOreg. Does not show any io though commit f98606c6db09d50c7ae234437ea03eda2cc8739c Author: Jos Dehaes Date: Fri Oct 8 09:32:06 2021 +0200 per process IO stats commit c8b50ed4883103f66c9ed869fd0252d48f18f58f Author: Jos Dehaes Date: Fri Oct 8 00:11:08 2021 +0200 don't show autofs, it's useless commit c4df64d4409c511847d76b37a0794b8bb4f6942d Author: aristocratos Date: Thu Oct 7 18:41:49 2021 +0200 Fixed compile time display for gmake and command timings commit b3e6f495f76bd71fba3442a557df22afdd3e642d Author: aristocratos Date: Thu Oct 7 18:26:15 2021 +0200 Fixed clk_tck -> clkTck commit e53799188ffc24f3948e7ced375b7fbb53911247 Author: aristocratos Date: Thu Oct 7 18:25:14 2021 +0200 Fixed better detection for OSX commit b864edf984e8f0daa0f10a6ee305074c68efeb42 Author: aristocratos Date: Thu Oct 7 18:24:37 2021 +0200 Fixed cumulative cpu usage commit 6a3c5d9b976c711461d08c373483c84bb69db257 Author: aristocratos Date: Thu Oct 7 13:20:30 2021 +0200 Proc::collect() better cpu percent accurazy commit 84d0596294432baef1b10f7d3a566a07382f69d3 Merge: 3564f8e 98e1e87 Author: aristocratos Date: Thu Oct 7 12:56:55 2021 +0200 Merge branch 'OSX' of github.com:aristocratos/btop into OSX commit 3564f8e4c26f04ec89482606e68a452a3e5f9693 Author: aristocratos Date: Thu Oct 7 12:56:27 2021 +0200 Proc::collect() fixed cputimes and cpu percentage calc commit 98e1e874059fe69968d4bb7e4685f292e3b7fd65 Merge: 60c5636 d96fdd7 Author: Jos Dehaes Date: Thu Oct 7 11:32:41 2021 +0200 Merge branch 'main' into OSX commit 60c5636cd7c18e6c806cb4cd88846db10092dd57 Author: Jos Dehaes Date: Wed Oct 6 22:45:54 2021 +0200 fix warning commit 489e446152ce00f8e92db8c4e10759f96e38f17f Author: Jos Dehaes Date: Wed Oct 6 22:38:40 2021 +0200 details + process states commit 7e5a808c731772bab35204f2e286975fca334f54 Author: Jos Dehaes Date: Wed Oct 6 22:38:19 2021 +0200 avoid details crash commit 9c9da4606b3f93c0701b820a875fb3db5d0c3daf Author: Jos Dehaes Date: Wed Oct 6 21:03:21 2021 +0200 fix quit on macos commit ec7415384d9d9b42892a1e36ff55bf7a117a253b Author: Jos Dehaes Date: Wed Oct 6 00:41:37 2021 +0200 fix mistake in makefile commit 5ac8fa4c8a8f73efac6ac1f15e458ed3b2c1164b Author: Jos Dehaes Date: Wed Oct 6 18:56:13 2021 +0200 don't show /dev commit d901bbebd94ec45c45431fcd1ab37a974f783d9b Author: aristocratos Date: Wed Oct 6 17:27:51 2021 +0200 Ignore tags and other branches commit c7f1e71e29bafb5334cd4e256c662e5ee6303b1b Author: Jos Dehaes Date: Wed Oct 6 16:00:41 2021 +0200 comment commit b9d58e3faf5b60ad4f5f65454b454ff52deb5eaa Author: Jos Dehaes Date: Wed Oct 6 15:55:58 2021 +0200 impossible to get CPU freq on M1 apparently commit 66072711c24b2694c4a0054c58829095ed97ada2 Author: Jos Dehaes Date: Wed Oct 6 15:33:43 2021 +0200 detect full commit 6bb0e930a2c44b4fb7d0d02a40f210fa12fdc657 Author: Jos Dehaes Date: Wed Oct 6 00:38:46 2021 +0200 CPU freq in GHz commit a5f10f1a0ff9d10fa8d9d3038aa160b2380aa294 Author: Jos Dehaes Date: Wed Oct 6 15:13:18 2021 +0200 check array length commit 155c848b97e1385bd29eaba91a87ecfb1d846bf7 Author: Jos Dehaes Date: Wed Oct 6 15:05:20 2021 +0200 switch to other way to get CPU freq (still does not work) commit cf51ba2ebe88dddd943040ced484581dc260c3c8 Author: Jos Dehaes Date: Wed Oct 6 14:45:44 2021 +0200 remove some warnings commit 775dff5f72b0631bba0ed01d72374d8c1d1cd059 Author: Jos Dehaes Date: Wed Oct 6 14:16:45 2021 +0200 fix link commit 8c67967775fb98bda80eee40cb6833a00bfb93a1 Author: Jos Dehaes Date: Wed Oct 6 14:16:38 2021 +0200 reduce diff more commit 70b47d2ca8a7e0927cf9613e8fe776d2405f60ee Author: Jos Dehaes Date: Wed Oct 6 14:10:23 2021 +0200 reduce diff with main branch commit ca9cb48054c5850cbb3c23d368e04644a1885de0 Merge: d0c6c0a c66b46f Author: Jos Dehaes Date: Wed Oct 6 13:49:20 2021 +0200 Merge remote-tracking branch 'origin/main' into OSX commit c66b46f850d31c100226e519c55b39df9129aeb8 Author: Jos Dehaes Date: Wed Oct 6 13:41:57 2021 +0200 battery state via CoreFoundation commit d0c6c0a362d8dc4f76e2901d7b406a70d8a69b6b Author: Jos Dehaes Date: Wed Oct 6 10:51:36 2021 +0200 all disks + load averages commit ca67526dc175dba7d98193a6462e70ef1acab194 Author: Jos Dehaes Date: Wed Oct 6 10:33:55 2021 +0200 show all disks commit 56119f99a95ca541d6ab744a9ded54c84e0a3184 Author: Jos Dehaes Date: Wed Oct 6 00:17:41 2021 +0200 procs sorting/filtering commit 8d86011d72a07b3f86f6b525b026b805667a3172 Author: Jos Dehaes Date: Tue Oct 5 23:42:17 2021 +0200 battery states commit a9b64d62e4abf96fe3edcfa660871caef2041d0f Author: Jos Dehaes Date: Tue Oct 5 23:24:59 2021 +0200 battery hack works on M1 commit ce5103114246f5549017ef4823442a0ea916e1dd Author: Jos Dehaes Date: Tue Oct 5 23:18:22 2021 +0200 ugly hack to get battery commit d5e6725c6cd6973cc75dfe2993892e1c25ac8d38 Author: Jos Dehaes Date: Tue Oct 5 22:42:42 2021 +0200 CPU stuff commit 5c02bd8c8380c5c74837b982987b7bf31103245f Author: Jos Dehaes Date: Tue Oct 5 21:25:42 2021 +0200 network commit d5da9d49835cdb23ad5830c000e1b93fcb8f46fd Author: Jos Dehaes Date: Tue Oct 5 15:43:05 2021 +0200 correct cached size commit 5f11aba504254d86ed9a2319967590d50988e16f Author: Jos Dehaes Date: Tue Oct 5 12:03:48 2021 +0200 vm stats from syscall + swap commit 776fc968529e8e7e38fc3168c83b2727198722ad Author: Jos Dehaes Date: Tue Oct 5 10:48:07 2021 +0200 seems to work indeed commit 7b40e2835a085bfe0d5eb40f367a1ed50353e4d9 Author: Jos Dehaes Date: Tue Oct 5 10:46:14 2021 +0200 allow override optimization flag commit 005ea24e4c9bcc6608671a0635126bf10bdece34 Author: Jos Dehaes Date: Tue Oct 5 10:09:24 2021 +0200 update Makefile commit af8cec9debac328645f0f4e2f136e4572d88332e Author: Jos Dehaes Date: Mon Oct 4 15:32:55 2021 +0200 some more params commit 7ebe4f7594599ccafbf72a004ce37f965549f64d Author: Jos Dehaes Date: Mon Oct 4 15:15:55 2021 +0200 show more disks commit e50a56394a3702b6616d03694f5d23a5f7ba2f1c Author: Jos Dehaes Date: Mon Oct 4 14:52:56 2021 +0200 disks show something commit 6497a8c2021b67057dfed26488aec0d82e919a90 Author: Jos Dehaes Date: Mon Oct 4 09:15:35 2021 +0200 reformat commit 28e152b80c07c1fb9a4049cca8510f8bdc31adbb Author: Jos Dehaes Date: Sun Oct 3 23:21:13 2021 +0200 decrease diff with upstream commit 40da88e9ca91f3db540b63b15da5bc34dc9175e9 Author: Jos Dehaes Date: Sun Oct 3 22:56:14 2021 +0200 try to get disks to show commit eaf2bb56a503fd2bf3787bfd90b5bc8640b7d628 Author: Jos Dehaes Date: Sun Oct 3 22:42:01 2021 +0200 don't crash on deque::back() commit f66b6f712c361fafbe6d0cfd8f8c0838dc1bb4d2 Author: Jos Dehaes Date: Sun Oct 3 22:08:21 2021 +0200 cpu freq, name & process uid/name commit 34a8a61f4de964d3137637b045be8738c4b1b6e5 Author: Jos Dehaes Date: Sun Oct 3 21:46:11 2021 +0200 basic process info commit 29bb2dcc5fcc6b946511068f036590c18fb459ce Author: Jos Dehaes Date: Sun Oct 3 21:45:39 2021 +0200 initialize mutex (needed on macos apparently and not on linux) commit fb5970b0005793d760e652348d6acc30fb570f70 Author: Jos Dehaes Date: Sat Oct 2 23:53:41 2021 +0200 comment commit 49d16cdddd56ba5631269eb2ffbec87d9f36f81e Author: Jos Dehaes Date: Sat Oct 2 23:51:29 2021 +0200 extract delimiters commit 3db9d6647650bd836201b8150e320a7fbf28e3c2 Author: Jos Dehaes Date: Sat Oct 2 23:48:28 2021 +0200 first infos on macos: memory used & free commit f8acb2f8542429677116799ddb5f442488cf3f4f Author: Jos Dehaes Date: Tue Sep 28 23:37:03 2021 +0200 make it compile on macos (M1 - arm64). Does not run though commit bbba17cd35248e4e9ec9bfc1b113758cfcffde1f Author: Jos Dehaes Date: Wed Oct 6 10:51:36 2021 +0200 all disks + load averages commit 548203e93dfaf3ec9f24086bee08aac85891c4df Author: Jos Dehaes Date: Wed Oct 6 10:33:55 2021 +0200 show all disks commit 0ab2be39857fb3dcdb13b49bc9155f17c7d82a4e Author: Jos Dehaes Date: Wed Oct 6 00:17:41 2021 +0200 procs sorting/filtering commit 096104c90b571e931a3a7d9c813dbfc9aa47e212 Author: Jos Dehaes Date: Tue Oct 5 23:42:17 2021 +0200 battery states commit 0ad93684c2a72293b23d6a2163c9ec51b499dfa3 Author: Jos Dehaes Date: Tue Oct 5 23:24:59 2021 +0200 battery hack works on M1 commit c75b0f1cea34e6c4c70332ba7e2572ec9b70deef Author: Jos Dehaes Date: Tue Oct 5 23:18:22 2021 +0200 ugly hack to get battery commit 600b4f72b3bbbcd85bf5d148942bce7be8cf0b72 Author: Jos Dehaes Date: Tue Oct 5 22:42:42 2021 +0200 CPU stuff commit 4eb812d52c6e179ae386df0156021d7c35cbe5a3 Author: Jos Dehaes Date: Tue Oct 5 21:25:42 2021 +0200 network commit 899be68a78270216bfdcca5f0c87668a87c8792f Author: Jos Dehaes Date: Tue Oct 5 15:43:05 2021 +0200 correct cached size commit a1c7f935e3a5661688c0de1ad3226f7bc43b9979 Author: Jos Dehaes Date: Tue Oct 5 12:03:48 2021 +0200 vm stats from syscall + swap commit bd1050a7404f9766a0125523c868a27d5cfac8e8 Author: Jos Dehaes Date: Tue Oct 5 10:48:07 2021 +0200 seems to work indeed commit 5094b73758ee88617e8d5ce876211e1efa298769 Author: Jos Dehaes Date: Tue Oct 5 10:46:14 2021 +0200 allow override optimization flag commit 8811270332bc2276cd18c1116f4d3c2d64a6f721 Author: Jos Dehaes Date: Tue Oct 5 10:09:24 2021 +0200 update Makefile commit 42f966f448b9ad571db7849dc8fd525e0fe72309 Author: Jos Dehaes Date: Mon Oct 4 15:32:55 2021 +0200 some more params commit c1e6d6a62e2810f80fac372e666ec169540b0591 Author: Jos Dehaes Date: Mon Oct 4 15:15:55 2021 +0200 show more disks commit 50fcdaa8543f717bf36146cfa38636fd39009f23 Author: Jos Dehaes Date: Mon Oct 4 14:52:56 2021 +0200 disks show something commit 264bf2d7da0e3fabb5987cddee73762e52170a51 Author: Jos Dehaes Date: Mon Oct 4 09:15:35 2021 +0200 reformat commit 1fd625086ba42e9440c463ae940563d934b8b5c3 Author: Jos Dehaes Date: Sun Oct 3 23:21:13 2021 +0200 decrease diff with upstream commit 17f9f3703c1dd52a86176131a2239cd52ee285bd Author: Jos Dehaes Date: Sun Oct 3 22:56:14 2021 +0200 try to get disks to show commit 8462ae6431fcfe1985d1bbb4404452ddc03cc1de Author: Jos Dehaes Date: Sun Oct 3 22:42:01 2021 +0200 don't crash on deque::back() commit 78bce5b5a6c1c0f3b38f802acad49ec2e32482d6 Merge: 53e379d f9505a4 Author: Jos Dehaes Date: Sun Oct 3 22:08:34 2021 +0200 Merge branch 'aristocratos:main' into main commit 53e379d74dffe2282b089450728501b51d13d199 Author: Jos Dehaes Date: Sun Oct 3 22:08:21 2021 +0200 cpu freq, name & process uid/name commit 2a44b307ef9e947c1007a86988876668a5731e64 Author: Jos Dehaes Date: Sun Oct 3 21:46:11 2021 +0200 basic process info commit 66534eb5b50753217687de0414d390bcb2a14cf1 Author: Jos Dehaes Date: Sun Oct 3 21:45:39 2021 +0200 initialize mutex (needed on macos apparently and not on linux) commit 0983917f26948d83fd8da103903ec99f88058d87 Author: Jos Dehaes Date: Sat Oct 2 23:53:41 2021 +0200 comment commit 9732507248b30139d4af54615945c0b4737cff7d Author: Jos Dehaes Date: Sat Oct 2 23:51:29 2021 +0200 extract delimiters commit 6e704ce8387041c33022459fb6a084362f82a72c Merge: fe4db7c 7bfbd83 Author: Jos Dehaes Date: Sat Oct 2 23:48:43 2021 +0200 Merge branch 'main' of github.com:joske/btop commit fe4db7c16cd349053385eda62e9f2df2e7344d3d Author: Jos Dehaes Date: Sat Oct 2 23:48:28 2021 +0200 first infos on macos: memory used & free commit 7bfbd83a476c8cbe3b74e22b1e44f201026bf9d1 Merge: 8c8139b a15f961 Author: Jos Dehaes Date: Fri Oct 1 17:05:26 2021 +0200 Merge branch 'aristocratos:main' into main commit 8c8139bd1df0849061b5e1425a3138d5f45ec149 Merge: 679d21c a246c09 Author: Jos Dehaes Date: Wed Sep 29 21:50:00 2021 +0200 Merge branch 'aristocratos:main' into main commit 679d21cd223b1928e8dde95cac25e8bfb412bedf Merge: 4c70c5b a49b8f9 Author: Jos Dehaes Date: Wed Sep 29 20:23:34 2021 +0200 Merge branch 'aristocratos:main' into main commit 4c70c5bdd98bfcc0ae9d9d9e8e3713dc8af71d03 Merge: 84a9746 c70667e Author: Jos Dehaes Date: Wed Sep 29 08:30:05 2021 +0200 Merge branch 'aristocratos:main' into main commit 84a974695afaadc53d1d8576ea66255166ede482 Author: Jos Dehaes Date: Tue Sep 28 23:37:03 2021 +0200 make it compile on macos (M1 - arm64). Does not run though Co-authored-by: Jos Dehaes --- ...s-build.yml => continuous-build-linux.yml} | 0 .github/workflows/continuous-build-macos.yml | 37 + README.md | 1 + src/btop.cpp | 4 +- src/btop_config.cpp | 3 +- src/btop_input.cpp | 2 +- src/btop_menu.cpp | 2 +- src/btop_shared.hpp | 2 + src/btop_tools.cpp | 2 +- src/btop_tools.hpp | 8 + src/osx/btop_collect.cpp | 1405 +++++++++++++++++ src/osx/sensors.cpp | 92 ++ src/osx/sensors.hpp | 7 + src/osx/smc.cpp | 120 ++ src/osx/smc.hpp | 96 ++ 15 files changed, 1773 insertions(+), 8 deletions(-) rename .github/workflows/{continuous-build.yml => continuous-build-linux.yml} (100%) create mode 100644 .github/workflows/continuous-build-macos.yml create mode 100644 src/osx/btop_collect.cpp create mode 100644 src/osx/sensors.cpp create mode 100644 src/osx/sensors.hpp create mode 100644 src/osx/smc.cpp create mode 100644 src/osx/smc.hpp diff --git a/.github/workflows/continuous-build.yml b/.github/workflows/continuous-build-linux.yml similarity index 100% rename from .github/workflows/continuous-build.yml rename to .github/workflows/continuous-build-linux.yml diff --git a/.github/workflows/continuous-build-macos.yml b/.github/workflows/continuous-build-macos.yml new file mode 100644 index 0000000..b747e92 --- /dev/null +++ b/.github/workflows/continuous-build-macos.yml @@ -0,0 +1,37 @@ +name: Continuous Build MacOS + +on: + push: + branches: + - OSX + tags-ignore: + - '*.*' + paths: + - 'src/**' + - '!src/linux/**' + - '!src/freebsd/**' + - 'include/**' + - 'Makefile' + - '.github/workflows/*' + +jobs: + build-osx: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Install build tools + run: | + git checkout OSX + - name: Compile + run: | + make CXX=g++-11 ARCH=x86_64 + GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") + mv bin/btop bin/btop-x86_64-$GIT_HASH + ls -alh bin + + - uses: actions/upload-artifact@v2 + with: + name: btop-x86_64-macos + path: 'bin/*' diff --git a/README.md b/README.md index 3286929..2dd6f21 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos) [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) [![Continuous Build](https://github.com/aristocratos/btop/actions/workflows/continuous-build.yml/badge.svg)](https://github.com/aristocratos/btop/actions) +[![Continuous Build MacOS](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml/badge.svg)](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml) ## Index diff --git a/src/btop.cpp b/src/btop.cpp index b9be5e8..5d782f6 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -88,7 +88,6 @@ namespace Global { int arg_preset = -1; } - //* A simple argument parser void argumentParser(const int& argc, char **argv) { for(int i = 1; i < argc; i++) { @@ -320,7 +319,7 @@ namespace Runner { pthread_mutex_t& pt_mutex; public: int status; - thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { pthread_mutex_init(&mtx, NULL); status = pthread_mutex_lock(&pt_mutex); } + thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { pthread_mutex_init(&pt_mutex, NULL); status = pthread_mutex_lock(&pt_mutex); } ~thread_lock() { if (status == 0) pthread_mutex_unlock(&pt_mutex); } }; @@ -571,7 +570,6 @@ namespace Runner { << Term::sync_end << flush; } //* ----------------------------------------------- THREAD LOOP ----------------------------------------------- - pthread_exit(NULL); } //? ------------------------------------------ Secondary thread end ----------------------------------------------- diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 6284084..66069d7 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -479,7 +479,7 @@ namespace Config { } catch (const std::exception& e) { Global::exit_error_msg = "Exception during Config::unlock() : " + (string)e.what(); - exit(1); + clean_quit(1); } locked = false; @@ -530,7 +530,6 @@ namespace Config { vector valid_names; for (auto &n : descriptions) valid_names.push_back(n[0]); - if (string v_string; cread.peek() != '#' or (getline(cread, v_string, '\n') and not s_contains(v_string, Global::Version))) write_new = true; while (not cread.eof()) { diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 885121f..d7b8ece 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -193,7 +193,7 @@ namespace Input { if (not filtering) { bool keep_going = false; if (str_to_lower(key) == "q") { - exit(0); + clean_quit(0); } else if (is_in(key, "escape", "m")) { Menu::show(Menu::Menus::Main); diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 891ea1f..c3af6d6 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -913,7 +913,7 @@ namespace Menu { currentMenu = Menus::Help; return Switch; case Quit: - exit(0); + clean_quit(0); } } else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) { diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index b5eaf6b..c9f66df 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -34,6 +34,8 @@ using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std: void term_resize(bool force=false); void banner_gen(); +extern void clean_quit(int sig); + namespace Global { extern const vector> Banner_src; extern const string Version; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 061e43f..b7e80da 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -23,10 +23,10 @@ tab-size = 4 #include #include #include +#include #include #include -#include #include #include diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 218fbca..f22de84 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -28,6 +28,14 @@ tab-size = 4 #include #include #include +#include +#ifndef HOST_NAME_MAX + #ifdef __APPLE__ + #define HOST_NAME_MAX 255 + #else + #define HOST_NAME_MAX 64 + #endif +#endif using std::string, std::vector, std::atomic, std::to_string, std::tuple, std::array; diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp new file mode 100644 index 0000000..f976a55 --- /dev/null +++ b/src/osx/btop_collect.cpp @@ -0,0 +1,1405 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sensors.hpp" +#include "smc.hpp" + +using std::clamp, std::string_literals::operator""s, std::cmp_equal, std::cmp_less, std::cmp_greater; +using std::ifstream, std::numeric_limits, std::streamsize, std::round, std::max, std::min; +namespace fs = std::filesystem; +namespace rng = std::ranges; +using namespace Tools; + +//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- + +namespace Cpu { + vector core_old_totals; + vector core_old_idles; + vector available_fields = {"total"}; + vector available_sensors = {"Auto"}; + cpu_info current_cpu; + fs::path freq_path = "/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq"; + bool got_sensors = false, cpu_temp_only = false; + + //* Populate found_sensors map + bool get_sensors(); + + //* Get current cpu clock speed + string get_cpuHz(); + + //* Search /proc/cpuinfo for a cpu name + string get_cpuName(); + + struct Sensor { + fs::path path; + string label; + int64_t temp = 0; + int64_t high = 0; + int64_t crit = 0; + }; + + string cpu_sensor; + vector core_sensors; + unordered_flat_map core_mapping; +} // namespace Cpu + +namespace Mem { + double old_uptime; +} + + class MachProcessorInfo { + public: + processor_info_array_t info_array; + mach_msg_type_number_t info_count; + MachProcessorInfo() {} + virtual ~MachProcessorInfo() {vm_deallocate(mach_task_self(), (vm_address_t)info_array, (vm_size_t)sizeof(processor_info_array_t) * info_count);} + }; + +namespace Shared { + + fs::path passwd_path; + uint64_t totalMem; + long pageSize, coreCount, clkTck, physicalCoreCount, arg_max; + double machTck; + int totalMem_len; + + void init() { + //? Shared global variables init + + coreCount = sysconf(_SC_NPROCESSORS_ONLN); // this returns all logical cores (threads) + if (coreCount < 1) { + coreCount = 1; + Logger::warning("Could not determine number of cores, defaulting to 1."); + } + + size_t physicalCoreCountSize = sizeof(physicalCoreCount); + if (sysctlbyname("hw.physicalcpu", &physicalCoreCount, &physicalCoreCountSize, NULL, 0) < 0) { + Logger::error("Could not get physical core count"); + } + + pageSize = sysconf(_SC_PAGE_SIZE); + if (pageSize <= 0) { + pageSize = 4096; + Logger::warning("Could not get system page size. Defaulting to 4096, processes memory usage might be incorrect."); + } + + mach_timebase_info_data_t convf; + if (mach_timebase_info(&convf) == KERN_SUCCESS) { + machTck = convf.numer / convf.denom; + } else { + Logger::warning("Could not get mach clock tick conversion factor. Defaulting to 100, processes cpu usage might be incorrect."); + machTck = 100; + } + + clkTck = sysconf(_SC_CLK_TCK); + if (clkTck <= 0) { + clkTck = 100; + Logger::warning("Could not get system clock ticks per second. Defaulting to 100, processes cpu usage might be incorrect."); + } + + int64_t memsize = 0; + size_t size = sizeof(memsize); + if (sysctlbyname("hw.memsize", &memsize, &size, NULL, 0) < 0) { + Logger::warning("Could not get memory size"); + } + totalMem = memsize; + + //* Get maximum length of process arguments + arg_max = sysconf(_SC_ARG_MAX); + + //? Init for namespace Cpu + if (not fs::exists(Cpu::freq_path) or access(Cpu::freq_path.c_str(), R_OK) == -1) Cpu::freq_path.clear(); + Cpu::current_cpu.core_percent.insert(Cpu::current_cpu.core_percent.begin(), Shared::coreCount, {}); + Cpu::current_cpu.temp.insert(Cpu::current_cpu.temp.begin(), Shared::coreCount + 1, {}); + Cpu::core_old_totals.insert(Cpu::core_old_totals.begin(), Shared::coreCount, 0); + Cpu::core_old_idles.insert(Cpu::core_old_idles.begin(), Shared::coreCount, 0); + Cpu::collect(); + for (auto &[field, vec] : Cpu::current_cpu.cpu_percent) { + if (not vec.empty() and not v_contains(Cpu::available_fields, field)) Cpu::available_fields.push_back(field); + } + Cpu::cpuName = Cpu::get_cpuName(); + Cpu::got_sensors = Cpu::get_sensors(); + Cpu::core_mapping = Cpu::get_core_mapping(); + + //? Init for namespace Mem + Mem::old_uptime = system_uptime(); + Mem::collect(); + } + +} // namespace Shared + +namespace Cpu { + string cpuName; + string cpuHz; + bool has_battery = true; + bool macM1 = false; + tuple current_bat; + + const array time_names = {"user", "nice", "system", "idle"}; + + unordered_flat_map cpu_old = { + {"totals", 0}, + {"idles", 0}, + {"user", 0}, + {"nice", 0}, + {"system", 0}, + {"idle", 0} + }; + + string get_cpuName() { + string name; + char buffer[1024]; + size_t size = sizeof(buffer); + if (sysctlbyname("machdep.cpu.brand_string", &buffer, &size, NULL, 0) < 0) { + Logger::error("Failed to get CPU name"); + return name; + } + name = string(buffer); + + auto name_vec = ssplit(name); + + if ((s_contains(name, "Xeon"s) or v_contains(name_vec, "Duo"s)) and v_contains(name_vec, "CPU"s)) { + auto cpu_pos = v_index(name_vec, "CPU"s); + if (cpu_pos < name_vec.size() - 1 and not name_vec.at(cpu_pos + 1).ends_with(')')) + name = name_vec.at(cpu_pos + 1); + else + name.clear(); + } else if (v_contains(name_vec, "Ryzen"s)) { + auto ryz_pos = v_index(name_vec, "Ryzen"s); + name = "Ryzen" + (ryz_pos < name_vec.size() - 1 ? ' ' + name_vec.at(ryz_pos + 1) : "") + (ryz_pos < name_vec.size() - 2 ? ' ' + name_vec.at(ryz_pos + 2) : ""); + } else if (s_contains(name, "Intel"s) and v_contains(name_vec, "CPU"s)) { + auto cpu_pos = v_index(name_vec, "CPU"s); + if (cpu_pos < name_vec.size() - 1 and not name_vec.at(cpu_pos + 1).ends_with(')') and name_vec.at(cpu_pos + 1) != "@") + name = name_vec.at(cpu_pos + 1); + else + name.clear(); + } else + name.clear(); + + if (name.empty() and not name_vec.empty()) { + for (const auto &n : name_vec) { + if (n == "@") break; + name += n + ' '; + } + name.pop_back(); + for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) { + name = s_replace(name, replace, ""); + name = s_replace(name, " ", " "); + } + name = trim(name); + } + + return name; + } + + bool get_sensors() { + got_sensors = false; + if (Config::getB("show_coretemp") and Config::getB("check_temp")) { + ThermalSensors sensors; + if (sensors.getSensors() > 0) { + got_sensors = true; + cpu_temp_only = true; + macM1 = true; + } else { + // try SMC (intel) + SMCConnection smcCon; + try { + long long t = smcCon.getTemp(-1); // check if we have package T + if (t > -1) { + got_sensors = true; + } else { + got_sensors = false; + } + } catch (std::runtime_error &e) { + // ignore, we don't have temp + got_sensors = false; + } + } + } + return got_sensors; + } + + void update_sensors() { + current_cpu.temp_max = 95; // we have no idea how to get the critical temp + try { + if (macM1) { + ThermalSensors sensors; + current_cpu.temp.at(0).push_back(sensors.getSensors()); + if (current_cpu.temp.at(0).size() > 20) + current_cpu.temp.at(0).pop_front(); + + } else { + SMCConnection smcCon; + int threadsPerCore = Shared::coreCount / Shared::physicalCoreCount; + long long packageT = smcCon.getTemp(-1); // -1 returns package T + current_cpu.temp.at(0).push_back(packageT); + + if (Config::getB("show_coretemp") and not cpu_temp_only) { + for (int core = 0; core < Shared::coreCount; core++) { + long long temp = smcCon.getTemp(core / threadsPerCore); // same temp for all threads of same physical core + if (cmp_less(core + 1, current_cpu.temp.size())) { + current_cpu.temp.at(core + 1).push_back(temp); + if (current_cpu.temp.at(core + 1).size() > 20) + current_cpu.temp.at(core + 1).pop_front(); + } + } + } + } + } catch (std::runtime_error &e) { + got_sensors = false; + Logger::error("failed getting CPU temp"); + } + } + + string get_cpuHz() { + unsigned int freq = 1; + size_t size = sizeof(freq); + + int mib[] = {CTL_HW, HW_CPU_FREQ}; + + if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { + // this fails on Apple Silicon macs. Apparently you're not allowed to know + return ""; + } + return std::to_string(freq / 1000.0 / 1000.0 / 1000.0).substr(0, 3); + } + + auto get_core_mapping() -> unordered_flat_map { + unordered_flat_map core_map; + if (cpu_temp_only) return core_map; + + natural_t cpu_count; + natural_t i; + MachProcessorInfo info {}; + kern_return_t error; + + error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &info.info_array, &info.info_count); + if (error != KERN_SUCCESS) { + Logger::error("Failed getting CPU info"); + return core_map; + } + for (i = 0; i < cpu_count; i++) { + core_map[i] = i; + } + + //? If core mapping from cpuinfo was incomplete try to guess remainder, if missing completely, map 0-0 1-1 2-2 etc. + if (cmp_less(core_map.size(), Shared::coreCount)) { + if (Shared::coreCount % 2 == 0 and (long) core_map.size() == Shared::coreCount / 2) { + for (int i = 0, n = 0; i < Shared::coreCount / 2; i++) { + if (std::cmp_greater_equal(n, core_sensors.size())) n = 0; + core_map[Shared::coreCount / 2 + i] = n++; + } + } else { + core_map.clear(); + for (int i = 0, n = 0; i < Shared::coreCount; i++) { + if (std::cmp_greater_equal(n, core_sensors.size())) n = 0; + core_map[i] = n++; + } + } + } + + //? Apply user set custom mapping if any + const auto &custom_map = Config::getS("cpu_core_map"); + if (not custom_map.empty()) { + try { + for (const auto &split : ssplit(custom_map)) { + const auto vals = ssplit(split, ':'); + if (vals.size() != 2) continue; + int change_id = std::stoi(vals.at(0)); + int new_id = std::stoi(vals.at(1)); + if (not core_map.contains(change_id) or cmp_greater(new_id, core_sensors.size())) continue; + core_map.at(change_id) = new_id; + } + } catch (...) { + } + } + + return core_map; + } + + class IOPSInfo_Wrap { + CFTypeRef data; + public: + IOPSInfo_Wrap() { data = IOPSCopyPowerSourcesInfo(); } + CFTypeRef& operator()() { return data; } + ~IOPSInfo_Wrap() { CFRelease(data); } + }; + + class IOPSList_Wrap { + CFArrayRef data; + public: + IOPSList_Wrap(CFTypeRef cft_ref) { data = IOPSCopyPowerSourcesList(cft_ref); } + CFArrayRef& operator()() { return data; } + ~IOPSList_Wrap() { CFRelease(data); } + }; + + auto get_battery() -> tuple { + if (not has_battery) return {0, 0, ""}; + + uint32_t percent = -1; + long seconds = -1; + string status = "discharging"; + IOPSInfo_Wrap ps_info{}; + if (ps_info()) { + IOPSList_Wrap one_ps_descriptor(ps_info()); + if (one_ps_descriptor()) { + if (CFArrayGetCount(one_ps_descriptor())) { + CFDictionaryRef one_ps = IOPSGetPowerSourceDescription(ps_info(), CFArrayGetValueAtIndex(one_ps_descriptor(), 0)); + has_battery = true; + CFNumberRef remaining = (CFNumberRef)CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToEmptyKey)); + int32_t estimatedMinutesRemaining; + if (remaining) { + CFNumberGetValue(remaining, kCFNumberSInt32Type, &estimatedMinutesRemaining); + seconds = estimatedMinutesRemaining * 60; + } + CFNumberRef charge = (CFNumberRef)CFDictionaryGetValue(one_ps, CFSTR(kIOPSCurrentCapacityKey)); + if (charge) { + CFNumberGetValue(charge, kCFNumberSInt32Type, &percent); + } + CFBooleanRef charging = (CFBooleanRef)CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargingKey)); + if (charging) { + bool isCharging = CFBooleanGetValue(charging); + if (isCharging) { + status = "charging"; + } + } + if (percent == 100) { + status = "full"; + } + } else { + has_battery = false; + } + } else { + has_battery = false; + } + } + return {percent, seconds, status}; + } + + auto collect(const bool no_update) -> cpu_info & { + if (Runner::stopping or (no_update and not current_cpu.cpu_percent.at("total").empty())) + return current_cpu; + auto &cpu = current_cpu; + + double avg[3]; + + if (getloadavg(avg, sizeof(avg)) < 0) { + Logger::error("failed to get load averages"); + } + + cpu.load_avg = { (float)avg[0], (float)avg[1], (float)avg[2]}; + + natural_t cpu_count; + natural_t i; + kern_return_t error; + processor_cpu_load_info_data_t *cpu_load_info = NULL; + + MachProcessorInfo info{}; + error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &info.info_array, &info.info_count); + if (error != KERN_SUCCESS) { + Logger::error("Failed getting CPU load info"); + } + cpu_load_info = (processor_cpu_load_info_data_t *)info.info_array; + long long global_totals = 0; + long long global_idles = 0; + vector times_summed = {0, 0, 0, 0}; + for (i = 0; i < cpu_count; i++) { + vector times; + //? 0=user, 1=nice, 2=system, 3=idle + for (int x = 0; const unsigned int c_state : {CPU_STATE_USER, CPU_STATE_NICE, CPU_STATE_SYSTEM, CPU_STATE_IDLE}) { + auto val = cpu_load_info[i].cpu_ticks[c_state]; + times.push_back(val); + times_summed.at(x++) += val; + } + + try { + //? All values + const long long totals = std::accumulate(times.begin(), times.end(), 0ll); + + //? Idle time + const long long idles = times.at(3); + + global_totals += totals; + global_idles += idles; + + //? Calculate cpu total for each core + if (i > Shared::coreCount) break; + const long long calc_totals = max(0ll, totals - core_old_totals.at(i)); + const long long calc_idles = max(0ll, idles - core_old_idles.at(i)); + core_old_totals.at(i) = totals; + core_old_idles.at(i) = idles; + + cpu.core_percent.at(i).push_back(clamp((long long)round((double)(calc_totals - calc_idles) * 100 / calc_totals), 0ll, 100ll)); + + //? Reduce size if there are more values than needed for graph + if (cpu.core_percent.at(i).size() > 40) cpu.core_percent.at(i).pop_front(); + + } catch (const std::exception &e) { + Logger::error("Cpu::collect() : " + (string)e.what()); + throw std::runtime_error("collect() : " + (string)e.what()); + } + } + + const long long calc_totals = max(1ll, global_totals - cpu_old.at("totals")); + const long long calc_idles = max(1ll, global_idles - cpu_old.at("idles")); + + //? Populate cpu.cpu_percent with all fields from syscall + for (int ii = 0; const auto &val : times_summed) { + cpu.cpu_percent.at(time_names.at(ii)).push_back(clamp((long long)round((double)(val - cpu_old.at(time_names.at(ii))) * 100 / calc_totals), 0ll, 100ll)); + cpu_old.at(time_names.at(ii)) = val; + + //? Reduce size if there are more values than needed for graph + while (cmp_greater(cpu.cpu_percent.at(time_names.at(ii)).size(), width * 2)) cpu.cpu_percent.at(time_names.at(ii)).pop_front(); + + ii++; + } + + cpu_old.at("totals") = global_totals; + cpu_old.at("idles") = global_idles; + + //? Total usage of cpu + cpu.cpu_percent.at("total").push_back(clamp((long long)round((double)(calc_totals - calc_idles) * 100 / calc_totals), 0ll, 100ll)); + + //? Reduce size if there are more values than needed for graph + while (cmp_greater(cpu.cpu_percent.at("total").size(), width * 2)) cpu.cpu_percent.at("total").pop_front(); + + if (Config::getB("show_cpu_freq")) { + auto hz = get_cpuHz(); + if (hz != "") { + cpuHz = hz; + } + } + + if (Config::getB("check_temp") and got_sensors) + update_sensors(); + + if (Config::getB("show_battery") and has_battery) + current_bat = get_battery(); + + return cpu; + } +} // namespace Cpu + +namespace Mem { + bool has_swap = false; + vector fstab; + fs::file_time_type fstab_time; + int disk_ios = 0; + vector last_found; + + mem_info current_mem{}; + + uint64_t get_totalMem() { + return Shared::totalMem; + } + + int64_t getCFNumber(CFDictionaryRef dict, const void *key) { + CFNumberRef ref = (CFNumberRef)CFDictionaryGetValue(dict, key); + if (ref) { + int64_t value; + CFNumberGetValue(ref, kCFNumberSInt64Type, &value); + return value; + } + return 0; + } + + string getCFString(io_registry_entry_t volumeRef, CFStringRef key) { + CFStringRef bsdNameRef = (CFStringRef)IORegistryEntryCreateCFProperty(volumeRef, key, kCFAllocatorDefault, 0); + if (bsdNameRef) { + char buf[200]; + CFStringGetCString(bsdNameRef, buf, 200, kCFStringEncodingASCII); + CFRelease(bsdNameRef); + return string(buf); + } + return ""; + } + + bool isWhole(io_registry_entry_t volumeRef) { + CFBooleanRef isWhole = (CFBooleanRef)IORegistryEntryCreateCFProperty(volumeRef, CFSTR("Whole"), kCFAllocatorDefault, 0); + Boolean val = CFBooleanGetValue(isWhole); + CFRelease(isWhole); + return bool(val); + } + + class IOObject { + public: + IOObject(string name, io_object_t& obj) : name(name), object(obj) {} + virtual ~IOObject() { IOObjectRelease(object); } + private: + string name; + io_object_t &object; + }; + + void collect_disk(unordered_flat_map &disks, unordered_flat_map &mapping) { + io_registry_entry_t drive; + io_iterator_t drive_list; + + mach_port_t libtop_master_port; + if (IOMasterPort(bootstrap_port, &libtop_master_port)) { + Logger::error("errot getting master port"); + return; + } + /* Get the list of all drive objects. */ + if (IOServiceGetMatchingServices(libtop_master_port, + IOServiceMatching("IOMediaBSDClient"), &drive_list)) { + Logger::error("Error in IOServiceGetMatchingServices()"); + return; + } + auto d = IOObject("drive list", drive_list); // dummy var so it gets destroyed + while ((drive = IOIteratorNext(drive_list)) != 0) { + auto dr = IOObject("drive", drive); + io_registry_entry_t volumeRef; + IORegistryEntryGetParentEntry(drive, kIOServicePlane, &volumeRef); + if (volumeRef) { + if (!isWhole(volumeRef)) { + string bsdName = getCFString(volumeRef, CFSTR("BSD Name")); + string device = getCFString(volumeRef, CFSTR("VolGroupMntFromName")); + if (!mapping.contains(device)) { + device = "/dev/" + bsdName; // try again with BSD name - not all volumes seem to have VolGroupMntFromName property + } + if (device != "") { + if (mapping.contains(device)) { + string mountpoint = mapping.at(device); + if (disks.contains(mountpoint)) { + auto& disk = disks.at(mountpoint); + CFDictionaryRef properties; + IORegistryEntryCreateCFProperties(volumeRef, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0); + if (properties) { + CFDictionaryRef statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR("Statistics")); + if (statistics) { + disk_ios++; + int64_t readBytes = getCFNumber(statistics, CFSTR("Bytes read from block device")); + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (readBytes - disk.old_io.at(0)))); + disk.old_io.at(0) = readBytes; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + + int64_t writeBytes = getCFNumber(statistics, CFSTR("Bytes written to block device")); + if (disk.io_write.empty()) + disk.io_write.push_back(0); + else + disk.io_write.push_back(max((int64_t)0, (writeBytes - disk.old_io.at(1)))); + disk.old_io.at(1) = writeBytes; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + + // IOKit does not give us IO times, (use IO read + IO write with 1 MiB being 100% to get some activity indication) + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(clamp((long)round((double)(disk.io_write.back() + disk.io_read.back()) / (1 << 20)), 0l, 100l)); + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + } + } + CFRelease(properties); + } + } + } + } + } + } + } + + auto collect(const bool no_update) -> mem_info & { + if (Runner::stopping or (no_update and not current_mem.percent.at("used").empty())) + return current_mem; + + auto &show_swap = Config::getB("show_swap"); + auto &show_disks = Config::getB("show_disks"); + auto &swap_disk = Config::getB("swap_disk"); + auto &mem = current_mem; + static const bool snapped = (getenv("BTOP_SNAPPED") != NULL); + + vm_statistics64 p; + mach_msg_type_number_t info_size = HOST_VM_INFO64_COUNT; + if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&p, &info_size) == 0) { + mem.stats.at("free") = p.free_count * Shared::pageSize; + mem.stats.at("cached") = p.external_page_count * Shared::pageSize; + mem.stats.at("used") = (p.active_count + p.inactive_count + p.wire_count) * Shared::pageSize; + mem.stats.at("available") = Shared::totalMem - mem.stats.at("used"); + } + + int mib[2] = {CTL_VM, VM_SWAPUSAGE}; + + struct xsw_usage swap; + size_t len = sizeof(struct xsw_usage); + if (sysctl(mib, 2, &swap, &len, NULL, 0) == 0) { + mem.stats.at("swap_total") = swap.xsu_total; + mem.stats.at("swap_free") = swap.xsu_avail; + mem.stats.at("swap_used") = swap.xsu_used; + } + + if (show_swap and mem.stats.at("swap_total") > 0) { + for (const auto &name : swap_names) { + mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / mem.stats.at("swap_total"))); + while (cmp_greater(mem.percent.at(name).size(), width * 2)) + mem.percent.at(name).pop_front(); + } + has_swap = true; + } else + has_swap = false; + //? Calculate percentages + for (const auto &name : mem_names) { + mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / Shared::totalMem)); + while (cmp_greater(mem.percent.at(name).size(), width * 2)) + mem.percent.at(name).pop_front(); + } + + if (show_disks) { + unordered_flat_map mapping; // keep mapping from device -> mountpoint, since IOKit doesn't give us the mountpoint + double uptime = system_uptime(); + auto &disks_filter = Config::getS("disks_filter"); + bool filter_exclude = false; + // auto &only_physical = Config::getB("only_physical"); + auto &disks = mem.disks; + vector filter; + if (not disks_filter.empty()) { + filter = ssplit(disks_filter); + if (filter.at(0).starts_with("exclude=")) { + filter_exclude = true; + filter.at(0) = filter.at(0).substr(8); + } + } + + struct statfs *stfs; + int count = getmntinfo(&stfs, MNT_WAIT); + vector found; + found.reserve(last_found.size()); + for (int i = 0; i < count; i++) { + std::error_code ec; + string mountpoint = stfs[i].f_mntonname; + string dev = stfs[i].f_mntfromname; + mapping[dev] = mountpoint; + + if (string(stfs[i].f_fstypename) == "autofs") { + continue; + } + + //? Match filter if not empty + if (not filter.empty()) { + bool match = v_contains(filter, mountpoint); + if ((filter_exclude and match) or (not filter_exclude and not match)) + continue; + } + + found.push_back(mountpoint); + if (not disks.contains(mountpoint)) { + disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename()}; + + if (disks.at(mountpoint).dev.empty()) + disks.at(mountpoint).dev = dev; + + if (disks.at(mountpoint).name.empty()) + disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); + } + + + if (not v_contains(last_found, mountpoint)) + redraw = true; + + disks.at(mountpoint).free = stfs[i].f_bfree; + disks.at(mountpoint).total = stfs[i].f_iosize; + } + + //? Remove disks no longer mounted or filtered out + if (swap_disk and has_swap) found.push_back("swap"); + for (auto it = disks.begin(); it != disks.end();) { + if (not v_contains(found, it->first)) + it = disks.erase(it); + else + it++; + } + if (found.size() != last_found.size()) redraw = true; + last_found = std::move(found); + + //? Get disk/partition stats + for (auto &[mountpoint, disk] : disks) { + if (std::error_code ec; not fs::exists(mountpoint, ec)) + continue; + struct statvfs vfs; + if (statvfs(mountpoint.c_str(), &vfs) < 0) { + Logger::warning("Failed to get disk/partition stats with statvfs() for: " + mountpoint); + continue; + } + disk.total = vfs.f_blocks * vfs.f_frsize; + disk.free = vfs.f_bfree * vfs.f_frsize; + disk.used = disk.total - disk.free; + disk.used_percent = round((double)disk.used * 100 / disk.total); + disk.free_percent = 100 - disk.used_percent; + } + + //? Setup disks order in UI and add swap if enabled + mem.disks_order.clear(); + if (snapped and disks.contains("/mnt")) + mem.disks_order.push_back("/mnt"); + else if (disks.contains("/")) + mem.disks_order.push_back("/"); + if (swap_disk and has_swap) { + mem.disks_order.push_back("swap"); + if (not disks.contains("swap")) + disks["swap"] = {"", "swap"}; + disks.at("swap").total = mem.stats.at("swap_total"); + disks.at("swap").used = mem.stats.at("swap_used"); + disks.at("swap").free = mem.stats.at("swap_free"); + disks.at("swap").used_percent = mem.percent.at("swap_used").back(); + disks.at("swap").free_percent = mem.percent.at("swap_free").back(); + } + for (const auto &name : last_found) + if (not is_in(name, "/", "swap", "/dev")) + mem.disks_order.push_back(name); + + disk_ios = 0; + collect_disk(disks, mapping); + + old_uptime = uptime; + } + return mem; + } + +} // namespace Mem + +namespace Net { + unordered_flat_map current_net; + net_info empty_net = {}; + vector interfaces; + string selected_iface; + int errors = 0; + unordered_flat_map graph_max = {{"download", {}}, {"upload", {}}}; + unordered_flat_map> max_count = {{"download", {}}, {"upload", {}}}; + bool rescale = true; + uint64_t timestamp = 0; + + //* RAII wrapper for getifaddrs + class getifaddr_wrapper { + struct ifaddrs *ifaddr; + + public: + int status; + getifaddr_wrapper() { status = getifaddrs(&ifaddr); } + ~getifaddr_wrapper() { freeifaddrs(ifaddr); } + auto operator()() -> struct ifaddrs * { return ifaddr; } + }; + + auto collect(const bool no_update) -> net_info & { + auto &net = current_net; + auto &config_iface = Config::getS("net_iface"); + auto &net_sync = Config::getB("net_sync"); + auto &net_auto = Config::getB("net_auto"); + auto new_timestamp = time_ms(); + + if (not no_update and errors < 3) { + //? Get interface list using getifaddrs() wrapper + getifaddr_wrapper if_wrap{}; + if (if_wrap.status != 0) { + errors++; + Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_wrap.status)); + redraw = true; + return empty_net; + } + int family = 0; + char ip[NI_MAXHOST]; + interfaces.clear(); + string ipv4, ipv6; + + //? Iteration over all items in getifaddrs() list + for (auto *ifa = if_wrap(); ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) continue; + family = ifa->ifa_addr->sa_family; + const auto &iface = ifa->ifa_name; + //? Get IPv4 address + if (family == AF_INET) { + if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) + net[iface].ipv4 = ip; + } + //? Get IPv6 address + else if (family == AF_INET6) { + if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) + net[iface].ipv6 = ip; + } + + //? Update available interfaces vector and get status of interface + if (not v_contains(interfaces, iface)) { + interfaces.push_back(iface); + net[iface].connected = (ifa->ifa_flags & IFF_RUNNING); + } + } + + unordered_flat_map> ifstats; + int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0}; + size_t len; + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { + Logger::error("failed getting network interfaces"); + } else { + std::unique_ptr buf(new char[len]); + if (sysctl(mib, 6, buf.get(), &len, NULL, 0) < 0) { + Logger::error("failed getting network interfaces"); + } else { + char *lim = buf.get() + len; + char *next = NULL; + for (next = buf.get(); next < lim;) { + struct if_msghdr *ifm = (struct if_msghdr *)next; + next += ifm->ifm_msglen; + if (ifm->ifm_type == RTM_IFINFO2) { + struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm; + struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); + char iface[32]; + strncpy(iface, sdl->sdl_data, sdl->sdl_nlen); + iface[sdl->sdl_nlen] = 0; + ifstats[iface] = std::tuple(if2m->ifm_data.ifi_ibytes, if2m->ifm_data.ifi_obytes); + } + } + } + } + + //? Get total recieved and transmitted bytes + device address if no ip was found + for (const auto &iface : interfaces) { + for (const string dir : {"download", "upload"}) { + auto &saved_stat = net.at(iface).stat.at(dir); + auto &bandwidth = net.at(iface).bandwidth.at(dir); + auto dirval = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); + uint64_t val = saved_stat.last; + try { + val = max(dirval, val); + } catch (const std::invalid_argument &) { + } catch (const std::out_of_range &) { + } + + //? Update speed, total and top values + saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); + if (saved_stat.speed > saved_stat.top) saved_stat.top = saved_stat.speed; + if (saved_stat.offset > val) saved_stat.offset = 0; + saved_stat.total = val - saved_stat.offset; + saved_stat.last = val; + + //? Add values to graph + bandwidth.push_back(saved_stat.speed); + while (cmp_greater(bandwidth.size(), width * 2)) bandwidth.pop_front(); + + //? Set counters for auto scaling + if (net_auto and selected_iface == iface) { + if (saved_stat.speed > graph_max[dir]) { + ++max_count[dir][0]; + if (max_count[dir][1] > 0) --max_count[dir][1]; + } else if (graph_max[dir] > 10 << 10 and saved_stat.speed < graph_max[dir] / 10) { + ++max_count[dir][1]; + if (max_count[dir][0] > 0) --max_count[dir][0]; + } + } + } + } + + //? Clean up net map if needed + if (net.size() > interfaces.size()) { + for (auto it = net.begin(); it != net.end();) { + if (not v_contains(interfaces, it->first)) + it = net.erase(it); + else + it++; + } + net.compact(); + } + + timestamp = new_timestamp; + } + //? Return empty net_info struct if no interfaces was found + if (net.empty()) + return empty_net; + + //? Find an interface to display if selected isn't set or valid + if (selected_iface.empty() or not v_contains(interfaces, selected_iface)) { + max_count["download"][0] = max_count["download"][1] = max_count["upload"][0] = max_count["upload"][1] = 0; + redraw = true; + if (net_auto) rescale = true; + if (not config_iface.empty() and v_contains(interfaces, config_iface)) + selected_iface = config_iface; + else { + //? Sort interfaces by total upload + download bytes + auto sorted_interfaces = interfaces; + rng::sort(sorted_interfaces, [&](const auto &a, const auto &b) { + return cmp_greater(net.at(a).stat["download"].total + net.at(a).stat["upload"].total, + net.at(b).stat["download"].total + net.at(b).stat["upload"].total); + }); + selected_iface.clear(); + //? Try to set to a connected interface + for (const auto &iface : sorted_interfaces) { + if (net.at(iface).connected) selected_iface = iface; + break; + } + //? If no interface is connected set to first available + if (selected_iface.empty() and not sorted_interfaces.empty()) + selected_iface = sorted_interfaces.at(0); + else if (sorted_interfaces.empty()) + return empty_net; + } + } + + //? Calculate max scale for graphs if needed + if (net_auto) { + bool sync = false; + for (const auto &dir : {"download", "upload"}) { + for (const auto &sel : {0, 1}) { + if (rescale or max_count[dir][sel] >= 5) { + const uint64_t avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 + ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0) / 5 + : net[selected_iface].stat[dir].speed); + graph_max[dir] = max(uint64_t(avg_speed * (sel == 0 ? 1.3 : 3.0)), (uint64_t)10 << 10); + max_count[dir][0] = max_count[dir][1] = 0; + redraw = true; + if (net_sync) sync = true; + break; + } + } + //? Sync download/upload graphs if enabled + if (sync) { + const auto other = (string(dir) == "upload" ? "download" : "upload"); + graph_max[other] = graph_max[dir]; + max_count[other][0] = max_count[other][1] = 0; + break; + } + } + } + + rescale = false; + return net.at(selected_iface); + } +} // namespace Net + +namespace Proc { + + vector current_procs; + unordered_flat_map uid_user; + string current_sort; + string current_filter; + bool current_rev = false; + + fs::file_time_type passwd_time; + + uint64_t cputimes; + int collapse = -1, expand = -1; + uint64_t old_cputimes = 0; + atomic numpids = 0; + int filter_found = 0; + + detail_container detailed; + + //* Generate process tree list + void _tree_gen(proc_info &cur_proc, vector &in_procs, vector> &out_procs, int cur_depth, const bool collapsed, const string &filter, bool found = false, const bool no_update = false, const bool should_filter = false) { + auto cur_pos = out_procs.size(); + bool filtering = false; + + //? If filtering, include children of matching processes + if (not found and (should_filter or not filter.empty())) { + if (not s_contains(std::to_string(cur_proc.pid), filter) and not s_contains(cur_proc.name, filter) and not s_contains(cur_proc.cmd, filter) and not s_contains(cur_proc.user, filter)) { + filtering = true; + cur_proc.filtered = true; + filter_found++; + } else { + found = true; + cur_depth = 0; + } + } else if (cur_proc.filtered) + cur_proc.filtered = false; + + //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree + if (not collapsed and not filtering) { + out_procs.push_back(std::ref(cur_proc)); + cur_proc.tree_index = out_procs.size() - 1; + //? Try to find name of the binary file and append to program name if not the same + if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { + std::string_view cmd_view = cur_proc.cmd; + cmd_view = cmd_view.substr((size_t)0, min(cmd_view.find(' '), cmd_view.size())); + cmd_view = cmd_view.substr(min(cmd_view.find_last_of('/') + 1, cmd_view.size())); + cur_proc.short_cmd = (string)cmd_view; + } + } else { + cur_proc.tree_index = in_procs.size(); + } + + //? Recursive iteration over all children + int children = 0; + for (auto &p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { + if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { + out_procs.back().get().cpu_p += p.cpu_p; + out_procs.back().get().mem += p.mem; + out_procs.back().get().threads += p.threads; + filter_found++; + } + if (collapsed and not filtering) { + cur_proc.filtered = true; + } else + children++; + _tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cur_proc.collapsed), filter, found, no_update, should_filter); + } + if (collapsed or filtering) + return; + + //? Add tree terminator symbol if it's the last child in a sub-tree + if (out_procs.size() > cur_pos + 1 and not out_procs.back().get().prefix.ends_with("]─")) + out_procs.back().get().prefix.replace(out_procs.back().get().prefix.size() - 8, 8, " └─ "); + + //? Add collapse/expand symbols if process have any children + out_procs.at(cur_pos).get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); + } + + string get_status(char s) { + if (s & SRUN) return "Running"; + if (s & SSLEEP) return "Sleeping"; + if (s & SIDL) return "Idle"; + if (s & SSTOP) return "Stopped"; + if (s & SZOMB) return "Zombie"; + return "Unknown"; + } + + //* Get detailed info for selected process + void _collect_details(const size_t pid, vector &procs) { + if (pid != detailed.last_pid) { + detailed = {}; + detailed.last_pid = pid; + detailed.skip_smaps = not Config::getB("proc_info_smaps"); + } + + //? Copy proc_info for process from proc vector + auto p_info = rng::find(procs, pid, &proc_info::pid); + detailed.entry = *p_info; + + //? Update cpu percent deque for process cpu graph + if (not Config::getB("proc_per_core")) detailed.entry.cpu_p *= Shared::coreCount; + detailed.cpu_percent.push_back(clamp((long long)round(detailed.entry.cpu_p), 0ll, 100ll)); + while (cmp_greater(detailed.cpu_percent.size(), width)) detailed.cpu_percent.pop_front(); + + //? Process runtime : current time - start time (both in unix time - seconds since epoch) + struct timeval currentTime; + gettimeofday(¤tTime, NULL); + detailed.elapsed = sec_to_dhms(currentTime.tv_sec - (detailed.entry.cpu_s / 1'000'000)); + if (detailed.elapsed.size() > 8) detailed.elapsed.resize(detailed.elapsed.size() - 3); + + //? Get parent process name + if (detailed.parent.empty()) { + auto p_entry = rng::find(procs, detailed.entry.ppid, &proc_info::pid); + if (p_entry != procs.end()) detailed.parent = p_entry->name; + } + + //? Expand process status from single char to explanative string + detailed.status = get_status(detailed.entry.state); + + detailed.mem_bytes.push_back(detailed.entry.mem); + detailed.memory = floating_humanizer(detailed.entry.mem); + + if (detailed.first_mem == -1 or detailed.first_mem < detailed.mem_bytes.back() / 2 or detailed.first_mem > detailed.mem_bytes.back() * 4) { + detailed.first_mem = min((uint64_t)detailed.mem_bytes.back() * 2, Mem::get_totalMem()); + redraw = true; + } + + while (cmp_greater(detailed.mem_bytes.size(), width)) detailed.mem_bytes.pop_front(); + + rusage_info_current rusage; + if (proc_pid_rusage(pid, RUSAGE_INFO_CURRENT, (void **)&rusage) == 0) { + // this fails for processes we don't own - same as in Linux + detailed.io_read = floating_humanizer(rusage.ri_diskio_bytesread); + detailed.io_write = floating_humanizer(rusage.ri_diskio_byteswritten); + } + } + + //* Collects and sorts process information from /proc + auto collect(const bool no_update) -> vector & { + const auto &sorting = Config::getS("proc_sorting"); + const auto &reverse = Config::getB("proc_reversed"); + const auto &filter = Config::getS("proc_filter"); + const auto &per_core = Config::getB("proc_per_core"); + const auto &tree = Config::getB("proc_tree"); + const auto &show_detailed = Config::getB("show_detailed"); + const size_t detailed_pid = Config::getI("detailed_pid"); + bool should_filter = current_filter != filter; + if (should_filter) current_filter = filter; + const bool sorted_change = (sorting != current_sort or reverse != current_rev or should_filter); + if (sorted_change) { + current_sort = sorting; + current_rev = reverse; + } + + const int cmult = (per_core) ? Shared::coreCount : 1; + bool got_detailed = false; + + //* Use pids from last update if only changing filter, sorting or tree options + if (no_update and not current_procs.empty()) { + if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, current_procs); + } else { + //* ---------------------------------------------Collection start---------------------------------------------- + + { //* Get CPU totals + natural_t cpu_count; + kern_return_t error; + processor_cpu_load_info_data_t *cpu_load_info = NULL; + MachProcessorInfo info{}; + error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &info.info_array, &info.info_count); + if (error != KERN_SUCCESS) { + Logger::error("Failed getting CPU load info"); + } + cpu_load_info = (processor_cpu_load_info_data_t *)info.info_array; + cputimes = 0; + for (natural_t i = 0; i < cpu_count; i++) { + cputimes += (cpu_load_info[i].cpu_ticks[CPU_STATE_USER] + + cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] + + cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] + + cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE]); + } + } + + should_filter = true; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; + vector found; + size_t size = 0; + const auto timeNow = time_micros(); + + if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0 || size == 0) { + Logger::error("Unable to get size of kproc_infos"); + } + uint64_t cpu_t = 0; + + std::unique_ptr processes(new kinfo_proc[size / sizeof(kinfo_proc)]); + if (sysctl(mib, 4, processes.get(), &size, NULL, 0) == 0) { + size_t count = size / sizeof(struct kinfo_proc); + for (size_t i = 0; i < count; i++) { //* iterate over all processes in kinfo_proc + struct kinfo_proc& kproc = processes.get()[i]; + const size_t pid = (size_t)kproc.kp_proc.p_pid; + if (pid < 1) continue; + found.push_back(pid); + + //? Check if pid already exists in current_procs + bool no_cache = false; + auto find_old = rng::find(current_procs, pid, &proc_info::pid); + if (find_old == current_procs.end()) { + current_procs.push_back({pid}); + find_old = current_procs.end() - 1; + no_cache = true; + } + + auto &new_proc = *find_old; + + //? Get program name, command, username, parent pid, nice and status + if (no_cache) { + char fullname[PROC_PIDPATHINFO_MAXSIZE]; + proc_pidpath(pid, fullname, sizeof(fullname)); + const string f_name = std::string(fullname); + size_t lastSlash = f_name.find_last_of('/'); + new_proc.name = f_name.substr(lastSlash + 1); + //? Get process arguments if possible, fallback to process path in case of failure + if (Shared::arg_max > 0) { + std::unique_ptr proc_chars(new char[Shared::arg_max]); + int mib[] = {CTL_KERN, KERN_PROCARGS2, (int)pid}; + size_t argmax = Shared::arg_max; + if (sysctl(mib, 3, proc_chars.get(), &argmax, NULL, 0) == 0) { + int argc = 0; + memcpy(&argc, &proc_chars.get()[0], sizeof(argc)); + std::string_view proc_args(proc_chars.get(), argmax); + if (size_t null_pos = proc_args.find('\0', sizeof(argc)); null_pos != string::npos) { + if (size_t start_pos = proc_args.find_first_not_of('\0', null_pos); start_pos != string::npos) { + while (argc-- > 0 and null_pos != string::npos) { + null_pos = proc_args.find('\0', start_pos); + new_proc.cmd += (string)proc_args.substr(start_pos, null_pos - start_pos) + ' '; + start_pos = null_pos + 1; + } + } + } + if (not new_proc.cmd.empty()) new_proc.cmd.pop_back(); + } + } + if (new_proc.cmd.empty()) new_proc.cmd = f_name; + new_proc.ppid = kproc.kp_eproc.e_ppid; + new_proc.cpu_s = kproc.kp_proc.p_starttime.tv_sec * 1'000'000 + kproc.kp_proc.p_starttime.tv_usec; + struct passwd *pwd = getpwuid(kproc.kp_eproc.e_ucred.cr_uid); + new_proc.user = pwd->pw_name; + } + new_proc.p_nice = kproc.kp_proc.p_nice; + new_proc.state = kproc.kp_proc.p_stat; + + //? Get threads, mem and cpu usage + struct proc_taskinfo pti; + if (sizeof(pti) == proc_pidinfo(new_proc.pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti))) { + new_proc.threads = pti.pti_threadnum; + new_proc.mem = pti.pti_resident_size; + cpu_t = pti.pti_total_user + pti.pti_total_system; + + if (new_proc.cpu_t == 0) new_proc.cpu_t = cpu_t; + } + + //? Process cpu usage since last update + new_proc.cpu_p = clamp(round(((cpu_t - new_proc.cpu_t) * Shared::machTck) / ((cputimes - old_cputimes) * Shared::clkTck)) * cmult / 1000.0, 0.0, 100.0 * Shared::coreCount); + + //? Process cumulative cpu usage since process start + new_proc.cpu_c = (double)(cpu_t * Shared::machTck) / (timeNow - new_proc.cpu_s); + + //? Update cached value with latest cpu times + new_proc.cpu_t = cpu_t; + + if (show_detailed and not got_detailed and new_proc.pid == detailed_pid) { + got_detailed = true; + } + } + + // //? Clear dead processes from current_procs + auto eraser = rng::remove_if(current_procs, [&](const auto &element) { return not v_contains(found, element.pid); }); + current_procs.erase(eraser.begin(), eraser.end()); + + //? Update the details info box for process if active + if (show_detailed and got_detailed) { + _collect_details(detailed_pid, current_procs); + } else if (show_detailed and not got_detailed and detailed.status != "Dead") { + detailed.status = "Dead"; + redraw = true; + } + + old_cputimes = cputimes; + } + } + + //* ---------------------------------------------Collection done----------------------------------------------- + + //* Sort processes + if (sorted_change or not no_update) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::sort(current_procs, rng::greater{}, &proc_info::pid); break; + case 1: rng::sort(current_procs, rng::greater{}, &proc_info::name); break; + case 2: rng::sort(current_procs, rng::greater{}, &proc_info::cmd); break; + case 3: rng::sort(current_procs, rng::greater{}, &proc_info::threads); break; + case 4: rng::sort(current_procs, rng::greater{}, &proc_info::user); break; + case 5: rng::sort(current_procs, rng::greater{}, &proc_info::mem); break; + case 6: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + } + if (reverse) rng::reverse(current_procs); + + //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage + if (not tree and not reverse and sorting == "cpu lazy") { + double max = 10.0, target = 30.0; + for (size_t i = 0, x = 0, offset = 0; i < current_procs.size(); i++) { + if (i <= 5 and current_procs.at(i).cpu_p > max) + max = current_procs.at(i).cpu_p; + else if (i == 6) + target = (max > 30.0) ? max : 10.0; + if (i == offset and current_procs.at(i).cpu_p > 30.0) + offset++; + else if (current_procs.at(i).cpu_p > target) { + rotate(current_procs.begin() + offset, current_procs.begin() + i, current_procs.begin() + i + 1); + if (++x > 10) break; + } + } + } + } + + //* Match filter if defined + if (should_filter) { + filter_found = 0; + for (auto &p : current_procs) { + if (not tree and not filter.empty()) { + if (not s_contains(to_string(p.pid), filter) and not s_contains(p.name, filter) and not s_contains(p.cmd, filter) and not s_contains(p.user, filter)) { + p.filtered = true; + filter_found++; + } else { + p.filtered = false; + } + } else { + p.filtered = false; + } + } + } + + //* Generate tree view if enabled + if (tree and (not no_update or should_filter or sorted_change)) { + if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { + auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); + if (collapser != current_procs.end()) { + if (collapse == expand) { + collapser->collapsed = not collapser->collapsed; + } else if (collapse > -1) { + collapser->collapsed = true; + } else if (expand > -1) { + collapser->collapsed = false; + } + } + collapse = expand = -1; + } + if (should_filter or not filter.empty()) filter_found = 0; + + vector> tree_procs; + tree_procs.reserve(current_procs.size()); + + //? Stable sort to retain selected sorting among processes with the same parent + rng::stable_sort(current_procs, rng::less{}, &proc_info::ppid); + + //? Start recursive iteration over processes with the lowest shared parent pids + for (auto &p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { + _tree_gen(p, current_procs, tree_procs, 0, false, filter, false, no_update, should_filter); + } + + //? Final sort based on tree index + rng::sort(current_procs, rng::less{}, &proc_info::tree_index); + if (reverse) rng::reverse(current_procs); + } + + numpids = (int)current_procs.size() - filter_found; + return current_procs; + } +} // namespace Proc + +namespace Tools { + double system_uptime() { + struct timeval ts, currTime; + std::size_t len = sizeof(ts); + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + if (sysctl(mib, 2, &ts, &len, NULL, 0) != -1) { + gettimeofday(&currTime, NULL); + return currTime.tv_sec - ts.tv_sec; + } + return 0.0; + } +} // namespace Tools \ No newline at end of file diff --git a/src/osx/sensors.cpp b/src/osx/sensors.cpp new file mode 100644 index 0000000..bd6312e --- /dev/null +++ b/src/osx/sensors.cpp @@ -0,0 +1,92 @@ +#include "sensors.hpp" + +#include +#include + +#include +#include +#include + +extern "C" { +typedef struct __IOHIDEvent *IOHIDEventRef; +typedef struct __IOHIDServiceClient *IOHIDServiceClientRef; +#ifdef __LP64__ +typedef double IOHIDFloat; +#else +typedef float IOHIDFloat; +#endif + +#define IOHIDEventFieldBase(type) (type << 16) +#define kIOHIDEventTypeTemperature 15 + +IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef allocator); +int IOHIDEventSystemClientSetMatching(IOHIDEventSystemClientRef client, CFDictionaryRef match); +int IOHIDEventSystemClientSetMatchingMultiple(IOHIDEventSystemClientRef client, CFArrayRef match); +IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t, int32_t, int64_t); +CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property); +IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field); + +// create a dict ref, like for temperature sensor {"PrimaryUsagePage":0xff00, "PrimaryUsage":0x5} +CFDictionaryRef matching(int page, int usage) { + CFNumberRef nums[2]; + CFStringRef keys[2]; + + keys[0] = CFStringCreateWithCString(0, "PrimaryUsagePage", 0); + keys[1] = CFStringCreateWithCString(0, "PrimaryUsage", 0); + nums[0] = CFNumberCreate(0, kCFNumberSInt32Type, &page); + nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage); + + CFDictionaryRef dict = CFDictionaryCreate(0, (const void **)keys, (const void **)nums, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(keys); + return dict; +} + +double getValue(IOHIDServiceClientRef sc) { + IOHIDEventRef event = IOHIDServiceClientCopyEvent(sc, kIOHIDEventTypeTemperature, 0, 0); // here we use ...CopyEvent + IOHIDFloat temp = 0.0; + if (event != 0) { + temp = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(kIOHIDEventTypeTemperature)); + CFRelease(event); + } + return temp; +} + +} // extern C + +long long Cpu::ThermalSensors::getSensors() { + CFDictionaryRef thermalSensors = matching(0xff00, 5); // 65280_10 = FF00_16 + // thermalSensors's PrimaryUsagePage should be 0xff00 for M1 chip, instead of 0xff05 + // can be checked by ioreg -lfx + IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault); + IOHIDEventSystemClientSetMatching(system, thermalSensors); + CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system); + std::vector temps; + if (matchingsrvs) { + long count = CFArrayGetCount(matchingsrvs); + for (int i = 0; i < count; i++) { + IOHIDServiceClientRef sc = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(matchingsrvs, i); + if (sc) { + CFStringRef name = IOHIDServiceClientCopyProperty(sc, CFSTR("Product")); // here we use ...CopyProperty + if (name) { + char buf[200]; + CFStringGetCString(name, buf, 200, kCFStringEncodingASCII); + std::string n(buf); + // this is just a guess, nobody knows which sensors mean what + // on my system PMU tdie 3 and 9 are missing... + // there is also PMU tdev1-8 but it has negative values?? + // there is also eACC for efficiency package but it only has 2 entries + // and pACC for performance but it has 7 entries (2 - 9) WTF + if (n.starts_with("eACC") or n.starts_with("pACC")) { + temps.push_back(getValue(sc)); + } + CFRelease(name); + } + } + } + CFRelease(matchingsrvs); + } + CFRelease(system); + CFRelease(thermalSensors); + if (temps.empty()) return 0ll; + return round(std::accumulate(temps.begin(), temps.end(), 0ll) / temps.size()); +} diff --git a/src/osx/sensors.hpp b/src/osx/sensors.hpp new file mode 100644 index 0000000..48287ee --- /dev/null +++ b/src/osx/sensors.hpp @@ -0,0 +1,7 @@ + +namespace Cpu { + class ThermalSensors { + public: + long long getSensors(); + }; +} // namespace Cpu diff --git a/src/osx/smc.cpp b/src/osx/smc.cpp new file mode 100644 index 0000000..2482ae3 --- /dev/null +++ b/src/osx/smc.cpp @@ -0,0 +1,120 @@ +#include "smc.hpp" + +static UInt32 _strtoul(char *str, int size, int base) { + UInt32 total = 0; + int i; + + for (i = 0; i < size; i++) { + if (base == 16) { + total += str[i] << (size - 1 - i) * 8; + } else { + total += (unsigned char)(str[i] << (size - 1 - i) * 8); + } + } + return total; +} + +static void _ultostr(char *str, UInt32 val) { + str[0] = '\0'; + sprintf(str, "%c%c%c%c", + (unsigned int)val >> 24, + (unsigned int)val >> 16, + (unsigned int)val >> 8, + (unsigned int)val); +} + +namespace Cpu { + + SMCConnection::SMCConnection() { + IOMasterPort(kIOMasterPortDefault, &masterPort); + + CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC"); + result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator); + if (result != kIOReturnSuccess) { + throw std::runtime_error("failed to get AppleSMC"); + } + + device = IOIteratorNext(iterator); + IOObjectRelease(iterator); + if (device == 0) { + throw std::runtime_error("failed to get SMC device"); + } + + result = IOServiceOpen(device, mach_task_self(), 0, &conn); + IOObjectRelease(device); + if (result != kIOReturnSuccess) { + throw std::runtime_error("failed to get SMC connection"); + } + } + SMCConnection::~SMCConnection() { + IOServiceClose(conn); + } + + // core means physical core in SMC, while in core map it's cpu threads :-/ Only an issue on hackintosh? + // this means we can only get the T per physical core + // another issue with the SMC API is that the key is always 4 chars -> what with systems with more than 9 physical cores? + // no Mac models with more than 18 threads are released, so no problem so far + // according to VirtualSMC docs (hackintosh fake SMC) the enumeration follows with alphabetic chars - not implemented yet here (nor in VirtualSMC) + long long SMCConnection::getTemp(int core) { + SMCVal_t val; + kern_return_t result; + char key[] = SMC_KEY_CPU_TEMP; + if (core >= 0) { + snprintf(key, 5, "TC%1dc", core); + } + result = SMCReadKey(key, &val); + if (result == kIOReturnSuccess) { + if (strcmp(val.dataType, DATATYPE_SP78) == 0) { + // convert sp78 value to temperature + int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1]; + return static_cast(intValue / 256.0); + } + } + return -1; + } + + kern_return_t SMCConnection::SMCReadKey(UInt32Char_t key, SMCVal_t *val) { + kern_return_t result; + SMCKeyData_t inputStructure; + SMCKeyData_t outputStructure; + + memset(&inputStructure, 0, sizeof(SMCKeyData_t)); + memset(&outputStructure, 0, sizeof(SMCKeyData_t)); + memset(val, 0, sizeof(SMCVal_t)); + + inputStructure.key = _strtoul(key, 4, 16); + inputStructure.data8 = SMC_CMD_READ_KEYINFO; + + result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure); + if (result != kIOReturnSuccess) + return result; + + val->dataSize = outputStructure.keyInfo.dataSize; + _ultostr(val->dataType, outputStructure.keyInfo.dataType); + inputStructure.keyInfo.dataSize = val->dataSize; + inputStructure.data8 = SMC_CMD_READ_BYTES; + + result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure); + if (result != kIOReturnSuccess) + return result; + + memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes)); + + return kIOReturnSuccess; + } + + kern_return_t SMCConnection::SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure) { + size_t structureInputSize; + size_t structureOutputSize; + + structureInputSize = sizeof(SMCKeyData_t); + structureOutputSize = sizeof(SMCKeyData_t); + + return IOConnectCallStructMethod(conn, index, + // inputStructure + inputStructure, structureInputSize, + // ouputStructure + outputStructure, &structureOutputSize); + } + +} // namespace Cpu diff --git a/src/osx/smc.hpp b/src/osx/smc.hpp new file mode 100644 index 0000000..0aa02c1 --- /dev/null +++ b/src/osx/smc.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#define VERSION "0.01" + +#define KERNEL_INDEX_SMC 2 + +#define SMC_CMD_READ_BYTES 5 +#define SMC_CMD_WRITE_BYTES 6 +#define SMC_CMD_READ_INDEX 8 +#define SMC_CMD_READ_KEYINFO 9 +#define SMC_CMD_READ_PLIMIT 11 +#define SMC_CMD_READ_VERS 12 + +#define DATATYPE_FPE2 "fpe2" +#define DATATYPE_UINT8 "ui8 " +#define DATATYPE_UINT16 "ui16" +#define DATATYPE_UINT32 "ui32" +#define DATATYPE_SP78 "sp78" + +// key values +#define SMC_KEY_CPU_TEMP "TC0P" +#define SMC_KEY_CPU1_TEMP "TC1C" +#define SMC_KEY_CPU2_TEMP "TC2C" // etc +#define SMC_KEY_FAN0_RPM_CUR "F0Ac" + +typedef struct { + char major; + char minor; + char build; + char reserved[1]; + UInt16 release; +} SMCKeyData_vers_t; + +typedef struct { + UInt16 version; + UInt16 length; + UInt32 cpuPLimit; + UInt32 gpuPLimit; + UInt32 memPLimit; +} SMCKeyData_pLimitData_t; + +typedef struct { + UInt32 dataSize; + UInt32 dataType; + char dataAttributes; +} SMCKeyData_keyInfo_t; + +typedef char SMCBytes_t[32]; + +typedef struct { + UInt32 key; + SMCKeyData_vers_t vers; + SMCKeyData_pLimitData_t pLimitData; + SMCKeyData_keyInfo_t keyInfo; + char result; + char status; + char data8; + UInt32 data32; + SMCBytes_t bytes; +} SMCKeyData_t; + +typedef char UInt32Char_t[5]; + +typedef struct { + UInt32Char_t key; + UInt32 dataSize; + UInt32Char_t dataType; + SMCBytes_t bytes; +} SMCVal_t; + +namespace Cpu { + class SMCConnection { + public: + SMCConnection(); + virtual ~SMCConnection(); + + long long getTemp(int core); + + private: + kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val); + kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure); + + io_connect_t conn; + kern_return_t result; + mach_port_t masterPort; + io_iterator_t iterator; + io_object_t device; + }; +} // namespace Cpu From 0ed8ad76e84ea57180d39bb63f05b73a369e6c25 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 13 Nov 2021 23:56:29 +0100 Subject: [PATCH 123/289] Fix OSX build on main branch --- .github/workflows/continuous-build-macos.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/continuous-build-macos.yml b/.github/workflows/continuous-build-macos.yml index b747e92..04bf471 100644 --- a/.github/workflows/continuous-build-macos.yml +++ b/.github/workflows/continuous-build-macos.yml @@ -3,7 +3,7 @@ name: Continuous Build MacOS on: push: branches: - - OSX + - main tags-ignore: - '*.*' paths: @@ -21,9 +21,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install build tools - run: | - git checkout OSX - name: Compile run: | make CXX=g++-11 ARCH=x86_64 From 125e3c0cb2857882333a613881fa35ebd30db3e0 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 14 Nov 2021 01:23:12 +0100 Subject: [PATCH 124/289] v1.1.0 OSX Support --- CHANGELOG.md | 4 ++ Makefile | 4 +- README.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++----- src/btop.cpp | 18 ++++---- 4 files changed, 124 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d134d7e..a2a77d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.1.0 + +* Added: Support for OSX, by @joske and @aristocratos + ## v1.0.24 * Changed: Collection ordering diff --git a/Makefile b/Makefile index 42ff6c1..396b474 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -#* Btop++ makefile v1.4 +#* Btop++ makefile v1.5 -BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.4\033[0m +BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.5\033[0m override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") diff --git a/README.md b/README.md index 2dd6f21..c668a00 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ ![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux) +![OSX](https://img.shields.io/badge/-OSX-black?logo=apple) +![FreeBSD](https://img.shields.io/badge/-FreeBSD-red?logo=freebsd) ![Usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-yellow) ![c++20](https://img.shields.io/badge/cpp-c%2B%2B20-green) ![latest_release](https://img.shields.io/github/v/tag/aristocratos/btop?label=release) @@ -12,14 +14,11 @@ [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos) [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) -[![Continuous Build](https://github.com/aristocratos/btop/actions/workflows/continuous-build.yml/badge.svg)](https://github.com/aristocratos/btop/actions) +[![Continuous Build Linux](https://github.com/aristocratos/btop/actions/workflows/continuous-build-linux.yml/badge.svg)](https://github.com/aristocratos/btop/actions/workflows/continuous-build-linux.yml) [![Continuous Build MacOS](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml/badge.svg)](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml) - ## Index - - * [News](#news) * [Documents](#documents) * [Description](#description) @@ -29,9 +28,10 @@ * [Prerequisites](#prerequisites) (Read this if you are having issues!) * [Screenshots](#screenshots) * [Keybindings](#help-menu) -* [Installation](#installation) -* [Manual compilation](#compilation) -* [Install the snap](#install-the-snap) +* [Installation Linux/OSX](#installation-linux/osx) +* [Compilation Linux](#compilation-osx) +* [Compilation OSX](#compilation-osx) +* [Installing the snap](#installing-the-snap) * [Configurability](#configurability) * [License](#license) @@ -39,6 +39,16 @@ ### Under development +##### 13 November 2021 + +Release v1.1.0 with OSX support. Binaries in [continuous-build-macos](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml) are only x86 for now. +Macos binaries + installer are included for both x86 and ARM64 (Apple Silicon) in the releases. + +Big thank you to [@joske](https://github.com/joske) who wrote the vast majority of the implementation! + +
+More... + ##### 30 October 2021 Work on the OSX and FreeBSD branches, both initiated and mostly worked on by [@joske](https://github.com/joske), will likely be completed in the coming weeks. @@ -97,6 +107,8 @@ Windows support is not in the plans as of now, but if anyone else wants to take This project is gonna take some time until it has complete feature parity with bpytop, since all system information gathering will have to be written from scratch without any external libraries. And will need some help in the form of code contributions to get complete support for BSD and OSX. +
+ ## Documents **[CHANGELOG.md](CHANGELOG.md)** @@ -203,11 +215,11 @@ Also needs a UTF8 locale and a font that covers: ![Screenshot 5](Img/help-menu.png) -## Installation +## Installation Linux/OSX -**Binary release (statically compiled with musl, for kernel 2.6.39 and newer)** +**Binaries for Linux are statically compiled with musl and works on kernel 2.6.39 and newer** -1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** +1. **Download btop-(VERSION)-(ARCH)-(PLATFORM).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** **Notice! Use x86_64 for 64-bit x86 systems, i486 and i686 are 32-bit!** @@ -263,7 +275,7 @@ Also needs a UTF8 locale and a font that covers: sudo zypper in btop ``` -## Compilation +## Compilation Linux Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary). @@ -355,7 +367,92 @@ Also needs a UTF8 locale and a font that covers: make help ``` -## Install the snap +## Compilation OSX + + Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary). + + The makefile also needs GNU coreutils and `sed`. + + Install and use Homebrew or MacPorts package managers for easy dependency installation + +1. **Install dependencies (example for Homebrew)** + + ``` bash + brew install coreutils make gcc@11 + ``` + +2. **Clone repository** + + ``` bash + git clone https://github.com/aristocratos/btop.git + cd btop + ``` + +3. **Compile** + + Append `QUIET=true` for less verbose output. + + Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). + + Append `ARCH=` to manually set the target architecture. + If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. + + Use `ADDFLAGS` variable for appending flags to both compiler and linker. + + For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + + ``` bash + gmake + ``` + +4. **Install** + + Append `PREFIX=/target/dir` to set target, default: `/usr/local` + + Notice! Only use "sudo" when installing to a NON user owned directory. + + ``` bash + sudo gmake install + ``` + +5. **(Recommended) Set suid bit to make btop always run as root (or other user)** + + No need for `sudo` to see information for non user owned processes and to enable signal sending to any process. + + Run after make install and use same PREFIX if any was used at install. + + Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `wheel` + + ``` bash + sudo gmake setuid + ``` + +* **Uninstall** + + ``` bash + sudo gmake uninstall + ``` + +* **Remove any object files from source dir** + + ```bash + gmake clean + ``` + +* **Remove all object files, binaries and created directories in source dir** + + ```bash + gmake distclean + ``` + +* **Show help** + + ```bash + gmake help + ``` + + +## Installing the snap [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) * **Install the snap** diff --git a/src/btop.cpp b/src/btop.cpp index 5d782f6..88c3403 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.24"; + const string Version = "1.1.0"; int coreCount; string overlay; @@ -179,7 +179,7 @@ void term_resize(bool force) { if (Input::poll()) { auto key = Input::get(); if (key == "q") - exit(0); + clean_quit(0); else if (is_in(key, "1", "2", "3", "4")) { Config::current_preset = -1; Config::toggle_box(all_boxes.at(std::stoi(key) - 1)); @@ -584,7 +584,7 @@ namespace Runner { pthread_cancel(Runner::runner_id); if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) { Global::exit_error_msg = "Failed to re-create _runner thread!"; - exit(1); + clean_quit(1); } } if (stopping or Global::resized) return; @@ -623,7 +623,7 @@ namespace Runner { if (ret != EBUSY and not Global::quitting) { if (active) active = false; Global::exit_error_msg = "Runner thread died unexpectedly!"; - exit(1); + clean_quit(1); } else if (ret == EBUSY) { atomic_wait_for(active, true, 5000); @@ -634,7 +634,7 @@ namespace Runner { } else { Global::exit_error_msg = "No response from Runner thread, quitting!"; - exit(1); + clean_quit(1); } } thread_trigger(); @@ -829,7 +829,7 @@ int main(int argc, char **argv) { Runner::thread_sem_init(); if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) { Global::exit_error_msg = "Failed to create _runner thread!"; - exit(1); + clean_quit(1); } else { Global::_runner_started = true; @@ -866,8 +866,8 @@ int main(int argc, char **argv) { try { while (not true not_eq not false) { //? Check for exceptions in secondary thread and exit with fail signal if true - if (Global::thread_exception) exit(1); - else if (Global::should_quit) exit(0); + if (Global::thread_exception) clean_quit(1); + else if (Global::should_quit) clean_quit(0); else if (Global::should_sleep) { Global::should_sleep = false; _sleep(); } //? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly) @@ -923,7 +923,7 @@ int main(int argc, char **argv) { } catch (const std::exception& e) { Global::exit_error_msg = "Exception in main loop -> " + (string)e.what(); - exit(1); + clean_quit(1); } } From 044927b7e5161ba40bfd4e1943e89f4fe49b5c7c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 14 Nov 2021 01:30:27 +0100 Subject: [PATCH 125/289] Fixed broken links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c668a00..56e0575 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ * [Prerequisites](#prerequisites) (Read this if you are having issues!) * [Screenshots](#screenshots) * [Keybindings](#help-menu) -* [Installation Linux/OSX](#installation-linux/osx) +* [Installation Linux/OSX](#installation) * [Compilation Linux](#compilation-osx) * [Compilation OSX](#compilation-osx) * [Installing the snap](#installing-the-snap) @@ -215,7 +215,7 @@ Also needs a UTF8 locale and a font that covers: ![Screenshot 5](Img/help-menu.png) -## Installation Linux/OSX +## Installation **Binaries for Linux are statically compiled with musl and works on kernel 2.6.39 and newer** From d721c4b13582cc32130ba9b127f9456bd6a9e781 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 15 Nov 2021 21:58:09 +0100 Subject: [PATCH 126/289] Fixed link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56e0575..18eb725 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ * [Screenshots](#screenshots) * [Keybindings](#help-menu) * [Installation Linux/OSX](#installation) -* [Compilation Linux](#compilation-osx) +* [Compilation Linux](#compilation-linux) * [Compilation OSX](#compilation-osx) * [Installing the snap](#installing-the-snap) * [Configurability](#configurability) From cb6ad141eb0523201ef27a5ea5dbf27ec5b5eb53 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 16 Nov 2021 07:16:55 +0100 Subject: [PATCH 127/289] Added support for partial static linking on OSX --- Makefile | 5 ++++- README.md | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 396b474..c207094 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,10 @@ ifneq ($(PLATFORM) $(ARCH),macos arm64) endif ifeq ($(STATIC),true) - override ADDFLAGS += -DSTATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings + override ADDFLAGS += -static-libgcc -static-libstdc++ + ifneq ($(PLATFORM),macos) + override ADDFLAGS += -DSTATIC_BUILD -static -Wl,--fatal-warnings + endif endif ifeq ($(STRIP),true) diff --git a/README.md b/README.md index 18eb725..c0f8ec8 100644 --- a/README.md +++ b/README.md @@ -390,6 +390,8 @@ Also needs a UTF8 locale and a font that covers: 3. **Compile** + Append `STATIC=true` to `make` command for static compilation (only libgcc and libstdc++ will be static!). + Append `QUIET=true` for less verbose output. Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). From 7373d24905cd211aa42e842cc7afd24a71e0a76c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 16 Nov 2021 07:34:09 +0100 Subject: [PATCH 128/289] Continuous build macos switch to BigSur Also added static linking with libgcc and libstdc++ --- .github/workflows/continuous-build-macos.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous-build-macos.yml b/.github/workflows/continuous-build-macos.yml index 04bf471..2cb5e4a 100644 --- a/.github/workflows/continuous-build-macos.yml +++ b/.github/workflows/continuous-build-macos.yml @@ -17,18 +17,18 @@ on: jobs: build-osx: - runs-on: macos-latest + runs-on: macos-11 steps: - uses: actions/checkout@v2 - name: Compile run: | - make CXX=g++-11 ARCH=x86_64 + make CXX=g++-11 ARCH=x86_64 STATIC=true STRIP=true GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop bin/btop-x86_64-$GIT_HASH + mv bin/btop bin/btop-x86_64-BigSur-$GIT_HASH ls -alh bin - uses: actions/upload-artifact@v2 with: - name: btop-x86_64-macos + name: btop-x86_64-macos-BigSur path: 'bin/*' From 19894feec70bc3173f8dc10159dfc44cff4e8757 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 16 Nov 2021 07:58:42 +0100 Subject: [PATCH 129/289] bug_report added instruction for lldb --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index de86eaf..faa7b5e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -46,10 +46,10 @@ If btop++ is crashing at start the following steps could be helpful: (Extra helpful if compiled with `make OPTFLAGS="-O0 -g"`) -1. run `gdb btop` +1. run (linux): `gdb btop` (macos): `lldb btop` -2. `r` to run, wait for crash and press enter +2. `r` to run, wait for crash and press enter if prompted, CTRL+L to clear screen if needed. -3. `thread apply all bt` to get backtrace for all threads +3. (gdb): `thread apply all bt` (lldb): `bt all` to get backtrace for all threads 4. Copy and paste the backtrace here: From 557bcf56c953c3aaa3fa788295ff19cf5a68a4d3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 16 Nov 2021 08:41:16 +0100 Subject: [PATCH 130/289] v1.1.1 OSX build fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2a77d3..7d2be4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.1.1 + +* Added: Partial static build (libgcc, libstdc++) for macos + +* Changed: Continuous build macos switched to OSX 11.6 (Big Sur) and partial static build + +* Changed: Release binaries for macos switched to OSX 12 (Monterey) and partial static build + ## v1.1.0 * Added: Support for OSX, by @joske and @aristocratos diff --git a/src/btop.cpp b/src/btop.cpp index 88c3403..dc5fc98 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.1.0"; + const string Version = "1.1.1"; int coreCount; string overlay; From 6ab49d28030908d64097943a5ececdc02aec8e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Gradowski?= Date: Tue, 16 Nov 2021 20:40:49 +0100 Subject: [PATCH 131/289] fix SISEGV on Mojave --- src/osx/sensors.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/osx/sensors.cpp b/src/osx/sensors.cpp index bd6312e..56aca68 100644 --- a/src/osx/sensors.cpp +++ b/src/osx/sensors.cpp @@ -37,7 +37,8 @@ CFDictionaryRef matching(int page, int usage) { nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage); CFDictionaryRef dict = CFDictionaryCreate(0, (const void **)keys, (const void **)nums, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(keys); + CFRelease(keys[0]); + CFRelease(keys[1]); return dict; } From 5fb484a299bad6f1fd9c0a7a5de37aa05360f685 Mon Sep 17 00:00:00 2001 From: Krzysztof Filipek Date: Wed, 17 Nov 2021 00:08:05 +0100 Subject: [PATCH 132/289] Fix coretemp iteration due to missing temp9_input (i9-9940X) There are cases when some files are missing: 1. Due to specific CPU topology (e.g. {cpu6: core_id=6; but cpu7: core_id=8}) 2. On architectures older than SandyBridge (missing per-package sensor) --- src/linux/btop_collect.cpp | 46 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 7e34de7..9fab773 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -240,20 +240,36 @@ namespace Cpu { if (s_contains(add_path, "coretemp")) got_coretemp = true; - if (fs::exists(add_path / "temp1_input")) { - search_paths.push_back(add_path); + for (const auto & file : fs::directory_iterator(add_path)) { + if (string(file.path().filename()) == "device") { + for (const auto & dev_file : fs::directory_iterator(file.path())) { + string dev_filename = dev_file.path().filename(); + if (dev_filename.starts_with("temp") and dev_filename.ends_with("_input")) { + search_paths.push_back(file.path()); + break; + } + } + } + + string filename = file.path().filename(); + if (filename.starts_with("temp") and filename.ends_with("_input")) { + search_paths.push_back(add_path); + break; + } } - else if (fs::exists(add_path / "device/temp1_input")) - search_paths.push_back(add_path / "device"); } } if (not got_coretemp and fs::exists(fs::path("/sys/devices/platform/coretemp.0/hwmon"))) { for (auto& d : fs::directory_iterator(fs::path("/sys/devices/platform/coretemp.0/hwmon"))) { fs::path add_path = fs::canonical(d.path()); - if (fs::exists(d.path() / "temp1_input") and not v_contains(search_paths, add_path)) { - search_paths.push_back(add_path); - got_coretemp = true; + for (const auto & file : fs::directory_iterator(add_path)) { + string filename = file.path().filename(); + if (filename.starts_with("temp") and filename.ends_with("_input") and not v_contains(search_paths, add_path)) { + search_paths.push_back(add_path); + got_coretemp = true; + break; + } } } } @@ -261,9 +277,17 @@ namespace Cpu { if (not search_paths.empty()) { for (const auto& path : search_paths) { const string pname = readfile(path / "name", path.filename()); - for (int i = 1; fs::exists(path / string("temp" + to_string(i) + "_input")); i++) { - const string basepath = path / string("temp" + to_string(i) + "_"); - const string label = readfile(fs::path(basepath + "label"), "temp" + to_string(i)); + for (const auto & file : fs::directory_iterator(path)) { + const string file_suffix = "input"; + const int file_id = atoi(file.path().filename().c_str() + 4); // skip "temp" prefix + string file_path = file.path(); + + if (!s_contains(file_path, file_suffix)) { + continue; + } + + const string basepath = file_path.erase(file_path.find(file_suffix), file_suffix.length()); + const string label = readfile(fs::path(basepath + "label"), "temp" + to_string(file_id)); const string sensor_name = pname + "/" + label; const int64_t temp = stol(readfile(fs::path(basepath + "input"), "0")) / 1000; const int64_t high = stol(readfile(fs::path(basepath + "max"), "80000")) / 1000; @@ -1707,4 +1731,4 @@ namespace Tools { } throw std::runtime_error("Failed get uptime from from " + (string)Shared::procPath + "/uptime"); } -} \ No newline at end of file +} From e1074cd15b713016857ae375adf1d62cf731a7d2 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 22 Nov 2021 21:43:40 +0100 Subject: [PATCH 133/289] Mem::collect optimization --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 7e34de7..085fd9f 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -730,7 +730,7 @@ namespace Mem { ifstream meminfo(Shared::procPath / "meminfo"); if (meminfo.good()) { bool got_avail = false; - for (string label; meminfo >> label;) { + for (string label; meminfo.peek() != 'D' and meminfo >> label;) { if (label == "MemFree:") { meminfo >> mem.stats.at("free"); mem.stats.at("free") <<= 10; From 953216f614bb3a2afea0105521253720fbdf8a95 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 24 Nov 2021 21:58:21 +0100 Subject: [PATCH 134/289] Disabled unused mouse_released event --- src/btop_input.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index d7b8ece..cf7b934 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -105,14 +105,14 @@ namespace Input { if (key.starts_with("[<")) { std::string_view key_view = key; string mouse_event; - if (key_view.starts_with("[<0;") and key_view.ends_with('M')) { + if (key_view.starts_with("[<0;") and key_view.find('M') != std::string_view::npos) { mouse_event = "mouse_click"; key_view.remove_prefix(4); } - else if (key_view.starts_with("[<0;") and key_view.ends_with('m')) { - mouse_event = "mouse_release"; - key_view.remove_prefix(4); - } + // else if (key_view.starts_with("[<0;") and key_view.ends_with('m')) { + // mouse_event = "mouse_release"; + // key_view.remove_prefix(4); + // } else if (key_view.starts_with("[<64;")) { mouse_event = "mouse_scroll_up"; key_view.remove_prefix(5); From 538ec20b90bbc1137b17f30acaadea5df5550cf3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 27 Nov 2021 16:22:37 +0100 Subject: [PATCH 135/289] Fixed: Wrong unit for net_upload and net_download in config menu --- src/btop_menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index c3af6d6..ef159a4 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -486,13 +486,13 @@ namespace Menu { {"net_download", "Fixed network graph download value.", "", - "Value in Mebibytes, default \"100\".", + "Value in Mebibits, default \"100\".", "", "Can be toggled with auto button."}, {"net_upload", "Fixed network graph upload value.", "", - "Value in Mebibytes, default \"100\".", + "Value in Mebibits, default \"100\".", "", "Can be toggled with auto button."}, {"net_auto", From 297cb696b34617e2e23cc70747a340fe2d3264e9 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 27 Nov 2021 17:38:29 +0100 Subject: [PATCH 136/289] Fixed: UTF-8 detection on macos --- src/btop.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/btop.cpp b/src/btop.cpp index dc5fc98..f015308 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -28,6 +28,9 @@ tab-size = 4 #include #include #include +#ifdef __APPLE__ + #include +#endif #include #include @@ -764,12 +767,34 @@ int main(int argc, char **argv) { } } + #ifdef __APPLE__ + if (found.empty()) { + CFLocaleRef cflocale = CFLocaleCopyCurrent(); + CFStringRef id_value = (CFStringRef)CFLocaleGetValue(cflocale, kCFLocaleIdentifier); + auto loc_id = CFStringGetCStringPtr(id_value, kCFStringEncodingUTF8); + CFRelease(cflocale); + std::string cur_locale = (loc_id != nullptr ? loc_id : ""); + if (cur_locale.empty()) { + Logger::warning("No UTF-8 locale detected! Some symbols might not display correctly."); + } + else if (std::setlocale(LC_ALL, string(cur_locale + ".UTF-8").c_str()) != NULL) { + Logger::debug("Setting LC_ALL=" + cur_locale + ".UTF-8"); + } + else if(std::setlocale(LC_ALL, "en_US.UTF-8") != NULL) { + Logger::debug("Setting LC_ALL=en_US.UTF-8"); + } + else { + Logger::warning("Failed to set macos locale, continuing anyway."); + } + } + #else if (found.empty() and Global::utf_force) Logger::warning("No UTF-8 locale detected! Forcing start with --utf-force argument."); else if (found.empty()) { Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it."; clean_quit(1); } + #endif else if (not set_failure) Logger::debug("Setting LC_ALL=" + found); } From 50928fc1e15b65ad5d75a9bacedafd5fb69c9263 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 27 Nov 2021 17:59:46 +0100 Subject: [PATCH 137/289] Enabled more verbosity and disabled currently failing builds --- .github/workflows/continuous-build-linux.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/continuous-build-linux.yml b/.github/workflows/continuous-build-linux.yml index 38f3f2c..846aee8 100644 --- a/.github/workflows/continuous-build-linux.yml +++ b/.github/workflows/continuous-build-linux.yml @@ -52,7 +52,6 @@ jobs: - mipsel-linux-musln32 - mipsel-linux-musln32sf - mipsel-linux-muslsf - - or1k-linux-musl - powerpc-linux-musl - powerpc-linux-muslsf - powerpc64-linux-musl @@ -62,15 +61,17 @@ jobs: - riscv32-linux-musl - riscv64-linux-musl - s390x-linux-musl - - sh2-linux-musl - - sh2-linux-muslfdpic - - sh2eb-linux-musl - - sh2eb-linux-muslfdpic - - sh4-linux-musl - - sh4eb-linux-musl - x86_64-linux-musl - x86_64-linux-muslx32 + # - or1k-linux-musl + # - sh2-linux-musl + # - sh2-linux-muslfdpic + # - sh2eb-linux-musl + # - sh2eb-linux-muslfdpic + # - sh4-linux-musl + # - sh4eb-linux-musl + runs-on: ubuntu-latest container: muslcc/x86_64:${{ matrix.toolchain }} @@ -85,7 +86,7 @@ jobs: run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] - name: Build - run: make STATIC=true STRIP=true QUIET=true + run: make STATIC=true STRIP=true - name: Make executable run: chmod +x bin/* From 9465e9b01439b6c3c941c89ab062461a595292ed Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 27 Nov 2021 18:24:40 +0100 Subject: [PATCH 138/289] Fixed: coretemp ordering --- src/linux/btop_collect.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 468fd6d..bf869df 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -333,7 +333,16 @@ namespace Cpu { } catch (...) {} - if (not got_coretemp or core_sensors.empty()) cpu_temp_only = true; + if (not got_coretemp or core_sensors.empty()) { + cpu_temp_only = true; + } + else { + rng::sort(core_sensors, rng::less{}); + rng::stable_sort(core_sensors, [](const auto& a, const auto& b){ + return a.size() < b.size(); + }); + } + if (cpu_sensor.empty() and not found_sensors.empty()) { for (const auto& [name, sensor] : found_sensors) { if (s_contains(str_to_lower(name), "cpu") or s_contains(str_to_lower(name), "k10temp")) { From 48cbe688c5672572049c1064f8429735b27ffd30 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 27 Nov 2021 18:52:10 +0100 Subject: [PATCH 139/289] v1.1.2 Bug fixes --- CHANGELOG.md | 14 ++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d2be4a..99f2a4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.1.2 + +* Fixed: SISEGV on macos Mojave, by @mgradowski + +* Fixed: Small optimizations and fixes to Mem::collect() and Input::get() + +* Fixed: Wrong unit for net_upload and net_download in config menu + +* Fixed: UTF-8 detection on macos + +* Fixed: coretemp iteration due to missing tempX_input, by @KFilipek + +* Fixed: coretemp ordering + ## v1.1.1 * Added: Partial static build (libgcc, libstdc++) for macos diff --git a/src/btop.cpp b/src/btop.cpp index f015308..a07a8c5 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -56,7 +56,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.1.1"; + const string Version = "1.1.2"; int coreCount; string overlay; From 7f7795d674f2bf5f1d9d82d5b4b3c68b74b2b674 Mon Sep 17 00:00:00 2001 From: Nguyen Thanh Quang <57827456+AlphaNecron@users.noreply.github.com> Date: Wed, 1 Dec 2021 13:09:30 +0700 Subject: [PATCH 140/289] Added `ayu` --- themes/ayu.theme | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 themes/ayu.theme diff --git a/themes/ayu.theme b/themes/ayu.theme new file mode 100644 index 0000000..58d89b4 --- /dev/null +++ b/themes/ayu.theme @@ -0,0 +1,89 @@ +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#0B0E14" + +# Main text color +theme[main_fg]="#BFBDB6" + +# Title color for boxes +theme[title]="#BFBDB6" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#E6B450" + +# Background color of selected item in processes box +theme[selected_bg]="#E6B450" + +# Foreground color of selected item in processes box +theme[selected_fg]="#f8f8f2" + +# Color of inactive/disabled text +theme[inactive_fg]="#565B66" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#BFBDB6" + +# Background color of the percentage meters +theme[meter_bg]="#565B66" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#DFBFFF" + +# Cpu box outline color +theme[cpu_box]="#DFBFFF" + +# Memory/disks box outline color +theme[mem_box]="#95E6CB" + +# Net up/down box outline color +theme[net_box]="#F28779" + +# Processes box outline color +theme[proc_box]="#E6B673" + +# Box divider line and small boxes line color +theme[div_line]="#565B66" + +# Temperature graph colors +theme[temp_start]="#DFBFFF" +theme[temp_mid]="#D2A6FF" +theme[temp_end]="#A37ACC" + +# CPU graph colors +theme[cpu_start]="#DFBFFF" +theme[cpu_mid]="#D2A6FF" +theme[cpu_end]="#A37ACC" + +# Mem/Disk free meter +theme[free_start]="#95E6CB" +theme[free_mid]="#95E6CB" +theme[free_end]="#4CBF99" + +# Mem/Disk cached meter +theme[cached_start]="#95E6CB" +theme[cached_mid]="#95E6CB" +theme[cached_end]="#4CBF99" + +# Mem/Disk available meter +theme[available_start]="#95E6CB" +theme[available_mid]="#95E6CB" +theme[available_end]="#4CBF99" + +# Mem/Disk used meter +theme[used_start]="#95E6CB" +theme[used_mid]="#95E6CB" +theme[used_end]="#4CBF99" + +# Download graph colors +theme[download_start]="#F28779" +theme[download_mid]="#F07178" +theme[download_end]="#F07171" + +# Upload graph colors +theme[upload_start]="#73D0FF" +theme[upload_mid]="#59C2FF" +theme[upload_end]="#399EE6" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#FFCC66" +theme[process_mid]="#E6B450" +theme[process_end]="#FFAA33" From 7bee0016e477116768b1c51955ae76db94ceb969 Mon Sep 17 00:00:00 2001 From: Dzmitry Neviadomski Date: Thu, 2 Dec 2021 01:29:58 +0300 Subject: [PATCH 141/289] [macOS] Add Homebrew installation instructions. --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index c0f8ec8..dcff5e6 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,13 @@ Also needs a UTF8 locale and a font that covers: sudo zypper in btop ``` +**Binary release on macOS** + +* **[Homebrew](https://formulae.brew.sh/formula/btop)** + ```bash + brew install btop + ``` + ## Compilation Linux Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary). From 5aef22cfa17d63d2edc87a1807d48883861e9db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pietryszak?= <45850093+pietryszak@users.noreply.github.com> Date: Thu, 2 Dec 2021 01:56:14 +0100 Subject: [PATCH 142/289] Create gruvbox_dark_v2.theme I create a theme with colors used only from original scheme https://github.com/morhetz/gruvbox and with 3 colorsh gradient. --- themes/gruvbox_dark_v2.theme | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 themes/gruvbox_dark_v2.theme diff --git a/themes/gruvbox_dark_v2.theme b/themes/gruvbox_dark_v2.theme new file mode 100644 index 0000000..a3a0c9e --- /dev/null +++ b/themes/gruvbox_dark_v2.theme @@ -0,0 +1,98 @@ +# Bashtop gruvbox (https://github.com/morhetz/gruvbox) theme +# First version created By BachoSeven +# Adjustments to proper colors by Pietryszak (https://github.com/pietryszak/) + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#FFFFFF", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#282828" + +# Main text color +theme[main_fg]="#EBDBB2" + +# Title color for boxes +theme[title]="#EBDBB2" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#CC241D" + +# Background color of selected items +theme[selected_bg]="#32302F" + +# Foreground color of selected items +theme[selected_fg]="#D3869B" + +# Color of inactive/disabled text +theme[inactive_fg]="#3C3836" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#A89984" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#98971A" + +# Cpu box outline color +theme[cpu_box]="#A89984" + +# Memory/disks box outline color +theme[mem_box]="#A89984" + +# Net up/down box outline color +theme[net_box]="#A89984" + +# Processes box outline color +theme[proc_box]="#A89984" + +# Box divider line and small boxes line color +theme[div_line]="#A89984" + +# Temperature graph colors +theme[temp_start]="#98971A" +theme[temp_mid]="" +theme[temp_end]="#CC241D" + +# CPU graph colors +theme[cpu_start]="#8EC07C" +theme[cpu_mid]="#D79921" +theme[cpu_end]="#CC241D" + +# Mem/Disk free meter +theme[free_start]="#CC241D" +theme[free_mid]="#D79921" +theme[free_end]="#8EC07C" + +# Mem/Disk cached meter +theme[cached_start]="#458588" +theme[cached_mid]="#83A598" +theme[cached_end]="#8EC07C" + +# Mem/Disk available meter +theme[available_start]="#CC241D" +theme[available_mid]="#D65D0E" +theme[available_end]="#FABD2F" + +# Mem/Disk used meter +theme[used_start]="#8EC07C" +theme[used_mid]="#D65D0E" +theme[used_end]="#CC241D" + +# Download graph colors +theme[download_start]="#98971A" +theme[download_mid]="#689d6A" +theme[download_end]="#B8BB26" + +# Upload graph colors +theme[upload_start]="#CC241D" +theme[upload_mid]="#D65d0E" +theme[upload_end]="#FABF2F" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#8EC07C" +theme[process_mid]="#FE8019" +theme[process_end]="#CC241D" From 1997c7a751f2a84a40f6e4be1a8995c7755ebc26 Mon Sep 17 00:00:00 2001 From: Dzmitry Neviadomski Date: Thu, 2 Dec 2021 14:54:49 +0300 Subject: [PATCH 143/289] Update README.md Co-authored-by: Xuehai Pan --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dcff5e6..f52c2a3 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,7 @@ Also needs a UTF8 locale and a font that covers: sudo zypper in btop ``` -**Binary release on macOS** +**Binary release on Homebrew (macOS (x86_64 & ARM64) / Linux (x86_64))** * **[Homebrew](https://formulae.brew.sh/formula/btop)** ```bash From bcc0acf9f2905d7e2cad3b6d6469e16dbfbdd161 Mon Sep 17 00:00:00 2001 From: Jos Dehaes Date: Sun, 28 Nov 2021 21:50:49 +0100 Subject: [PATCH 144/289] #168 - try again with TC0C smc key --- src/osx/smc.cpp | 5 +++++ src/osx/smc.hpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/osx/smc.cpp b/src/osx/smc.cpp index 2482ae3..7386dbf 100644 --- a/src/osx/smc.cpp +++ b/src/osx/smc.cpp @@ -63,6 +63,11 @@ namespace Cpu { snprintf(key, 5, "TC%1dc", core); } result = SMCReadKey(key, &val); + if (result != kIOReturnSuccess) { + // try again with C + snprintf(key, 5, "TC%1dC", core); + result = SMCReadKey(key, &val); + } if (result == kIOReturnSuccess) { if (strcmp(val.dataType, DATATYPE_SP78) == 0) { // convert sp78 value to temperature diff --git a/src/osx/smc.hpp b/src/osx/smc.hpp index 0aa02c1..6d65c9c 100644 --- a/src/osx/smc.hpp +++ b/src/osx/smc.hpp @@ -25,7 +25,8 @@ #define DATATYPE_SP78 "sp78" // key values -#define SMC_KEY_CPU_TEMP "TC0P" +#define SMC_KEY_CPU_TEMP "TC0P" // proximity temp? +#define SMC_KEY_CPU_DIE_TEMP "TC0D" // die temp? #define SMC_KEY_CPU1_TEMP "TC1C" #define SMC_KEY_CPU2_TEMP "TC2C" // etc #define SMC_KEY_FAN0_RPM_CUR "F0Ac" From b015aa6ae18b42b806372adc4a85a0123c9220c2 Mon Sep 17 00:00:00 2001 From: vtmx Date: Tue, 7 Dec 2021 18:35:32 -0300 Subject: [PATCH 145/289] Added theme OneDark --- themes/onedark.theme | 81 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 themes/onedark.theme diff --git a/themes/onedark.theme b/themes/onedark.theme new file mode 100644 index 0000000..f4441de --- /dev/null +++ b/themes/onedark.theme @@ -0,0 +1,81 @@ +# Theme: OneDark +# By: Vitor Melo + +# Main bg +theme[main_bg]="#282c34" + +# Main text color +theme[main_fg]="#abb2bf" + +# Title color for boxes +theme[title]="#abb2bf" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#61afef" + +# Background color of selected item in processes box +theme[selected_bg]="#2c313c" + +# Foreground color of selected item in processes box +theme[selected_fg]="#abb2bf" + +# Color of inactive/disabled text +theme[inactive_fg]="#5c6370" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#61afef" + +# Cpu box outline color +theme[cpu_box]="#5c6370" + +# Memory/disks box outline color +theme[mem_box]="#5c6370" + +# Net up/down box outline color +theme[net_box]="#5c6370" + +# Processes box outline color +theme[proc_box]="#5c6370" + +# Box divider line and small boxes line color +theme[div_line]="#5c6370" + +# Temperature graph colors +theme[temp_start]="#98c379" +theme[temp_mid]="#e5c07b" +theme[temp_end]="#e06c75" + +# CPU graph colors +theme[cpu_start]="#98c379" +theme[cpu_mid]="#e5c07b" +theme[cpu_end]="#e06c75" + +# Mem/Disk free meter +theme[free_start]="#98c379" +theme[free_mid]="#e5c07b" +theme[free_end]="#e06c75" + +# Mem/Disk cached meter +theme[cached_start]="#98c379" +theme[cached_mid]="#e5c07b" +theme[cached_end]="#e06c75" + +# Mem/Disk available meter +theme[available_start]="#98c379" +theme[available_mid]="#e5c07b" +theme[available_end]="#e06c75" + +# Mem/Disk used meter +theme[used_start]="#98c379" +theme[used_mid]="#e5c07b" +theme[used_end]="#e06c75" + +# Download graph colors +theme[download_start]="#98c379" +theme[download_mid]="#e5c07b" +theme[download_end]="#e06c75" + +# Upload graph colors +theme[upload_start]="#98c379" +theme[upload_mid]="#e5c07b" +theme[upload_end]="#e06c75" From 609dfccadd1318490a08485153f17798f5c0b11b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 9 Dec 2021 07:10:56 +0100 Subject: [PATCH 146/289] Fixed: Fixed network graph scale int rollover --- src/btop_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index bc64dc9..a309834 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -947,8 +947,8 @@ namespace Net { const string title_left = Theme::c("net_box") + Fx::ub + Symbols::title_left; const string title_right = Theme::c("net_box") + Fx::ub + Symbols::title_right; const int i_size = min((int)selected_iface.size(), 10); - const long long down_max = (net_auto ? graph_max.at("download") : (long long)(Config::getI("net_download") << 20) / 8); - const long long up_max = (net_auto ? graph_max.at("upload") : (long long)(Config::getI("net_upload") << 20) / 8); + const long long down_max = (net_auto ? graph_max.at("download") : ((long long)(Config::getI("net_download")) << 20) / 8); + const long long up_max = (net_auto ? graph_max.at("upload") : ((long long)(Config::getI("net_upload")) << 20) / 8); //* Redraw elements not needed to be updated every cycle if (redraw) { From 13a29c39e15284844ea4baf723d08cbb4eafa32c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 11 Dec 2021 01:06:27 +0100 Subject: [PATCH 147/289] Fixed: Suspected possibility of very rare stall in Input::clear() --- src/btop_input.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index cf7b934..0fe5b9d 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -175,10 +175,11 @@ namespace Input { } void clear() { - auto first_num = cin.rdbuf()->in_avail(); - while (cin.rdbuf()->in_avail() == first_num) { - if (first_num-- == 0) break; - cin.ignore(1); + if (auto first_num = cin.rdbuf()->in_avail(); first_num > 0) { + while (cin.rdbuf()->in_avail() == first_num) { + if (first_num-- <= 0) break; + cin.ignore(1); + } } } From a6d27c1cc4f5079b46df48134459746bacb7d429 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 11 Dec 2021 18:22:08 +0100 Subject: [PATCH 148/289] v1.1.3 New themes + bugfixes --- CHANGELOG.md | 14 ++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f2a4f..0ec004f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.1.3 + +* Added: New theme ayu, by @AlphaNecron + +* Added: New theme gruvbox_dark_v2, by @pietryszak + +* Fixed: Macos cpu coretemp for Intel, by @joske + +* Added: New theme OneDark, by @vtmx + +* Fixed: Fixed network graph scale int rollover + +* Fixed: Suspected possibility of very rare stall in Input::clear() + ## v1.1.2 * Fixed: SISEGV on macos Mojave, by @mgradowski diff --git a/src/btop.cpp b/src/btop.cpp index a07a8c5..06dc42f 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -56,7 +56,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.1.2"; + const string Version = "1.1.3"; int coreCount; string overlay; From de27c581c52bf80bd4aca0722271a1caa30f52fd Mon Sep 17 00:00:00 2001 From: Marius Gripsgard Date: Mon, 13 Dec 2021 13:45:22 +0100 Subject: [PATCH 149/289] Fix spelling mistakes caught by debian lintian --- README.md | 4 ++-- src/btop_config.cpp | 6 +++--- src/btop_config.hpp | 2 +- src/btop_menu.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f52c2a3..7450962 100644 --- a/README.md +++ b/README.md @@ -507,8 +507,8 @@ truecolor = True force_tty = False #* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. -#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positons, G=graph symbol to use for box. -#* Use withespace " " as seprator between different presets. +#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box. +#* Use withespace " " as separator between different presets. #* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 66069d7..c9a5a42 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -50,8 +50,8 @@ namespace Config { "#* Will force 16-color mode and TTY theme, set all graph symbols to \"tty\" and swap out other non tty friendly symbols."}, {"presets", "#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.\n" - "#* Format: \"box_name:P:G,box_name:P:G\" P=(0 or 1) for alternate positons, G=graph symbol to use for box.\n" - "#* Use withespace \" \" as seprator between different presets.\n" + "#* Format: \"box_name:P:G,box_name:P:G\" P=(0 or 1) for alternate positions, G=graph symbol to use for box.\n" + "#* Use withespace \" \" as separator between different presets.\n" "#* Example: \"cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty\""}, {"vim_keys", "#* Set to True to enable \"h,j,k,l\" keys for directional control in lists.\n" @@ -603,4 +603,4 @@ namespace Config { } } } -} \ No newline at end of file +} diff --git a/src/btop_config.hpp b/src/btop_config.hpp index b99e26f..9d2f63c 100644 --- a/src/btop_config.hpp +++ b/src/btop_config.hpp @@ -48,7 +48,7 @@ namespace Config { extern vector available_batteries; extern int current_preset; - //* Check if string only contains space seperated valid names for boxes + //* Check if string only contains space separated valid names for boxes bool check_boxes(const string& boxes); //* Toggle box and update config string shown_boxes diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index ef159a4..c526521 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -194,10 +194,10 @@ namespace Menu { "Max 9 presets.", "", "Format: \"box_name:P:G,box_name:P:G\"", - "P=(0 or 1) for alternate positons.", + "P=(0 or 1) for alternate positions.", "G=graph symbol to use for box.", "", - "Use withespace \" \" as seprator between", + "Use withespace \" \" as separator between", "different presets.", "", "Example:", @@ -206,7 +206,7 @@ namespace Menu { "Manually set which boxes to show.", "", "Available values are \"cpu mem net proc\".", - "Seperate values with whitespace.", + "Separate values with whitespace.", "", "Toggle between presets with key \"p\"."}, {"update_ms", @@ -435,7 +435,7 @@ namespace Menu { "equals 100 percent in the io graphs.", "(100 MiB/s by default).", "", - "Format: \"device:speed\" seperate disks with", + "Format: \"device:speed\" separate disks with", "whitespace \" \".", "", "Example: \"/dev/sda:100, /dev/sdb:20\"."}, From 7a1c88adc40351f81418b6882aca2cb0d475b2c4 Mon Sep 17 00:00:00 2001 From: Marius Gripsgard Date: Mon, 13 Dec 2021 13:58:44 +0100 Subject: [PATCH 150/289] Fix some missing copyright in src files found by debian lintian --- src/osx/btop_collect.cpp | 1 + src/osx/sensors.cpp | 18 ++++++++++++++++++ src/osx/sensors.hpp | 17 +++++++++++++++++ src/osx/smc.cpp | 18 ++++++++++++++++++ src/osx/smc.hpp | 18 ++++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index f976a55..a9e4858 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -15,6 +15,7 @@ indent = tab tab-size = 4 */ + #include #include #include diff --git a/src/osx/sensors.cpp b/src/osx/sensors.cpp index 56aca68..e1f5f0e 100644 --- a/src/osx/sensors.cpp +++ b/src/osx/sensors.cpp @@ -1,3 +1,21 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ + #include "sensors.hpp" #include diff --git a/src/osx/sensors.hpp b/src/osx/sensors.hpp index 48287ee..698fca6 100644 --- a/src/osx/sensors.hpp +++ b/src/osx/sensors.hpp @@ -1,3 +1,20 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ namespace Cpu { class ThermalSensors { diff --git a/src/osx/smc.cpp b/src/osx/smc.cpp index 7386dbf..8ec6cf8 100644 --- a/src/osx/smc.cpp +++ b/src/osx/smc.cpp @@ -1,3 +1,21 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ + #include "smc.hpp" static UInt32 _strtoul(char *str, int size, int base) { diff --git a/src/osx/smc.hpp b/src/osx/smc.hpp index 6d65c9c..edd3551 100644 --- a/src/osx/smc.hpp +++ b/src/osx/smc.hpp @@ -1,3 +1,21 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ + #pragma once #include From 0e2517ae1129b2870e8bc9bcdeb519c3d4bd3de7 Mon Sep 17 00:00:00 2001 From: stwnt Date: Sun, 19 Dec 2021 23:53:01 +0100 Subject: [PATCH 151/289] Create dependency files in build directory when compiling. --- Makefile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c207094..4b2d0a0 100644 --- a/Makefile +++ b/Makefile @@ -223,12 +223,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) @sleep 0.3 2>/dev/null || true @TSTAMP=$$(date +%s 2>/dev/null || echo "0") @$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n" - @$(CXX) $(CXXFLAGS) $(INC) -c -o $@ $< || exit 1 - @$(CXX) $(CXXFLAGS) $(INC) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT) >/dev/null || exit 1 - @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp - @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) - @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) - @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + @$(CXX) $(CXXFLAGS) $(INC) -MMD -c -o $@ $< || exit 1 @printf "\033[1;92m-> \033[1;37m$@ \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" #? Non-File Targets From 96ac1149d15743d148c51714b496e389a71fe8f4 Mon Sep 17 00:00:00 2001 From: Jos Dehaes Date: Tue, 21 Dec 2021 23:15:02 +0100 Subject: [PATCH 152/289] fix CPU temp fallback on macOS --- src/osx/btop_collect.cpp | 28 ++++++++++++++++++++-------- src/osx/smc.cpp | 33 ++++++++++++++++++++------------- src/osx/smc.hpp | 4 +++- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index f976a55..ae4411a 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -68,6 +68,7 @@ namespace Cpu { cpu_info current_cpu; fs::path freq_path = "/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq"; bool got_sensors = false, cpu_temp_only = false; + int core_offset = 0; //* Populate found_sensors map bool get_sensors(); @@ -241,21 +242,34 @@ namespace Cpu { } bool get_sensors() { + Logger::debug("get_sensors(): show_coretemp=" + std::to_string(Config::getB("show_coretemp")) + " check_temp=" + std::to_string(Config::getB("check_temp"))); got_sensors = false; if (Config::getB("show_coretemp") and Config::getB("check_temp")) { ThermalSensors sensors; if (sensors.getSensors() > 0) { + Logger::debug("M1 sensors found"); got_sensors = true; cpu_temp_only = true; macM1 = true; } else { // try SMC (intel) + Logger::debug("checking intel"); SMCConnection smcCon; try { long long t = smcCon.getTemp(-1); // check if we have package T if (t > -1) { + Logger::debug("intel sensors found"); got_sensors = true; + t = smcCon.getTemp(0); + if (t == -1) { + // for some macs the core offset is 1 - check if we get a sane value with 1 + if (smcCon.getTemp(1) > -1) { + Logger::debug("intel sensors with offset 1"); + core_offset = 1; + } + } } else { + Logger::debug("no intel sensors found"); got_sensors = false; } } catch (std::runtime_error &e) { @@ -282,14 +296,12 @@ namespace Cpu { long long packageT = smcCon.getTemp(-1); // -1 returns package T current_cpu.temp.at(0).push_back(packageT); - if (Config::getB("show_coretemp") and not cpu_temp_only) { - for (int core = 0; core < Shared::coreCount; core++) { - long long temp = smcCon.getTemp(core / threadsPerCore); // same temp for all threads of same physical core - if (cmp_less(core + 1, current_cpu.temp.size())) { - current_cpu.temp.at(core + 1).push_back(temp); - if (current_cpu.temp.at(core + 1).size() > 20) - current_cpu.temp.at(core + 1).pop_front(); - } + for (int core = 0; core < Shared::coreCount; core++) { + long long temp = smcCon.getTemp((core / threadsPerCore) + core_offset); // same temp for all threads of same physical core + if (cmp_less(core + 1, current_cpu.temp.size())) { + current_cpu.temp.at(core + 1).push_back(temp); + if (current_cpu.temp.at(core + 1).size() > 20) + current_cpu.temp.at(core + 1).pop_front(); } } } diff --git a/src/osx/smc.cpp b/src/osx/smc.cpp index 7386dbf..54fa422 100644 --- a/src/osx/smc.cpp +++ b/src/osx/smc.cpp @@ -50,32 +50,39 @@ namespace Cpu { IOServiceClose(conn); } + long long SMCConnection::getSMCTemp(char *key) { + SMCVal_t val; + kern_return_t result; + result = SMCReadKey(key, &val); + if (result == kIOReturnSuccess) { + if (val.dataSize > 0) { + if (strcmp(val.dataType, DATATYPE_SP78) == 0) { + // convert sp78 value to temperature + int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1]; + return static_cast(intValue / 256.0); + } + } + } + return -1; + } + // core means physical core in SMC, while in core map it's cpu threads :-/ Only an issue on hackintosh? // this means we can only get the T per physical core // another issue with the SMC API is that the key is always 4 chars -> what with systems with more than 9 physical cores? // no Mac models with more than 18 threads are released, so no problem so far // according to VirtualSMC docs (hackintosh fake SMC) the enumeration follows with alphabetic chars - not implemented yet here (nor in VirtualSMC) long long SMCConnection::getTemp(int core) { - SMCVal_t val; - kern_return_t result; char key[] = SMC_KEY_CPU_TEMP; if (core >= 0) { snprintf(key, 5, "TC%1dc", core); } - result = SMCReadKey(key, &val); - if (result != kIOReturnSuccess) { + long long result = getSMCTemp(key); + if (result == -1) { // try again with C snprintf(key, 5, "TC%1dC", core); - result = SMCReadKey(key, &val); + result = getSMCTemp(key); } - if (result == kIOReturnSuccess) { - if (strcmp(val.dataType, DATATYPE_SP78) == 0) { - // convert sp78 value to temperature - int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1]; - return static_cast(intValue / 256.0); - } - } - return -1; + return result; } kern_return_t SMCConnection::SMCReadKey(UInt32Char_t key, SMCVal_t *val) { diff --git a/src/osx/smc.hpp b/src/osx/smc.hpp index 6d65c9c..87ed2ef 100644 --- a/src/osx/smc.hpp +++ b/src/osx/smc.hpp @@ -26,7 +26,8 @@ // key values #define SMC_KEY_CPU_TEMP "TC0P" // proximity temp? -#define SMC_KEY_CPU_DIE_TEMP "TC0D" // die temp? +#define SMC_KEY_CPU_DIODE_TEMP "TC0D" // diode temp? +#define SMC_KEY_CPU_DIE_TEMP "TC0F" // die temp? #define SMC_KEY_CPU1_TEMP "TC1C" #define SMC_KEY_CPU2_TEMP "TC2C" // etc #define SMC_KEY_FAN0_RPM_CUR "F0Ac" @@ -86,6 +87,7 @@ namespace Cpu { private: kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val); + long long getSMCTemp(char *key); kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure); io_connect_t conn; From 5453e82a955ba0791607329f77bf41ea31b33ec6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 27 Dec 2021 10:55:17 +0100 Subject: [PATCH 153/289] Changed: From rng::sort() to rng::stable_sort() for more stability --- src/linux/btop_collect.cpp | 36 +++++++++++++++++++++++------------- src/osx/btop_collect.cpp | 35 +++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index bf869df..5a71e11 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1631,17 +1631,29 @@ namespace Proc { //* Sort processes if (sorted_change or not no_update) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + if (reverse) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; + } + } else { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + } } - if (reverse) rng::reverse(current_procs); //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage if (not tree and not reverse and sorting == "cpu lazy") { @@ -1714,9 +1726,7 @@ namespace Proc { } //? Final sort based on tree index - rng::sort(current_procs, rng::less{}, &proc_info::tree_index); - if (reverse) rng::reverse(current_procs); - + rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); } numpids = (int)current_procs.size() - filter_found; diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index f976a55..33cc651 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -1306,17 +1306,29 @@ namespace Proc { //* Sort processes if (sorted_change or not no_update) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + if (reverse) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; + } + } else { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + } } - if (reverse) rng::reverse(current_procs); //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage if (not tree and not reverse and sorting == "cpu lazy") { @@ -1382,8 +1394,7 @@ namespace Proc { } //? Final sort based on tree index - rng::sort(current_procs, rng::less{}, &proc_info::tree_index); - if (reverse) rng::reverse(current_procs); + rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); } numpids = (int)current_procs.size() - filter_found; From 35dccb103886064a8880773eae21378980462d7a Mon Sep 17 00:00:00 2001 From: Anton Samokhvalov Date: Wed, 29 Dec 2021 13:29:43 +0300 Subject: [PATCH 154/289] in_avail() can always be zero, it is a optimization opportunity only --- src/btop.cpp | 9 +++--- src/btop_input.cpp | 71 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 06dc42f..ac49a7e 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -17,6 +17,7 @@ tab-size = 4 */ #include +#include #include #include #include @@ -237,14 +238,14 @@ void clean_quit(int sig) { } Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); + const auto excode = (sig != -1 ? sig : 0); + //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor #ifndef __APPLE__ - if (Tools::active_locks > 0) { - quick_exit((sig != -1 ? sig : 0)); - } + quick_exit(excode); #endif - if (sig != -1) exit(sig); + exit(excode); } //* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 0fe5b9d..85ba644 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -19,6 +19,8 @@ tab-size = 4 #include #include #include +#include +#include #include #include @@ -78,14 +80,66 @@ namespace Input { deque history(50, ""); string old_filter; + struct InputThr { + InputThr() : thr(run, this) { + } + + static void run(InputThr* that) { + that->runImpl(); + } + + void runImpl() { + char ch = 0; + + // TODO(pg83): read whole buffer + while (cin.get(ch)) { + std::lock_guard g(lock); + current.push_back(ch); + if (current.size() > 100) { + current.clear(); + } + } + } + + size_t avail() { + std::lock_guard g(lock); + + return current.size(); + } + + std::string get() { + std::string res; + + { + std::lock_guard g(lock); + + res.swap(current); + } + + return res; + } + + static InputThr& instance() { + // intentional memory leak, to simplify shutdown process + static InputThr* input = new InputThr(); + + return *input; + } + + std::string current; + // TODO(pg83): use std::conditional_variable instead of sleep + std::mutex lock; + std::thread thr; + }; + bool poll(int timeout) { - if (timeout < 1) return cin.rdbuf()->in_avail() > 0; + if (timeout < 1) return InputThr::instance().avail() > 0; while (timeout > 0) { if (interrupt) { interrupt = false; return false; } - if (cin.rdbuf()->in_avail() > 0) return true; + if (InputThr::instance().avail() > 0) return true; sleep_ms(timeout < 10 ? timeout : 10); timeout -= 10; } @@ -93,9 +147,7 @@ namespace Input { } string get() { - string key; - while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get(); - if (cin.rdbuf()->in_avail() > 0) clear(); + string key = InputThr::instance().get(); if (not key.empty()) { //? Remove escape code prefix if present if (key.substr(0, 2) == Fx::e) { @@ -168,19 +220,14 @@ namespace Input { } string wait() { - while (cin.rdbuf()->in_avail() < 1) { + while (InputThr::instance().avail() < 1) { sleep_ms(10); } return get(); } void clear() { - if (auto first_num = cin.rdbuf()->in_avail(); first_num > 0) { - while (cin.rdbuf()->in_avail() == first_num) { - if (first_num-- <= 0) break; - cin.ignore(1); - } - } + // do not need it, actually } void process(const string& key) { From fe66d52a38bbc65703482db4fcfca7300d6953d9 Mon Sep 17 00:00:00 2001 From: Anton Samokhvalov Date: Wed, 29 Dec 2021 15:23:37 +0300 Subject: [PATCH 155/289] no memory leak --- src/btop.cpp | 10 +++++----- src/btop_input.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index ac49a7e..48884ba 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -237,15 +237,15 @@ void clean_quit(int sig) { std::cerr << Global::fg_red << "ERROR: " << Global::fg_white << Global::exit_error_msg << Fx::reset << endl; } Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); - - const auto excode = (sig != -1 ? sig : 0); - + close(0); //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor #ifndef __APPLE__ - quick_exit(excode); + if (Tools::active_locks > 0) { + quick_exit((sig != -1 ? sig : 0)); + } #endif - exit(excode); + if (sig != -1) exit(sig); } //* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 85ba644..7a8d910 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -82,10 +82,14 @@ namespace Input { struct InputThr { InputThr() : thr(run, this) { + thr.detach(); } static void run(InputThr* that) { - that->runImpl(); + try { + that->runImpl(); + } catch (...) {} + delete that; } void runImpl() { @@ -120,7 +124,6 @@ namespace Input { } static InputThr& instance() { - // intentional memory leak, to simplify shutdown process static InputThr* input = new InputThr(); return *input; From c1f540e61e5294a151dd6591a7533374fd2abce5 Mon Sep 17 00:00:00 2001 From: Anton Samokhvalov Date: Wed, 29 Dec 2021 15:46:15 +0300 Subject: [PATCH 156/289] Revert "no memory leak" This reverts commit fe66d52a38bbc65703482db4fcfca7300d6953d9. --- src/btop.cpp | 10 +++++----- src/btop_input.cpp | 7 ++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 48884ba..ac49a7e 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -237,15 +237,15 @@ void clean_quit(int sig) { std::cerr << Global::fg_red << "ERROR: " << Global::fg_white << Global::exit_error_msg << Fx::reset << endl; } Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); - close(0); + + const auto excode = (sig != -1 ? sig : 0); + //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor #ifndef __APPLE__ - if (Tools::active_locks > 0) { - quick_exit((sig != -1 ? sig : 0)); - } + quick_exit(excode); #endif - if (sig != -1) exit(sig); + exit(excode); } //* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 7a8d910..85ba644 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -82,14 +82,10 @@ namespace Input { struct InputThr { InputThr() : thr(run, this) { - thr.detach(); } static void run(InputThr* that) { - try { - that->runImpl(); - } catch (...) {} - delete that; + that->runImpl(); } void runImpl() { @@ -124,6 +120,7 @@ namespace Input { } static InputThr& instance() { + // intentional memory leak, to simplify shutdown process static InputThr* input = new InputThr(); return *input; From 9faeeabda5132e05c5d9b31658fe8faf629e3621 Mon Sep 17 00:00:00 2001 From: Anton Samokhvalov Date: Wed, 29 Dec 2021 15:47:48 +0300 Subject: [PATCH 157/289] quick_exit for Darwin --- src/btop.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index ac49a7e..494418f 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -241,11 +241,11 @@ void clean_quit(int sig) { const auto excode = (sig != -1 ? sig : 0); //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor -#ifndef __APPLE__ +#ifdef __APPLE__ + _Exit(excode); +#else quick_exit(excode); #endif - - exit(excode); } //* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP From 2171789675099353601ee10ea19c39d8960d504f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Dec 2021 14:40:32 +0100 Subject: [PATCH 158/289] v1.1.4 Bug fixes --- CHANGELOG.md | 10 ++++++++++ src/btop.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ec004f..c5b6797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.1.4 + +* Fixed: Create dependency files in build directory when compiling, by @stwnt + +* Fixed: fix CPU temp fallback on macOS, by @joske + +* Changed: From rng::sort() to rng::stable_sort() for more stability + +* Fixed: in_avail() can always be zero, by @pg83 + ## v1.1.3 * Added: New theme ayu, by @AlphaNecron diff --git a/src/btop.cpp b/src/btop.cpp index 494418f..8ad11e8 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -57,7 +57,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.1.3"; + const string Version = "1.1.4"; int coreCount; string overlay; From 56deec49885498be0cca99717c59107e8e88ff16 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 30 Dec 2021 11:26:23 +0100 Subject: [PATCH 159/289] Fixed: Account for system rolling over net speeds in Net::collect() --- src/btop_input.cpp | 4 ++-- src/btop_shared.hpp | 2 +- src/linux/btop_collect.cpp | 12 ++++++++++-- src/osx/btop_collect.cpp | 12 ++++++++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 85ba644..39fbd8a 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -517,8 +517,8 @@ namespace Input { ndev.stat.at("upload").offset = 0; } else { - ndev.stat.at("download").offset = ndev.stat.at("download").last; - ndev.stat.at("upload").offset = ndev.stat.at("upload").last; + ndev.stat.at("download").offset = ndev.stat.at("download").last + ndev.stat.at("download").rollover; + ndev.stat.at("upload").offset = ndev.stat.at("upload").last + ndev.stat.at("upload").rollover; } no_update = false; } diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index c9f66df..22c6204 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -171,7 +171,7 @@ namespace Net { extern unordered_flat_map graph_max; struct net_stat { - uint64_t speed = 0, top = 0, total = 0, last = 0, offset = 0; + uint64_t speed = 0, top = 0, total = 0, last = 0, offset = 0, rollover = 0; }; struct net_info { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 5a71e11..4fe120d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1103,10 +1103,18 @@ namespace Net { catch (const std::out_of_range&) {} //? Update speed, total and top values + if (val < saved_stat.last) { + saved_stat.rollover += saved_stat.last; + saved_stat.last = 0; + } + if (cmp_greater((unsigned long long)saved_stat.rollover + (unsigned long long)val, numeric_limits::max())) { + saved_stat.rollover = 0; + saved_stat.last = 0; + } saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); if (saved_stat.speed > saved_stat.top) saved_stat.top = saved_stat.speed; - if (saved_stat.offset > val) saved_stat.offset = 0; - saved_stat.total = val - saved_stat.offset; + if (saved_stat.offset > val + saved_stat.rollover) saved_stat.offset = 0; + saved_stat.total = (val + saved_stat.rollover) - saved_stat.offset; saved_stat.last = val; //? Add values to graph diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 9f5355c..5537d75 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -927,10 +927,18 @@ namespace Net { } //? Update speed, total and top values + if (val < saved_stat.last) { + saved_stat.rollover += saved_stat.last; + saved_stat.last = 0; + } + if (cmp_greater((unsigned long long)saved_stat.rollover + (unsigned long long)val, numeric_limits::max())) { + saved_stat.rollover = 0; + saved_stat.last = 0; + } saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); if (saved_stat.speed > saved_stat.top) saved_stat.top = saved_stat.speed; - if (saved_stat.offset > val) saved_stat.offset = 0; - saved_stat.total = val - saved_stat.offset; + if (saved_stat.offset > val + saved_stat.rollover) saved_stat.offset = 0; + saved_stat.total = (val + saved_stat.rollover) - saved_stat.offset; saved_stat.last = val; //? Add values to graph From 3ea3aaaf333c7443be76e7e22a93e9182a8f9ab0 Mon Sep 17 00:00:00 2001 From: Marco Radocchia Date: Mon, 10 Jan 2022 14:20:03 +0100 Subject: [PATCH 160/289] Added theme gruvbox_material_dark --- themes/gruvbox_material_dark.theme | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 themes/gruvbox_material_dark.theme diff --git a/themes/gruvbox_material_dark.theme b/themes/gruvbox_material_dark.theme new file mode 100644 index 0000000..7133e3f --- /dev/null +++ b/themes/gruvbox_material_dark.theme @@ -0,0 +1,92 @@ +#Bashtop gruvbox (https://github.com/morhetz/gruvbox) theme +#by BachoSeven + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#FFFFFF", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#282828" + +# Main text color +theme[main_fg]="#d4be98" + +# Title color for boxes +theme[title]="#d4be98" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#ea6962" + +# Background color of selected items +theme[selected_bg]="#d8a657" + +# Foreground color of selected items +theme[selected_fg]="#282828" + +# Color of inactive/disabled text +theme[inactive_fg]="#282828" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#665c54" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#a9b665" + +# Cpu box outline color +theme[cpu_box]="#7c6f64" + +# Memory/disks box outline color +theme[mem_box]="#7c6f64" + +# Net up/down box outline color +theme[net_box]="#7c6f64" + +# Processes box outline color +theme[proc_box]="#7c6f64" + +# Box divider line and small boxes line color +theme[div_line]="#7c6f64" + +# Temperature graph colors +theme[temp_start]="#7daea3" +theme[temp_mid]="#e78a4e" +theme[temp_end]="#ea6962" + +# CPU graph colors +theme[cpu_start]="#a9b665" +theme[cpu_mid]="d8a657" +theme[cpu_end]="#ea6962" + +# Mem/Disk free meter +theme[free_start]="#89b482" +theme[free_mid]="" +theme[free_end]="#89b482" + +# Mem/Disk cached meter +theme[cached_start]="#7daea3" +theme[cached_mid]="" +theme[cached_end]="#7daea3" + +# Mem/Disk available meter +theme[available_start]="#d8a657" +theme[available_mid]="" +theme[available_end]="#d8a657" + +# Mem/Disk used meter +theme[used_start]="#ea6962" +theme[used_mid]="" +theme[used_end]="#ea6962" + +# Download graph colors +theme[download_start]="#e78a4e" +theme[download_mid]="" +theme[download_end]="#e78a4e" + +# Upload graph colors +theme[upload_start]="#d3869b" +theme[upload_mid]="" +theme[upload_end]="#d3869b" From 3d7bb52e48c506ae73cdc45e947b2c820cb8cde4 Mon Sep 17 00:00:00 2001 From: Jos Dehaes Date: Wed, 12 Jan 2022 00:04:26 +0100 Subject: [PATCH 161/289] Squashed commit of the following: commit 7add05599de74d8047a9802fd673ae62a91a3372 Author: Jos Dehaes Date: Tue Jan 11 23:48:16 2022 +0100 bring in line with upstream commit ddb2fb0fac530ef10a20413f311e3d970d038d3f Author: Jos Dehaes Date: Tue Jan 11 23:35:21 2022 +0100 fix CPU name commit 01a1dda7346e9c1842225a3883e7dc5b99cdfc56 Merge: 3b6dac6 96ac114 Author: Jos Dehaes Date: Tue Jan 11 23:29:17 2022 +0100 merge main into freebsd commit 3b6dac640e70613b5549db291781e25fa6506202 Author: Jos Dehaes Date: Tue Jan 11 23:17:07 2022 +0100 disk IO working commit 30b33730b3de6567e5df3243fd372eb30123c181 Author: Jos Dehaes Date: Tue Jan 11 22:47:44 2022 +0100 reduce memleak drastically commit 682746ff0ee6c8b83f52bc44e44dd29dc9d7cdd2 Merge: 9fdf6d0 891051c Author: Jakob P. Liljenberg Date: Sat Dec 18 19:50:13 2021 +0100 Merge pull request #186 from GuillaumeGomez/freebsd Remove duplicated fstype commit 891051c8ab9984f155caa6bac2d170b0bb7d2a06 Author: Guillaume Gomez Date: Sun Dec 5 23:03:17 2021 +0100 Remove duplicated fstype commit 9fdf6d02044615da8b2c827abc002b2b71dd6db8 Author: Jos Dehaes Date: Sat Nov 27 20:55:49 2021 +0100 iterate over ALL pools commit 860a9fe472c7f4b6cc3f2ef38fb06101f5af7e21 Author: Jos Dehaes Date: Sat Nov 27 20:30:43 2021 +0100 RAII commit 7c433be4a6b6b0cac84713e976a63d661a9338ae Author: Jos Dehaes Date: Sun Nov 21 21:36:44 2021 +0100 regular filesystems + ZFS commit 70d9777908e8cd37088e1e19b8eb864a4357daba Author: Jos Dehaes Date: Sat Nov 20 22:57:00 2021 +0100 some comment + minor cleanup commit a61df3ff9815463da1cc0bdc713aa20dddc3b95e Author: Jos Dehaes Date: Sat Nov 20 22:51:49 2021 +0100 it does some IO!! commit f32358bd47802b7af2ef5fe7f03bb4d4b5c9d544 Author: Jos Dehaes Date: Tue Nov 16 22:30:55 2021 +0100 correct unit number commit d12b4d9d2359c9216ad5977a60de85aea865a92b Author: Jos Dehaes Date: Tue Nov 16 21:58:12 2021 +0100 readability commit a6602ff22b4b00ecb7138a09f5c5a15e1b13ca62 Author: Jos Dehaes Date: Tue Nov 16 21:53:33 2021 +0100 correctly iterate over devstat. still no idea how to map the devices we get back here to mountpoints commit e64610a163c23ec862c5f65d1accdd10a6163d47 Author: Jos Dehaes Date: Tue Nov 16 21:20:42 2021 +0100 RAII commit 98693aac2502ac4903b95dffcbc9664abe7c4739 Author: Jos Dehaes Date: Sun Oct 24 21:04:04 2021 +0200 devstat WIP commit 8940d68f47e3c22e9372495752ff16de2fa122b0 Author: aristocratos Date: Sun Oct 24 16:15:29 2021 +0200 Fixed cpu usage in cpu box, process cpu usage still wrong commit b547ccb25816497e5b31581d4cc102a24c1ec00a Author: aristocratos Date: Sun Oct 24 11:25:28 2021 +0200 Makefile even with OSX Makefile commit a5eabe20b6dc11367a49c51b614769bbb2436e1d Author: aristocratos Date: Sun Oct 24 11:20:46 2021 +0200 Updated Makefile commit 18451ceb0587d8304997f0e202117a73e5986b70 Author: aristocratos Date: Sun Oct 24 11:13:15 2021 +0200 Updated Makefile commit ca183b2b85fe729a8974715054bac4dc9d96d4a4 Author: aristocratos Date: Sun Oct 24 11:09:29 2021 +0200 Fixed up Makefile commit 235c95274f7ddd4a555ab1eb341776e0bd2c1dc5 Author: Jos Dehaes Date: Sat Oct 23 23:49:51 2021 +0200 fix boottime (not sure if needed) commit cc2a4987efde6f3cf8ef8ab96d6793c8220375cb Author: Jos Dehaes Date: Sat Oct 23 23:38:00 2021 +0200 temp commit 30ef6ee05057c6bbb0ddc96b7897de31e692907c Author: Jos Dehaes Date: Sat Oct 23 22:58:17 2021 +0200 cpu freq commit 735894b6caddedcf69a200e9d29cf0115c08bcce Author: aristocratos Date: Sat Oct 23 21:46:57 2021 +0200 Fixed leaks and proc tree mode commit cd3fd1a529f72eba979607f6e758ea855e01fd79 Author: Jos Dehaes Date: Fri Oct 22 22:27:32 2021 +0200 correct makefile commit cd644cfc55de21312d1492f8a8c285cfcfe44535 Author: Jos Dehaes Date: Fri Oct 22 15:49:39 2021 +0200 get rid of warnings commit 81b63652bfbaaa50d4da16f9e76a2d96036ba434 Author: Jos Dehaes Date: Fri Oct 22 15:43:22 2021 +0200 battery commit 41ba98695400a1a82aa6ddb884344b7c1e556f49 Author: Jos Dehaes Date: Fri Oct 22 15:31:04 2021 +0200 process args commit 137e876da636963ba2e758ea9fe3f4e91f15a662 Author: Jos Dehaes Date: Fri Oct 22 14:29:36 2021 +0200 remove debug commit 5249be0a40d12081ebdea05d6e3cad5c6bfa9e11 Author: Jos Dehaes Date: Fri Oct 22 14:28:40 2021 +0200 net stats commit 96461f4d948a29bbd6748223e8bb014c8d2f2902 Author: Jos Dehaes Date: Fri Oct 22 13:54:00 2021 +0200 sane memory stats commit e5ceeee1978ed5121f157da554fad9f51e1a5de1 Author: Jos Dehaes Date: Fri Oct 22 13:38:27 2021 +0200 processes commit 889433d4c651e3f7f9466f2b7d3353cc664c5950 Author: Jos Dehaes Date: Fri Oct 22 12:08:47 2021 +0200 cpu model + cpu load commit f037ab306a6e08bc4582933f6ecc8cf352dae6cd Author: Jos Dehaes Date: Fri Oct 22 10:31:37 2021 +0200 freebsd first work commit de6216792154477a5ab7f564c9467761daf842e2 Merge: a590dd3 a0ee404 Author: Jos Dehaes Date: Wed Oct 20 23:10:36 2021 +0200 Merge branch 'main' into OSX # Conflicts: # CHANGELOG.md # Makefile # src/btop.cpp commit a590dd3f67c9f2f8f8dc3fa49920a40a5e8b369d Author: aristocratos Date: Mon Oct 18 11:20:12 2021 +0200 Ignore format-truncation commit 4c30742d412cf552de22b3746a68cd62bfe867f2 Author: Jos Dehaes Date: Mon Oct 18 10:08:01 2021 +0200 comments about temp sensors commit 46030de77cb1409eb8b0247c331408a240b0227a Author: Jos Dehaes Date: Mon Oct 18 08:10:37 2021 +0200 available = total - used commit 4c228de0ef8a75275178bad081e568f85fc579fd Author: Jos Dehaes Date: Sun Oct 17 22:19:41 2021 +0200 use sysconf to get arg_max - seems simpler commit c60fc29f0f62831730c04c23cd9ffbefef50a1d8 Author: Jos Dehaes Date: Sun Oct 17 22:10:50 2021 +0200 arg_max should be int on macos commit 0b5a931a6d5e8d1a434e88e8fd0613ab948995fa Author: Jos Dehaes Date: Sun Oct 17 22:01:42 2021 +0200 only fetch max_args once commit 71d5cd5fd91511a90e43e5e6dbf7a1b6a3c3f9c8 Author: aristocratos Date: Sat Oct 16 23:24:07 2021 +0200 Reverted mutexes back to custom atomic bool based locks commit 3f34a67df68f3f451cb48b023b7cd42ccf933ce4 Author: Jos Dehaes Date: Sat Oct 16 21:47:55 2021 +0200 these helpers can be static commit fc19c46c8aab03e252f60f6f9447d7e1861cbcb9 Author: Jos Dehaes Date: Sat Oct 16 21:44:49 2021 +0200 code cleanup: put the code in .cpp to enable incremental build commit c252c618c043c4b85783f56363121877d0db0727 Author: Jos Dehaes Date: Sat Oct 16 21:09:21 2021 +0200 don't crash on intel commit 9f88187c29821148c7a5272926d204bd3eb39f89 Author: Jos Dehaes Date: Sat Oct 16 21:06:18 2021 +0200 small improvement commit 808f09c97465e8cf511f7690b40a69cd8a2efa15 Author: Jos Dehaes Date: Sat Oct 16 20:59:48 2021 +0200 don't iterate 3 times commit d8408336e3b8336025a087a2bf79a2d15f51ee66 Author: Jos Dehaes Date: Sat Oct 16 20:59:27 2021 +0200 remove debug commit 4f078c3beb960fe06f4d8b44b9c913e2aacf7625 Author: Jos Dehaes Date: Wed Oct 13 23:38:27 2021 +0200 more temperature (M1 + intel) commit 289880aaa6d1a3625c01e9d7643138343b29db53 Merge: 88a2528 3ffb212 Author: aristocratos Date: Sat Oct 16 19:37:09 2021 +0200 Merge branch 'OSX' of github.com:aristocratos/btop into OSX commit 88a2528ca3a2390f2c94c7f1a18ba982a5e5f2b2 Author: aristocratos Date: Sat Oct 16 19:34:10 2021 +0200 Merge changes from main commit 3ffb21203aa3f4ad978533a3f2b1e67e636381ea Author: Jos Dehaes Date: Sat Oct 16 19:20:45 2021 +0200 release a bit more - still has negative temps for 2 cores on my system commit 70b48710626ba22df496ba741625ce03cba6abbd Author: aristocratos Date: Sat Oct 16 01:59:44 2021 +0200 Fixed leaks in Mem and attempt at fixing leaks in sensors.cpp commit fbae907720afbae47162666b6b0aea974be80c07 Author: Jos Dehaes Date: Fri Oct 15 23:41:37 2021 +0200 temperature sensors via IOKit commit cef0f0a68daa88a380000ce200a364e4701ba93a Author: aristocratos Date: Fri Oct 15 18:39:17 2021 +0200 Process command line arguments commit 921cfa01ffc104c57f2825d0bca648233ddff191 Author: aristocratos Date: Wed Oct 13 23:20:15 2021 +0200 Re-enable setuid and set default SU_GROUP to wheel for OSX commit a416c888c7356634ef7a5286130a56160d72f50a Author: Jos Dehaes Date: Wed Oct 13 21:16:41 2021 +0200 temperature commit e7afe00ce7960bfe6fb6ba2a9a2f5d498c5b4fca Author: aristocratos Date: Wed Oct 13 12:54:43 2021 +0200 Cpu usage working again commit 4193ef8921617e48ce07ce95d898386f7dd77f43 Author: aristocratos Date: Wed Oct 13 10:36:51 2021 +0200 Fixed cpu lazy sorting commit 93fcb6ff04d84c008ed9f7d28918eb9eb8adf740 Author: aristocratos Date: Tue Oct 12 22:22:45 2021 +0200 Update README.md commit 683354cd2ed8add79c6940e51800431e8b020635 Merge: 8a399c4 6d724d6 Author: aristocratos Date: Tue Oct 12 22:19:30 2021 +0200 Merge pull request #80 from ShrirajHegde/OSX Add github workflow for MacOS commit 8a399c499af87883a7e4b2cf7f6d193f76909923 Author: aristocratos Date: Tue Oct 12 21:50:46 2021 +0200 pointer to smart pointer, first pass commit 772605003af9c1c00f163ff75279cd0055074c96 Author: aristocratos Date: Tue Oct 12 18:54:38 2021 +0200 Fixed detailed memory not updating commit 28cb67753332fe8c93d23cbf8e4db636fc6823d6 Author: Jos Dehaes Date: Mon Oct 11 22:19:25 2021 +0200 more memory free-up - still leaks like crazy commit 304457863f6cdccf82fbe1cca3078c7f5d9f97cd Author: Jos Dehaes Date: Mon Oct 11 21:48:07 2021 +0200 more RAII cleanup commit 82e2e3c55c23e37dbf226952cca4587df3522fa3 Author: aristocratos Date: Mon Oct 11 12:40:25 2021 +0200 Removed non present cpu fields and fixed calculation for selectable cpu field graphs commit 68603f2b37e34828f78f0f675f66bd835dae8325 Author: aristocratos Date: Mon Oct 11 10:57:04 2021 +0200 RAII Wrappers for Cpu::get_battery() commit d5cb24fbeb19ae57507e1715aa402b2dc33f9b6b Author: Jos Dehaes Date: Sun Oct 10 20:23:11 2021 +0200 RAII commit 8fad5a61bee973c22f3a11fd7fee2c4e40390bbb Author: Jos Dehaes Date: Sat Oct 9 21:44:16 2021 +0200 get more disk IO stats commit 7fa903cf160b391fb316ea32a60984921a174066 Author: Jos Dehaes Date: Sat Oct 9 21:43:48 2021 +0200 fix build commit 98036db660e306626d41fb1b67d9938d9ffe168a Author: Jos Dehaes Date: Sat Oct 9 21:18:25 2021 +0200 remove unnecessary uptime param commit aae7ae35caec64ba611d9b78b24c0ad2716f333e Author: Jos Dehaes Date: Sat Oct 9 21:07:23 2021 +0200 remove debug logging commit 5187420b04973edcdd25c1b639795a2c8539b2d9 Author: Jos Dehaes Date: Sat Oct 9 21:06:43 2021 +0200 fix process elapsed time commit 89582c0ea6e9bdd7a658b5583d2ce2c5deeee8b0 Author: Jos Dehaes Date: Sat Oct 9 21:06:29 2021 +0200 don't double free commit 6d724d6155bad8c084e4c9bdb1d7dda13543a5ac Author: Shriraj Hegde Date: Sat Oct 9 21:46:33 2021 +0530 Change Upload filename commit 4f94ecc8ad7d7cdb7daed82fd98a5634d723ec6b Author: Shriraj Hegde Date: Sat Oct 9 21:40:11 2021 +0530 Fix upload path commit e1d6d0a1f224474417078a0a1b98a6c4b5c94a53 Author: Shriraj Hegde Date: Sat Oct 9 21:36:13 2021 +0530 Skip installing gcc via Homebrew Change job name commit 02cdd9d759d163519048d24746273e4eda2149d0 Author: Shriraj Hegde Date: Sat Oct 9 21:30:40 2021 +0530 Fix uploading Remove distclean commit 39eb6c396fc31f798d23c21e7f4b313930dca982 Author: Shriraj Hegde Date: Sat Oct 9 21:26:57 2021 +0530 Disable static compilation commit 099592bccdafe8d8d8c421bcad3e036cbea580ce Author: aristocratos Date: Sat Oct 9 17:52:10 2021 +0200 Ignore empty pid 0 to fix tree mode commit a28e17556e74bb618fc2b6eb74f250b139406cdd Author: Shriraj Hegde Date: Sat Oct 9 21:17:11 2021 +0530 Add workflow for MacOS commit aee9179c0a98bce54b55c8bb8ebdc1ac99bad69e Author: aristocratos Date: Sat Oct 9 17:36:46 2021 +0200 Disable failed tty mode detection for OSX commit 4b7b98058d7190a494fa522834217d786d71e5fb Author: aristocratos Date: Sat Oct 9 11:28:32 2021 +0200 Fixed disk io and added io activity based on read/write commit bfa0629e7d1e50f88d9a1207930e2f39270fc189 Author: Jos Dehaes Date: Fri Oct 8 22:28:10 2021 +0200 fill in 0 for ioticks commit a016ff8a039634bc37a22a4a84b31055b3cfab37 Author: Jos Dehaes Date: Fri Oct 8 22:16:01 2021 +0200 disk io from IOreg. Does not show any io though commit f98606c6db09d50c7ae234437ea03eda2cc8739c Author: Jos Dehaes Date: Fri Oct 8 09:32:06 2021 +0200 per process IO stats commit c8b50ed4883103f66c9ed869fd0252d48f18f58f Author: Jos Dehaes Date: Fri Oct 8 00:11:08 2021 +0200 don't show autofs, it's useless commit c4df64d4409c511847d76b37a0794b8bb4f6942d Author: aristocratos Date: Thu Oct 7 18:41:49 2021 +0200 Fixed compile time display for gmake and command timings commit b3e6f495f76bd71fba3442a557df22afdd3e642d Author: aristocratos Date: Thu Oct 7 18:26:15 2021 +0200 Fixed clk_tck -> clkTck commit e53799188ffc24f3948e7ced375b7fbb53911247 Author: aristocratos Date: Thu Oct 7 18:25:14 2021 +0200 Fixed better detection for OSX commit b864edf984e8f0daa0f10a6ee305074c68efeb42 Author: aristocratos Date: Thu Oct 7 18:24:37 2021 +0200 Fixed cumulative cpu usage commit 6a3c5d9b976c711461d08c373483c84bb69db257 Author: aristocratos Date: Thu Oct 7 13:20:30 2021 +0200 Proc::collect() better cpu percent accurazy commit 84d0596294432baef1b10f7d3a566a07382f69d3 Merge: 3564f8e 98e1e87 Author: aristocratos Date: Thu Oct 7 12:56:55 2021 +0200 Merge branch 'OSX' of github.com:aristocratos/btop into OSX commit 3564f8e4c26f04ec89482606e68a452a3e5f9693 Author: aristocratos Date: Thu Oct 7 12:56:27 2021 +0200 Proc::collect() fixed cputimes and cpu percentage calc commit 98e1e874059fe69968d4bb7e4685f292e3b7fd65 Merge: 60c5636 d96fdd7 Author: Jos Dehaes Date: Thu Oct 7 11:32:41 2021 +0200 Merge branch 'main' into OSX commit 60c5636cd7c18e6c806cb4cd88846db10092dd57 Author: Jos Dehaes Date: Wed Oct 6 22:45:54 2021 +0200 fix warning commit 489e446152ce00f8e92db8c4e10759f96e38f17f Author: Jos Dehaes Date: Wed Oct 6 22:38:40 2021 +0200 details + process states commit 7e5a808c731772bab35204f2e286975fca334f54 Author: Jos Dehaes Date: Wed Oct 6 22:38:19 2021 +0200 avoid details crash commit 9c9da4606b3f93c0701b820a875fb3db5d0c3daf Author: Jos Dehaes Date: Wed Oct 6 21:03:21 2021 +0200 fix quit on macos commit ec7415384d9d9b42892a1e36ff55bf7a117a253b Author: Jos Dehaes Date: Wed Oct 6 00:41:37 2021 +0200 fix mistake in makefile commit 5ac8fa4c8a8f73efac6ac1f15e458ed3b2c1164b Author: Jos Dehaes Date: Wed Oct 6 18:56:13 2021 +0200 don't show /dev commit d901bbebd94ec45c45431fcd1ab37a974f783d9b Author: aristocratos Date: Wed Oct 6 17:27:51 2021 +0200 Ignore tags and other branches commit c7f1e71e29bafb5334cd4e256c662e5ee6303b1b Author: Jos Dehaes Date: Wed Oct 6 16:00:41 2021 +0200 comment commit b9d58e3faf5b60ad4f5f65454b454ff52deb5eaa Author: Jos Dehaes Date: Wed Oct 6 15:55:58 2021 +0200 impossible to get CPU freq on M1 apparently commit 66072711c24b2694c4a0054c58829095ed97ada2 Author: Jos Dehaes Date: Wed Oct 6 15:33:43 2021 +0200 detect full commit 6bb0e930a2c44b4fb7d0d02a40f210fa12fdc657 Author: Jos Dehaes Date: Wed Oct 6 00:38:46 2021 +0200 CPU freq in GHz commit a5f10f1a0ff9d10fa8d9d3038aa160b2380aa294 Author: Jos Dehaes Date: Wed Oct 6 15:13:18 2021 +0200 check array length commit 155c848b97e1385bd29eaba91a87ecfb1d846bf7 Author: Jos Dehaes Date: Wed Oct 6 15:05:20 2021 +0200 switch to other way to get CPU freq (still does not work) commit cf51ba2ebe88dddd943040ced484581dc260c3c8 Author: Jos Dehaes Date: Wed Oct 6 14:45:44 2021 +0200 remove some warnings commit 775dff5f72b0631bba0ed01d72374d8c1d1cd059 Author: Jos Dehaes Date: Wed Oct 6 14:16:45 2021 +0200 fix link commit 8c67967775fb98bda80eee40cb6833a00bfb93a1 Author: Jos Dehaes Date: Wed Oct 6 14:16:38 2021 +0200 reduce diff more commit 70b47d2ca8a7e0927cf9613e8fe776d2405f60ee Author: Jos Dehaes Date: Wed Oct 6 14:10:23 2021 +0200 reduce diff with main branch commit ca9cb48054c5850cbb3c23d368e04644a1885de0 Merge: d0c6c0a c66b46f Author: Jos Dehaes Date: Wed Oct 6 13:49:20 2021 +0200 Merge remote-tracking branch 'origin/main' into OSX # Conflicts: # Makefile # src/osx/btop_collect.cpp commit c66b46f850d31c100226e519c55b39df9129aeb8 Author: Jos Dehaes Date: Wed Oct 6 13:41:57 2021 +0200 battery state via CoreFoundation commit d0c6c0a362d8dc4f76e2901d7b406a70d8a69b6b Author: Jos Dehaes Date: Wed Oct 6 10:51:36 2021 +0200 all disks + load averages commit ca67526dc175dba7d98193a6462e70ef1acab194 Author: Jos Dehaes Date: Wed Oct 6 10:33:55 2021 +0200 show all disks commit 56119f99a95ca541d6ab744a9ded54c84e0a3184 Author: Jos Dehaes Date: Wed Oct 6 00:17:41 2021 +0200 procs sorting/filtering commit 8d86011d72a07b3f86f6b525b026b805667a3172 Author: Jos Dehaes Date: Tue Oct 5 23:42:17 2021 +0200 battery states commit a9b64d62e4abf96fe3edcfa660871caef2041d0f Author: Jos Dehaes Date: Tue Oct 5 23:24:59 2021 +0200 battery hack works on M1 commit ce5103114246f5549017ef4823442a0ea916e1dd Author: Jos Dehaes Date: Tue Oct 5 23:18:22 2021 +0200 ugly hack to get battery commit d5e6725c6cd6973cc75dfe2993892e1c25ac8d38 Author: Jos Dehaes Date: Tue Oct 5 22:42:42 2021 +0200 CPU stuff commit 5c02bd8c8380c5c74837b982987b7bf31103245f Author: Jos Dehaes Date: Tue Oct 5 21:25:42 2021 +0200 network commit d5da9d49835cdb23ad5830c000e1b93fcb8f46fd Author: Jos Dehaes Date: Tue Oct 5 15:43:05 2021 +0200 correct cached size commit 5f11aba504254d86ed9a2319967590d50988e16f Author: Jos Dehaes Date: Tue Oct 5 12:03:48 2021 +0200 vm stats from syscall + swap commit 776fc968529e8e7e38fc3168c83b2727198722ad Author: Jos Dehaes Date: Tue Oct 5 10:48:07 2021 +0200 seems to work indeed commit 7b40e2835a085bfe0d5eb40f367a1ed50353e4d9 Author: Jos Dehaes Date: Tue Oct 5 10:46:14 2021 +0200 allow override optimization flag commit 005ea24e4c9bcc6608671a0635126bf10bdece34 Author: Jos Dehaes Date: Tue Oct 5 10:09:24 2021 +0200 update Makefile commit af8cec9debac328645f0f4e2f136e4572d88332e Author: Jos Dehaes Date: Mon Oct 4 15:32:55 2021 +0200 some more params commit 7ebe4f7594599ccafbf72a004ce37f965549f64d Author: Jos Dehaes Date: Mon Oct 4 15:15:55 2021 +0200 show more disks commit e50a56394a3702b6616d03694f5d23a5f7ba2f1c Author: Jos Dehaes Date: Mon Oct 4 14:52:56 2021 +0200 disks show something commit 6497a8c2021b67057dfed26488aec0d82e919a90 Author: Jos Dehaes Date: Mon Oct 4 09:15:35 2021 +0200 reformat commit 28e152b80c07c1fb9a4049cca8510f8bdc31adbb Author: Jos Dehaes Date: Sun Oct 3 23:21:13 2021 +0200 decrease diff with upstream commit 40da88e9ca91f3db540b63b15da5bc34dc9175e9 Author: Jos Dehaes Date: Sun Oct 3 22:56:14 2021 +0200 try to get disks to show commit eaf2bb56a503fd2bf3787bfd90b5bc8640b7d628 Author: Jos Dehaes Date: Sun Oct 3 22:42:01 2021 +0200 don't crash on deque::back() commit f66b6f712c361fafbe6d0cfd8f8c0838dc1bb4d2 Author: Jos Dehaes Date: Sun Oct 3 22:08:21 2021 +0200 cpu freq, name & process uid/name commit 34a8a61f4de964d3137637b045be8738c4b1b6e5 Author: Jos Dehaes Date: Sun Oct 3 21:46:11 2021 +0200 basic process info commit 29bb2dcc5fcc6b946511068f036590c18fb459ce Author: Jos Dehaes Date: Sun Oct 3 21:45:39 2021 +0200 initialize mutex (needed on macos apparently and not on linux) commit fb5970b0005793d760e652348d6acc30fb570f70 Author: Jos Dehaes Date: Sat Oct 2 23:53:41 2021 +0200 comment commit 49d16cdddd56ba5631269eb2ffbec87d9f36f81e Author: Jos Dehaes Date: Sat Oct 2 23:51:29 2021 +0200 extract delimiters commit 3db9d6647650bd836201b8150e320a7fbf28e3c2 Author: Jos Dehaes Date: Sat Oct 2 23:48:28 2021 +0200 first infos on macos: memory used & free commit f8acb2f8542429677116799ddb5f442488cf3f4f Author: Jos Dehaes Date: Tue Sep 28 23:37:03 2021 +0200 make it compile on macos (M1 - arm64). Does not run though commit bbba17cd35248e4e9ec9bfc1b113758cfcffde1f Author: Jos Dehaes Date: Wed Oct 6 10:51:36 2021 +0200 all disks + load averages commit 548203e93dfaf3ec9f24086bee08aac85891c4df Author: Jos Dehaes Date: Wed Oct 6 10:33:55 2021 +0200 show all disks commit 0ab2be39857fb3dcdb13b49bc9155f17c7d82a4e Author: Jos Dehaes Date: Wed Oct 6 00:17:41 2021 +0200 procs sorting/filtering commit 096104c90b571e931a3a7d9c813dbfc9aa47e212 Author: Jos Dehaes Date: Tue Oct 5 23:42:17 2021 +0200 battery states commit 0ad93684c2a72293b23d6a2163c9ec51b499dfa3 Author: Jos Dehaes Date: Tue Oct 5 23:24:59 2021 +0200 battery hack works on M1 commit c75b0f1cea34e6c4c70332ba7e2572ec9b70deef Author: Jos Dehaes Date: Tue Oct 5 23:18:22 2021 +0200 ugly hack to get battery commit 600b4f72b3bbbcd85bf5d148942bce7be8cf0b72 Author: Jos Dehaes Date: Tue Oct 5 22:42:42 2021 +0200 CPU stuff commit 4eb812d52c6e179ae386df0156021d7c35cbe5a3 Author: Jos Dehaes Date: Tue Oct 5 21:25:42 2021 +0200 network commit 899be68a78270216bfdcca5f0c87668a87c8792f Author: Jos Dehaes Date: Tue Oct 5 15:43:05 2021 +0200 correct cached size commit a1c7f935e3a5661688c0de1ad3226f7bc43b9979 Author: Jos Dehaes Date: Tue Oct 5 12:03:48 2021 +0200 vm stats from syscall + swap commit bd1050a7404f9766a0125523c868a27d5cfac8e8 Author: Jos Dehaes Date: Tue Oct 5 10:48:07 2021 +0200 seems to work indeed commit 5094b73758ee88617e8d5ce876211e1efa298769 Author: Jos Dehaes Date: Tue Oct 5 10:46:14 2021 +0200 allow override optimization flag commit 8811270332bc2276cd18c1116f4d3c2d64a6f721 Author: Jos Dehaes Date: Tue Oct 5 10:09:24 2021 +0200 update Makefile commit 42f966f448b9ad571db7849dc8fd525e0fe72309 Author: Jos Dehaes Date: Mon Oct 4 15:32:55 2021 +0200 some more params commit c1e6d6a62e2810f80fac372e666ec169540b0591 Author: Jos Dehaes Date: Mon Oct 4 15:15:55 2021 +0200 show more disks commit 50fcdaa8543f717bf36146cfa38636fd39009f23 Author: Jos Dehaes Date: Mon Oct 4 14:52:56 2021 +0200 disks show something commit 264bf2d7da0e3fabb5987cddee73762e52170a51 Author: Jos Dehaes Date: Mon Oct 4 09:15:35 2021 +0200 reformat commit 1fd625086ba42e9440c463ae940563d934b8b5c3 Author: Jos Dehaes Date: Sun Oct 3 23:21:13 2021 +0200 decrease diff with upstream commit 17f9f3703c1dd52a86176131a2239cd52ee285bd Author: Jos Dehaes Date: Sun Oct 3 22:56:14 2021 +0200 try to get disks to show commit 8462ae6431fcfe1985d1bbb4404452ddc03cc1de Author: Jos Dehaes Date: Sun Oct 3 22:42:01 2021 +0200 don't crash on deque::back() commit 78bce5b5a6c1c0f3b38f802acad49ec2e32482d6 Merge: 53e379d f9505a4 Author: Jos Dehaes Date: Sun Oct 3 22:08:34 2021 +0200 Merge branch 'aristocratos:main' into main commit 53e379d74dffe2282b089450728501b51d13d199 Author: Jos Dehaes Date: Sun Oct 3 22:08:21 2021 +0200 cpu freq, name & process uid/name commit 2a44b307ef9e947c1007a86988876668a5731e64 Author: Jos Dehaes Date: Sun Oct 3 21:46:11 2021 +0200 basic process info commit 66534eb5b50753217687de0414d390bcb2a14cf1 Author: Jos Dehaes Date: Sun Oct 3 21:45:39 2021 +0200 initialize mutex (needed on macos apparently and not on linux) commit 0983917f26948d83fd8da103903ec99f88058d87 Author: Jos Dehaes Date: Sat Oct 2 23:53:41 2021 +0200 comment commit 9732507248b30139d4af54615945c0b4737cff7d Author: Jos Dehaes Date: Sat Oct 2 23:51:29 2021 +0200 extract delimiters commit 6e704ce8387041c33022459fb6a084362f82a72c Merge: fe4db7c 7bfbd83 Author: Jos Dehaes Date: Sat Oct 2 23:48:43 2021 +0200 Merge branch 'main' of github.com:joske/btop commit fe4db7c16cd349053385eda62e9f2df2e7344d3d Author: Jos Dehaes Date: Sat Oct 2 23:48:28 2021 +0200 first infos on macos: memory used & free commit 7bfbd83a476c8cbe3b74e22b1e44f201026bf9d1 Merge: 8c8139b a15f961 Author: Jos Dehaes Date: Fri Oct 1 17:05:26 2021 +0200 Merge branch 'aristocratos:main' into main commit 8c8139bd1df0849061b5e1425a3138d5f45ec149 Merge: 679d21c a246c09 Author: Jos Dehaes Date: Wed Sep 29 21:50:00 2021 +0200 Merge branch 'aristocratos:main' into main commit 679d21cd223b1928e8dde95cac25e8bfb412bedf Merge: 4c70c5b a49b8f9 Author: Jos Dehaes Date: Wed Sep 29 20:23:34 2021 +0200 Merge branch 'aristocratos:main' into main commit 4c70c5bdd98bfcc0ae9d9d9e8e3713dc8af71d03 Merge: 84a9746 c70667e Author: Jos Dehaes Date: Wed Sep 29 08:30:05 2021 +0200 Merge branch 'aristocratos:main' into main commit 84a974695afaadc53d1d8576ea66255166ede482 Author: Jos Dehaes Date: Tue Sep 28 23:37:03 2021 +0200 make it compile on macos (M1 - arm64). Does not run though --- Makefile | 7 +- src/btop.cpp | 3 + src/freebsd/btop_collect.cpp | 1348 ++++++++++++++++++++++++++++++++++ 3 files changed, 1357 insertions(+), 1 deletion(-) create mode 100644 src/freebsd/btop_collect.cpp diff --git a/Makefile b/Makefile index 4b2d0a0..f844c21 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) SU_GROUP := root - override ADDFLAGS += -lstdc++ -lm -lkvm -Wl,-rpath=/usr/local/lib/gcc11 + override ADDFLAGS += -lstdc++ -lm -lkvm -ldevstat -Wl,-rpath=/usr/local/lib/gcc11 export MAKE = gmake else ifeq ($(PLATFORM_LC),macos) PLATFORM_DIR := osx @@ -125,6 +125,10 @@ override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) INC := -I$(INCDIR) -I$(SRCDIR) SU_USER := root +ifdef DEBUG + override OPTFLAGS := -O0 -g +endif + SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)) SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)) @@ -190,6 +194,7 @@ install: @printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n" @cp -pr themes $(DESTDIR)$(PREFIX)/share/btop + #? Set SUID bit for btop as $SU_USER in $SU_GROUP setuid: @printf "\033[1;97mFile: $(DESTDIR)$(PREFIX)/bin/btop\n" diff --git a/src/btop.cpp b/src/btop.cpp index 8ad11e8..6bf3ff4 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -19,6 +19,9 @@ tab-size = 4 #include #include #include +#ifdef __FreeBSD__ +#include +#endif #include #include #include diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp new file mode 100644 index 0000000..e913c79 --- /dev/null +++ b/src/freebsd/btop_collect.cpp @@ -0,0 +1,1348 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::clamp, std::string_literals::operator""s, std::cmp_equal, std::cmp_less, std::cmp_greater; +using std::ifstream, std::numeric_limits, std::streamsize, std::round, std::max, std::min; +namespace fs = std::filesystem; +namespace rng = std::ranges; +using namespace Tools; + +//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- + +namespace Cpu { + vector core_old_totals; + vector core_old_idles; + vector available_fields = {"total"}; + vector available_sensors = {"Auto"}; + cpu_info current_cpu; + bool got_sensors = false, cpu_temp_only = false; + + //* Populate found_sensors map + bool get_sensors(); + + //* Get current cpu clock speed + string get_cpuHz(); + + //* Search /proc/cpuinfo for a cpu name + string get_cpuName(); + + struct Sensor { + fs::path path; + string label; + int64_t temp = 0; + int64_t high = 0; + int64_t crit = 0; + }; + + string cpu_sensor; + vector core_sensors; + unordered_flat_map core_mapping; +} // namespace Cpu + +namespace Mem { + double old_uptime; + std::vector zpools; + + void get_zpools(); +} + +namespace Shared { + + fs::path passwd_path; + uint64_t totalMem; + long pageSize, clkTck, coreCount, physicalCoreCount, arg_max; + int totalMem_len; + long bootTime; + + void init() { + //? Shared global variables init + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + int ncpu; + size_t len = sizeof(ncpu); + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { + Logger::warning("Could not determine number of cores, defaulting to 1."); + } else { + coreCount = ncpu; + } + + pageSize = sysconf(_SC_PAGE_SIZE); + if (pageSize <= 0) { + pageSize = 4096; + Logger::warning("Could not get system page size. Defaulting to 4096, processes memory usage might be incorrect."); + } + + clkTck = sysconf(_SC_CLK_TCK); + if (clkTck <= 0) { + clkTck = 100; + Logger::warning("Could not get system clock ticks per second. Defaulting to 100, processes cpu usage might be incorrect."); + } + + int64_t memsize = 0; + size_t size = sizeof(memsize); + if (sysctlbyname("hw.physmem", &memsize, &size, NULL, 0) < 0) { + Logger::warning("Could not get memory size"); + } + totalMem = memsize; + + struct timeval result; + size = sizeof(result); + if (sysctlbyname("kern.boottime", &result, &size, NULL, 0) < 0) { + Logger::warning("Could not get boot time"); + } else { + bootTime = result.tv_sec; + } + + //* Get maximum length of process arguments + arg_max = sysconf(_SC_ARG_MAX); + + //? Init for namespace Cpu + Cpu::current_cpu.core_percent.insert(Cpu::current_cpu.core_percent.begin(), Shared::coreCount, {}); + Cpu::current_cpu.temp.insert(Cpu::current_cpu.temp.begin(), Shared::coreCount + 1, {}); + Cpu::core_old_totals.insert(Cpu::core_old_totals.begin(), Shared::coreCount, 0); + Cpu::core_old_idles.insert(Cpu::core_old_idles.begin(), Shared::coreCount, 0); + Cpu::collect(); + for (auto &[field, vec] : Cpu::current_cpu.cpu_percent) { + if (not vec.empty() and not v_contains(Cpu::available_fields, field)) Cpu::available_fields.push_back(field); + } + Cpu::cpuName = Cpu::get_cpuName(); + Cpu::got_sensors = Cpu::get_sensors(); + Cpu::core_mapping = Cpu::get_core_mapping(); + + //? Init for namespace Mem + Mem::old_uptime = system_uptime(); + Mem::collect(); + Mem::get_zpools(); + } + +} // namespace Shared + +namespace Cpu { + string cpuName; + string cpuHz; + bool has_battery = true; + tuple current_bat; + + const array time_names = {"user", "nice", "system", "idle"}; + + unordered_flat_map cpu_old = { + {"totals", 0}, + {"idles", 0}, + {"user", 0}, + {"nice", 0}, + {"system", 0}, + {"idle", 0} + }; + + string get_cpuName() { + string name; + char buffer[1024]; + size_t size = sizeof(buffer); + if (sysctlbyname("hw.model", &buffer, &size, NULL, 0) < 0) { + Logger::error("Failed to get CPU name"); + return name; + } + name = string(buffer); + + auto name_vec = ssplit(name); + + if ((s_contains(name, "Xeon"s) or v_contains(name_vec, "Duo"s)) and v_contains(name_vec, "CPU"s)) { + auto cpu_pos = v_index(name_vec, "CPU"s); + if (cpu_pos < name_vec.size() - 1 and not name_vec.at(cpu_pos + 1).ends_with(')')) + name = name_vec.at(cpu_pos + 1); + else + name.clear(); + } else if (v_contains(name_vec, "Ryzen"s)) { + auto ryz_pos = v_index(name_vec, "Ryzen"s); + name = "Ryzen" + (ryz_pos < name_vec.size() - 1 ? ' ' + name_vec.at(ryz_pos + 1) : "") + (ryz_pos < name_vec.size() - 2 ? ' ' + name_vec.at(ryz_pos + 2) : ""); + } else if (s_contains(name, "Intel"s) and v_contains(name_vec, "CPU"s)) { + auto cpu_pos = v_index(name_vec, "CPU"s); + if (cpu_pos < name_vec.size() - 1 and not name_vec.at(cpu_pos + 1).ends_with(')') and name_vec.at(cpu_pos + 1) != "@") + name = name_vec.at(cpu_pos + 1); + else + name.clear(); + } else + name.clear(); + + if (name.empty() and not name_vec.empty()) { + for (const auto &n : name_vec) { + if (n == "@") break; + name += n + ' '; + } + name.pop_back(); + for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) { + name = s_replace(name, replace, ""); + name = s_replace(name, " ", " "); + } + name = trim(name); + } + + return name; + } + + bool get_sensors() { + got_sensors = false; + if (Config::getB("show_coretemp") and Config::getB("check_temp")) { + int32_t temp; + size_t size = sizeof(temp); + if (sysctlbyname("dev.cpu.0.temperature", &temp, &size, NULL, 0) < 0) { + Logger::warning("Could not get temp sensor - maybe you need to load the coretemp module"); + } else { + got_sensors = true; + int temp; + size_t size = sizeof(temp); + sysctlbyname("dev.cpu.0.coretemp.tjmax", &temp, &size, NULL, 0); //asuming the max temp is same for all cores + temp = (temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero... + current_cpu.temp_max = temp; + } + } + return got_sensors; + } + + void update_sensors() { + int temp; + size_t size = sizeof(temp); + sysctlbyname("hw.acpi.thermal.tz0.temperature", &temp, &size, NULL, 0); + temp = (temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero... + current_cpu.temp.at(0).push_back(temp); + if (current_cpu.temp.at(0).size() > 20) + current_cpu.temp.at(0).pop_front(); + + for (int i = 0; i < Shared::coreCount; i++) { + string s = "dev.cpu." + std::to_string(i) + ".temperature"; + if (sysctlbyname(s.c_str(), &temp, &size, NULL, 0) < 0) { + Logger::warning("Could not get temp sensor - maybe you need to load the coretemp module"); + } else { + temp = (temp - 2732) / 10; + if (cmp_less(i + 1, current_cpu.temp.size())) { + current_cpu.temp.at(i + 1).push_back(temp); + if (current_cpu.temp.at(i + 1).size() > 20) + current_cpu.temp.at(i + 1).pop_front(); + } + } + } + + } + + string get_cpuHz() { + unsigned int freq = 1; + size_t size = sizeof(freq); + + if (sysctlbyname("dev.cpu.0.freq", &freq, &size, NULL, 0) < 0) { + return ""; + } + return std::to_string(freq / 1000.0 ).substr(0, 3); // seems to be in MHz + } + + auto get_core_mapping() -> unordered_flat_map { + unordered_flat_map core_map; + if (cpu_temp_only) return core_map; + + for (long i = 0; i < Shared::coreCount; i++) { + core_map[i] = i; + } + + //? If core mapping from cpuinfo was incomplete try to guess remainder, if missing completely, map 0-0 1-1 2-2 etc. + if (cmp_less(core_map.size(), Shared::coreCount)) { + if (Shared::coreCount % 2 == 0 and (long) core_map.size() == Shared::coreCount / 2) { + for (int i = 0, n = 0; i < Shared::coreCount / 2; i++) { + if (std::cmp_greater_equal(n, core_sensors.size())) n = 0; + core_map[Shared::coreCount / 2 + i] = n++; + } + } else { + core_map.clear(); + for (int i = 0, n = 0; i < Shared::coreCount; i++) { + if (std::cmp_greater_equal(n, core_sensors.size())) n = 0; + core_map[i] = n++; + } + } + } + + //? Apply user set custom mapping if any + const auto &custom_map = Config::getS("cpu_core_map"); + if (not custom_map.empty()) { + try { + for (const auto &split : ssplit(custom_map)) { + const auto vals = ssplit(split, ':'); + if (vals.size() != 2) continue; + int change_id = std::stoi(vals.at(0)); + int new_id = std::stoi(vals.at(1)); + if (not core_map.contains(change_id) or cmp_greater(new_id, core_sensors.size())) continue; + core_map.at(change_id) = new_id; + } + } catch (...) { + } + } + + return core_map; + } + + auto get_battery() -> tuple { + if (not has_battery) return {0, 0, ""}; + + long seconds = -1; + uint32_t percent = -1; + size_t size = sizeof(percent); + string status = "discharging"; + if (sysctlbyname("hw.acpi.battery.life", &percent, &size, NULL, 0) < 0) { + has_battery = false; + } else { + has_battery = true; + size_t size = sizeof(seconds); + if (sysctlbyname("hw.acpi.battery.time", &seconds, &size, NULL, 0) < 0) { + seconds = 0; + } + int state; + size = sizeof(state); + if (sysctlbyname("hw.acpi.battery.state", &state, &size, NULL, 0) < 0) { + status = "unknown"; + } else { + if (state == 2) { + status = "charging"; + } + } + if (percent == 100) { + status = "full"; + } + } + + return {percent, seconds, status}; + } + + auto collect(const bool no_update) -> cpu_info & { + if (Runner::stopping or (no_update and not current_cpu.cpu_percent.at("total").empty())) + return current_cpu; + auto &cpu = current_cpu; + + double avg[3]; + + if (getloadavg(avg, sizeof(avg)) < 0) { + Logger::error("failed to get load averages"); + } + + cpu.load_avg = { (float)avg[0], (float)avg[1], (float)avg[2]}; + + vector> cpu_time(Shared::coreCount); + size_t size = sizeof(long) * CPUSTATES * Shared::coreCount; + if (sysctlbyname("kern.cp_times", &cpu_time[0], &size, NULL, 0) == -1) { + Logger::error("failed to get CPU times"); + } + long long global_totals = 0; + long long global_idles = 0; + vector times_summed = {0, 0, 0, 0}; + + for (long i = 0; i < Shared::coreCount; i++) { + vector times; + //? 0=user, 1=nice, 2=system, 3=idle + for (int x = 0; const unsigned int c_state : {CP_USER, CP_NICE, CP_SYS, CP_IDLE}) { + auto val = cpu_time[i][c_state]; + times.push_back(val); + times_summed.at(x++) += val; + } + try { + //? All values + const long long totals = std::accumulate(times.begin(), times.end(), 0ll); + + //? Idle time + const long long idles = times.at(3); + + global_totals += totals; + global_idles += idles; + + //? Calculate cpu total for each core + if (i > Shared::coreCount) break; + const long long calc_totals = max(0ll, totals - core_old_totals.at(i)); + const long long calc_idles = max(0ll, idles - core_old_idles.at(i)); + core_old_totals.at(i) = totals; + core_old_idles.at(i) = idles; + + cpu.core_percent.at(i).push_back(clamp((long long)round((double)(calc_totals - calc_idles) * 100 / calc_totals), 0ll, 100ll)); + + //? Reduce size if there are more values than needed for graph + if (cpu.core_percent.at(i).size() > 40) cpu.core_percent.at(i).pop_front(); + + } catch (const std::exception &e) { + Logger::error("Cpu::collect() : " + (string)e.what()); + throw std::runtime_error("collect() : " + (string)e.what()); + } + + } + + const long long calc_totals = max(1ll, global_totals - cpu_old.at("totals")); + const long long calc_idles = max(1ll, global_idles - cpu_old.at("idles")); + + //? Populate cpu.cpu_percent with all fields from syscall + for (int ii = 0; const auto &val : times_summed) { + cpu.cpu_percent.at(time_names.at(ii)).push_back(clamp((long long)round((double)(val - cpu_old.at(time_names.at(ii))) * 100 / calc_totals), 0ll, 100ll)); + cpu_old.at(time_names.at(ii)) = val; + + //? Reduce size if there are more values than needed for graph + while (cmp_greater(cpu.cpu_percent.at(time_names.at(ii)).size(), width * 2)) cpu.cpu_percent.at(time_names.at(ii)).pop_front(); + + ii++; + } + + cpu_old.at("totals") = global_totals; + cpu_old.at("idles") = global_idles; + + //? Total usage of cpu + cpu.cpu_percent.at("total").push_back(clamp((long long)round((double)(calc_totals - calc_idles) * 100 / calc_totals), 0ll, 100ll)); + + //? Reduce size if there are more values than needed for graph + while (cmp_greater(cpu.cpu_percent.at("total").size(), width * 2)) cpu.cpu_percent.at("total").pop_front(); + + if (Config::getB("show_cpu_freq")) { + auto hz = get_cpuHz(); + if (hz != "") { + cpuHz = hz; + } + } + + if (Config::getB("check_temp") and got_sensors) + update_sensors(); + + if (Config::getB("show_battery") and has_battery) + current_bat = get_battery(); + + return cpu; + } +} // namespace Cpu + +namespace Mem { + bool has_swap = false; + vector fstab; + fs::file_time_type fstab_time; + int disk_ios = 0; + vector last_found; + + mem_info current_mem{}; + + uint64_t get_totalMem() { + return Shared::totalMem; + } + + void assign_values(struct disk_info& disk, int64_t readBytes, int64_t writeBytes) { + disk_ios++; + if (disk.io_read.empty()) { + disk.io_read.push_back(0); + } else { + disk.io_read.push_back(max((int64_t)0, (readBytes - disk.old_io.at(0)))); + } + disk.old_io.at(0) = readBytes; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + + if (disk.io_write.empty()) { + disk.io_write.push_back(0); + } else { + disk.io_write.push_back(max((int64_t)0, (writeBytes - disk.old_io.at(1)))); + } + disk.old_io.at(1) = writeBytes; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + + // no io times - need to push something anyway or we'll get an ABORT + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(clamp((long)round((double)(disk.io_write.back() + disk.io_read.back()) / (1 << 20)), 0l, 100l)); + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + } + + class PipeWrapper { + public: + PipeWrapper(const char *file, const char *mode) {fd = popen(file, mode);} + virtual ~PipeWrapper() {if (fd) pclose(fd);} + auto operator()() -> FILE* { return fd;}; + private: + FILE *fd; + }; + + // find all zpools in the system. Do this only at startup. + void get_zpools() { + PipeWrapper poolPipe = PipeWrapper("zpool list -H -o name", "r"); + while (not std::feof(poolPipe())) { + char poolName[512]; + size_t len = 512; + if (fgets(poolName, len, poolPipe())) { + poolName[strcspn(poolName, "\n")] = 0; + Logger::debug("zpool found: " + string(poolName)); + Mem::zpools.push_back(poolName); + } + } + } + + void collect_disk(unordered_flat_map &disks, unordered_flat_map &mapping) { + // this bit is for 'regular' mounts + static struct statinfo cur; + long double etime = 0; + uint64_t total_bytes_read; + uint64_t total_bytes_write; + + static std::unique_ptr curDevInfo (reinterpret_cast(std::calloc(1, sizeof(struct devinfo))), std::free); + cur.dinfo = curDevInfo.get(); + + if (devstat_getdevs(NULL, &cur) != -1) { + for (int i = 0; i < cur.dinfo->numdevs; i++) { + auto d = cur.dinfo->devices[i]; + string devStatName = "/dev/" + string(d.device_name) + std::to_string(d.unit_number); + for (auto& [ignored, disk] : disks) { // find matching mountpoints - could be multiple as d.device_name is only ada (and d.unit_number is the device number), while the disk.dev is like /dev/ada0s1 + if (disk.dev.string().rfind(devStatName, 0) == 0) { + devstat_compute_statistics(&d, NULL, etime, DSM_TOTAL_BYTES_READ, &total_bytes_read, DSM_TOTAL_BYTES_WRITE, &total_bytes_write, DSM_NONE); + assign_values(disk, total_bytes_read, total_bytes_write); + string mountpoint = mapping.at(disk.dev); + Logger::debug("dev " + devStatName + " -> " + mountpoint + " read=" + std::to_string(total_bytes_read) + " write=" + std::to_string(total_bytes_write)); + } + } + + } + Logger::debug(""); + } + + // this code is for ZFS mounts + for (string poolName : Mem::zpools) { + char sysCtl[1024]; + snprintf(sysCtl, sizeof(sysCtl), "sysctl kstat.zfs.%s.dataset | egrep \'dataset_name|nread|nwritten\'", poolName.c_str()); + PipeWrapper f = PipeWrapper(sysCtl, "r"); + if (f()) { + char buf[512]; + size_t len = 512; + while (not std::feof(f())) { + uint64_t nread, nwritten; + if (fgets(buf, len, f())) { + char *name = std::strtok(buf, ": \n"); + char *value = std::strtok(NULL, ": \n"); + if (string(name).find("dataset_name") != string::npos) { + // create entry if datasetname matches with anything in mapping + // relies on the fact that the dataset name is last value in the list + // alternatively you could parse the objset-0x... when this changes, you have a new entry + string datasetname = string(value);// this is the zfs volume, like 'zroot/usr/home' -> this maps onto the device we get back from getmntinfo(3) + if (mapping.contains(datasetname)) { + string mountpoint = mapping.at(datasetname); + if (disks.contains(mountpoint)) { + auto& disk = disks.at(mountpoint); + assign_values(disk, nread, nwritten); + } + } + } else if (string(name).find("nread") != string::npos) { + nread = atoll(value); + } else if (string(name).find("nwritten") != string::npos) { + nwritten = atoll(value); + } + } + } + } + } + + } + + auto collect(const bool no_update) -> mem_info & { + if (Runner::stopping or (no_update and not current_mem.percent.at("used").empty())) + return current_mem; + + auto &show_swap = Config::getB("show_swap"); + auto &show_disks = Config::getB("show_disks"); + auto &swap_disk = Config::getB("swap_disk"); + auto &mem = current_mem; + static const bool snapped = (getenv("BTOP_SNAPPED") != NULL); + + int mib[4]; + u_int memActive, memWire, cachedMem, freeMem; + size_t len; + + len = 4; sysctlnametomib("vm.stats.vm.v_active_count", mib, &len); + len = sizeof(memActive); + sysctl(mib, 4, &(memActive), &len, NULL, 0); + memActive *= Shared::pageSize; + + len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", mib, &len); + len = sizeof(memWire); + sysctl(mib, 4, &(memWire), &len, NULL, 0); + memWire *= Shared::pageSize; + + mem.stats.at("used") = memWire + memActive; + mem.stats.at("available") = Shared::totalMem - memActive - memWire; + + len = sizeof(cachedMem); + len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", mib, &len); + sysctl(mib, 4, &(cachedMem), &len, NULL, 0); + cachedMem *= Shared::pageSize; + mem.stats.at("cached") = cachedMem; + + len = sizeof(freeMem); + len = 4; sysctlnametomib("vm.stats.vm.v_free_count", mib, &len); + sysctl(mib, 4, &(freeMem), &len, NULL, 0); + freeMem *= Shared::pageSize; + mem.stats.at("free") = freeMem; + + if (show_swap and mem.stats.at("swap_total") > 0) { + for (const auto &name : swap_names) { + mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / mem.stats.at("swap_total"))); + while (cmp_greater(mem.percent.at(name).size(), width * 2)) + mem.percent.at(name).pop_front(); + } + has_swap = true; + } else + has_swap = false; + //? Calculate percentages + for (const auto &name : mem_names) { + mem.percent.at(name).push_back(round((double)mem.stats.at(name) * 100 / Shared::totalMem)); + while (cmp_greater(mem.percent.at(name).size(), width * 2)) + mem.percent.at(name).pop_front(); + } + + if (show_disks) { + unordered_flat_map mapping; // keep mapping from device -> mountpoint, since IOKit doesn't give us the mountpoint + double uptime = system_uptime(); + auto &disks_filter = Config::getS("disks_filter"); + bool filter_exclude = false; + // auto &only_physical = Config::getB("only_physical"); + auto &disks = mem.disks; + vector filter; + if (not disks_filter.empty()) { + filter = ssplit(disks_filter); + if (filter.at(0).starts_with("exclude=")) { + filter_exclude = true; + filter.at(0) = filter.at(0).substr(8); + } + } + + struct statfs *stfs; + int count = getmntinfo(&stfs, MNT_WAIT); + vector found; + found.reserve(last_found.size()); + for (int i = 0; i < count; i++) { + auto fstype = string(stfs[i].f_fstypename); + if (fstype == "autofs" || fstype == "devfs" || fstype == "linprocfs" || fstype == "procfs" || fstype == "tmpfs" || fstype == "linsysfs" || + fstype == "fdesckfs") { + // in memory filesystems -> not useful to show + continue; + } + + std::error_code ec; + string mountpoint = stfs[i].f_mntonname; + string dev = stfs[i].f_mntfromname; + mapping[dev] = mountpoint; + + //? Match filter if not empty + if (not filter.empty()) { + bool match = v_contains(filter, mountpoint); + if ((filter_exclude and match) or (not filter_exclude and not match)) + continue; + } + + found.push_back(mountpoint); + if (not disks.contains(mountpoint)) { + disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename()}; + + if (disks.at(mountpoint).dev.empty()) + disks.at(mountpoint).dev = dev; + + if (disks.at(mountpoint).name.empty()) + disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); + } + + + if (not v_contains(last_found, mountpoint)) + redraw = true; + + disks.at(mountpoint).free = stfs[i].f_bfree; + disks.at(mountpoint).total = stfs[i].f_iosize; + } + + //? Remove disks no longer mounted or filtered out + if (swap_disk and has_swap) found.push_back("swap"); + for (auto it = disks.begin(); it != disks.end();) { + if (not v_contains(found, it->first)) + it = disks.erase(it); + else + it++; + } + if (found.size() != last_found.size()) redraw = true; + last_found = std::move(found); + + //? Get disk/partition stats + for (auto &[mountpoint, disk] : disks) { + if (std::error_code ec; not fs::exists(mountpoint, ec)) + continue; + struct statvfs vfs; + if (statvfs(mountpoint.c_str(), &vfs) < 0) { + Logger::warning("Failed to get disk/partition stats with statvfs() for: " + mountpoint); + continue; + } + disk.total = vfs.f_blocks * vfs.f_frsize; + disk.free = vfs.f_bfree * vfs.f_frsize; + disk.used = disk.total - disk.free; + disk.used_percent = round((double)disk.used * 100 / disk.total); + disk.free_percent = 100 - disk.used_percent; + } + + //? Setup disks order in UI and add swap if enabled + mem.disks_order.clear(); + if (snapped and disks.contains("/mnt")) + mem.disks_order.push_back("/mnt"); + else if (disks.contains("/")) + mem.disks_order.push_back("/"); + if (swap_disk and has_swap) { + mem.disks_order.push_back("swap"); + if (not disks.contains("swap")) + disks["swap"] = {"", "swap"}; + disks.at("swap").total = mem.stats.at("swap_total"); + disks.at("swap").used = mem.stats.at("swap_used"); + disks.at("swap").free = mem.stats.at("swap_free"); + disks.at("swap").used_percent = mem.percent.at("swap_used").back(); + disks.at("swap").free_percent = mem.percent.at("swap_free").back(); + } + for (const auto &name : last_found) + if (not is_in(name, "/", "swap", "/dev")) + mem.disks_order.push_back(name); + + disk_ios = 0; + collect_disk(disks, mapping); + + old_uptime = uptime; + } + return mem; + } + +} // namespace Mem + +namespace Net { + unordered_flat_map current_net; + net_info empty_net = {}; + vector interfaces; + string selected_iface; + int errors = 0; + unordered_flat_map graph_max = {{"download", {}}, {"upload", {}}}; + unordered_flat_map> max_count = {{"download", {}}, {"upload", {}}}; + bool rescale = true; + uint64_t timestamp = 0; + + //* RAII wrapper for getifaddrs + class getifaddr_wrapper { + struct ifaddrs *ifaddr; + + public: + int status; + getifaddr_wrapper() { status = getifaddrs(&ifaddr); } + ~getifaddr_wrapper() { freeifaddrs(ifaddr); } + auto operator()() -> struct ifaddrs * { return ifaddr; } + }; + + auto collect(const bool no_update) -> net_info & { + auto &net = current_net; + auto &config_iface = Config::getS("net_iface"); + auto &net_sync = Config::getB("net_sync"); + auto &net_auto = Config::getB("net_auto"); + auto new_timestamp = time_ms(); + + if (not no_update and errors < 3) { + //? Get interface list using getifaddrs() wrapper + getifaddr_wrapper if_wrap{}; + if (if_wrap.status != 0) { + errors++; + Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_wrap.status)); + redraw = true; + return empty_net; + } + int family = 0; + char ip[NI_MAXHOST]; + interfaces.clear(); + string ipv4, ipv6; + + //? Iteration over all items in getifaddrs() list + for (auto *ifa = if_wrap(); ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) continue; + family = ifa->ifa_addr->sa_family; + const auto &iface = ifa->ifa_name; + //? Get IPv4 address + if (family == AF_INET) { + if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) + net[iface].ipv4 = ip; + } + //? Get IPv6 address + // else if (family == AF_INET6) { + // if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) + // net[iface].ipv6 = ip; + // } + + //? Update available interfaces vector and get status of interface + if (not v_contains(interfaces, iface)) { + interfaces.push_back(iface); + net[iface].connected = (ifa->ifa_flags & IFF_RUNNING); + } + } + + unordered_flat_map> ifstats; + int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; + size_t len; + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { + Logger::error("failed getting network interfaces"); + } else { + std::unique_ptr buf(new char[len]); + if (sysctl(mib, 6, buf.get(), &len, NULL, 0) < 0) { + Logger::error("failed getting network interfaces"); + } else { + char *lim = buf.get() + len; + char *next = NULL; + for (next = buf.get(); next < lim;) { + struct if_msghdr *ifm = (struct if_msghdr *)next; + next += ifm->ifm_msglen; + struct if_data ifm_data = ifm->ifm_data; + if (ifm->ifm_addrs & RTA_IFP) { + struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifm + 1); + char iface[32]; + strncpy(iface, sdl->sdl_data, sdl->sdl_nlen); + iface[sdl->sdl_nlen] = 0; + ifstats[iface] = std::tuple(ifm_data.ifi_ibytes, ifm_data.ifi_obytes); + } + } + } + } + + //? Get total recieved and transmitted bytes + device address if no ip was found + for (const auto &iface : interfaces) { + for (const string dir : {"download", "upload"}) { + auto &saved_stat = net.at(iface).stat.at(dir); + auto &bandwidth = net.at(iface).bandwidth.at(dir); + auto dirval = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); + uint64_t val = saved_stat.last; + try { + val = max(dirval, val); + } catch (const std::invalid_argument &) { + } catch (const std::out_of_range &) { + } + + //? Update speed, total and top values + saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); + if (saved_stat.speed > saved_stat.top) saved_stat.top = saved_stat.speed; + if (saved_stat.offset > val) saved_stat.offset = 0; + saved_stat.total = val - saved_stat.offset; + saved_stat.last = val; + + //? Add values to graph + bandwidth.push_back(saved_stat.speed); + while (cmp_greater(bandwidth.size(), width * 2)) bandwidth.pop_front(); + + //? Set counters for auto scaling + if (net_auto and selected_iface == iface) { + if (saved_stat.speed > graph_max[dir]) { + ++max_count[dir][0]; + if (max_count[dir][1] > 0) --max_count[dir][1]; + } else if (graph_max[dir] > 10 << 10 and saved_stat.speed < graph_max[dir] / 10) { + ++max_count[dir][1]; + if (max_count[dir][0] > 0) --max_count[dir][0]; + } + } + } + } + + //? Clean up net map if needed + if (net.size() > interfaces.size()) { + for (auto it = net.begin(); it != net.end();) { + if (not v_contains(interfaces, it->first)) + it = net.erase(it); + else + it++; + } + net.compact(); + } + + timestamp = new_timestamp; + } + //? Return empty net_info struct if no interfaces was found + if (net.empty()) + return empty_net; + + //? Find an interface to display if selected isn't set or valid + if (selected_iface.empty() or not v_contains(interfaces, selected_iface)) { + max_count["download"][0] = max_count["download"][1] = max_count["upload"][0] = max_count["upload"][1] = 0; + redraw = true; + if (net_auto) rescale = true; + if (not config_iface.empty() and v_contains(interfaces, config_iface)) + selected_iface = config_iface; + else { + //? Sort interfaces by total upload + download bytes + auto sorted_interfaces = interfaces; + rng::sort(sorted_interfaces, [&](const auto &a, const auto &b) { + return cmp_greater(net.at(a).stat["download"].total + net.at(a).stat["upload"].total, + net.at(b).stat["download"].total + net.at(b).stat["upload"].total); + }); + selected_iface.clear(); + //? Try to set to a connected interface + for (const auto &iface : sorted_interfaces) { + if (net.at(iface).connected) selected_iface = iface; + break; + } + //? If no interface is connected set to first available + if (selected_iface.empty() and not sorted_interfaces.empty()) + selected_iface = sorted_interfaces.at(0); + else if (sorted_interfaces.empty()) + return empty_net; + } + } + + //? Calculate max scale for graphs if needed + if (net_auto) { + bool sync = false; + for (const auto &dir : {"download", "upload"}) { + for (const auto &sel : {0, 1}) { + if (rescale or max_count[dir][sel] >= 5) { + const uint64_t avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 + ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0) / 5 + : net[selected_iface].stat[dir].speed); + graph_max[dir] = max(uint64_t(avg_speed * (sel == 0 ? 1.3 : 3.0)), (uint64_t)10 << 10); + max_count[dir][0] = max_count[dir][1] = 0; + redraw = true; + if (net_sync) sync = true; + break; + } + } + //? Sync download/upload graphs if enabled + if (sync) { + const auto other = (string(dir) == "upload" ? "download" : "upload"); + graph_max[other] = graph_max[dir]; + max_count[other][0] = max_count[other][1] = 0; + break; + } + } + } + + rescale = false; + return net.at(selected_iface); + } +} // namespace Net + +namespace Proc { + + vector current_procs; + unordered_flat_map uid_user; + string current_sort; + string current_filter; + bool current_rev = false; + + fs::file_time_type passwd_time; + + uint64_t cputimes; + int collapse = -1, expand = -1; + uint64_t old_cputimes = 0; + atomic numpids = 0; + int filter_found = 0; + + detail_container detailed; + + //* Generate process tree list + void _tree_gen(proc_info &cur_proc, vector &in_procs, vector> &out_procs, int cur_depth, const bool collapsed, const string &filter, bool found = false, const bool no_update = false, const bool should_filter = false) { + auto cur_pos = out_procs.size(); + bool filtering = false; + + //? If filtering, include children of matching processes + if (not found and (should_filter or not filter.empty())) { + if (not s_contains(std::to_string(cur_proc.pid), filter) and not s_contains(cur_proc.name, filter) and not s_contains(cur_proc.cmd, filter) and not s_contains(cur_proc.user, filter)) { + filtering = true; + cur_proc.filtered = true; + filter_found++; + } else { + found = true; + cur_depth = 0; + } + } else if (cur_proc.filtered) + cur_proc.filtered = false; + + //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree + if (not collapsed and not filtering) { + out_procs.push_back(std::ref(cur_proc)); + cur_proc.tree_index = out_procs.size() - 1; + //? Try to find name of the binary file and append to program name if not the same + if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { + std::string_view cmd_view = cur_proc.cmd; + cmd_view = cmd_view.substr((size_t)0, min(cmd_view.find(' '), cmd_view.size())); + cmd_view = cmd_view.substr(min(cmd_view.find_last_of('/') + 1, cmd_view.size())); + cur_proc.short_cmd = (string)cmd_view; + } + } else { + cur_proc.tree_index = in_procs.size(); + } + + //? Recursive iteration over all children + int children = 0; + for (auto &p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { + if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { + out_procs.back().get().cpu_p += p.cpu_p; + out_procs.back().get().mem += p.mem; + out_procs.back().get().threads += p.threads; + filter_found++; + } + if (collapsed and not filtering) { + cur_proc.filtered = true; + } else + children++; + _tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cur_proc.collapsed), filter, found, no_update, should_filter); + } + if (collapsed or filtering) + return; + + //? Add tree terminator symbol if it's the last child in a sub-tree + if (out_procs.size() > cur_pos + 1 and not out_procs.back().get().prefix.ends_with("]─")) + out_procs.back().get().prefix.replace(out_procs.back().get().prefix.size() - 8, 8, " └─ "); + + //? Add collapse/expand symbols if process have any children + out_procs.at(cur_pos).get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); + } + + string get_status(char s) { + if (s & SRUN) return "Running"; + if (s & SSLEEP) return "Sleeping"; + if (s & SIDL) return "Idle"; + if (s & SSTOP) return "Stopped"; + if (s & SZOMB) return "Zombie"; + return "Unknown"; + } + + //* Get detailed info for selected process + void _collect_details(const size_t pid, vector &procs) { + if (pid != detailed.last_pid) { + detailed = {}; + detailed.last_pid = pid; + detailed.skip_smaps = not Config::getB("proc_info_smaps"); + } + + //? Copy proc_info for process from proc vector + auto p_info = rng::find(procs, pid, &proc_info::pid); + detailed.entry = *p_info; + + //? Update cpu percent deque for process cpu graph + if (not Config::getB("proc_per_core")) detailed.entry.cpu_p *= Shared::coreCount; + detailed.cpu_percent.push_back(clamp((long long)round(detailed.entry.cpu_p), 0ll, 100ll)); + while (cmp_greater(detailed.cpu_percent.size(), width)) detailed.cpu_percent.pop_front(); + + //? Process runtime : current time - start time (both in unix time - seconds since epoch) + struct timeval currentTime; + gettimeofday(¤tTime, NULL); + detailed.elapsed = sec_to_dhms(currentTime.tv_sec - detailed.entry.cpu_s); // only interested in second granularity, so ignoring tc_usec + if (detailed.elapsed.size() > 8) detailed.elapsed.resize(detailed.elapsed.size() - 3); + + //? Get parent process name + if (detailed.parent.empty()) { + auto p_entry = rng::find(procs, detailed.entry.ppid, &proc_info::pid); + if (p_entry != procs.end()) detailed.parent = p_entry->name; + } + + //? Expand process status from single char to explanative string + detailed.status = get_status(detailed.entry.state); + + detailed.mem_bytes.push_back(detailed.entry.mem); + detailed.memory = floating_humanizer(detailed.entry.mem); + + if (detailed.first_mem == -1 or detailed.first_mem < detailed.mem_bytes.back() / 2 or detailed.first_mem > detailed.mem_bytes.back() * 4) { + detailed.first_mem = min((uint64_t)detailed.mem_bytes.back() * 2, Mem::get_totalMem()); + redraw = true; + } + + while (cmp_greater(detailed.mem_bytes.size(), width)) detailed.mem_bytes.pop_front(); + + // rusage_info_current rusage; + // if (proc_pid_rusage(pid, RUSAGE_INFO_CURRENT, (void **)&rusage) == 0) { + // // this fails for processes we don't own - same as in Linux + // detailed.io_read = floating_humanizer(rusage.ri_diskio_bytesread); + // detailed.io_write = floating_humanizer(rusage.ri_diskio_byteswritten); + // } + } + + //* RAII wrapper for kvm_openfiles + class kvm_openfiles_wrapper { + kvm_t* kd = NULL; + public: + kvm_openfiles_wrapper(const char* execf, const char* coref, const char* swapf, int flags, char* err) { + this->kd = kvm_openfiles(execf, coref, swapf, flags, err); + } + ~kvm_openfiles_wrapper() { kvm_close(kd); } + auto operator()() -> kvm_t* { return kd; } + }; + + //* Collects and sorts process information from /proc + auto collect(const bool no_update) -> vector & { + const auto &sorting = Config::getS("proc_sorting"); + const auto &reverse = Config::getB("proc_reversed"); + const auto &filter = Config::getS("proc_filter"); + const auto &per_core = Config::getB("proc_per_core"); + const auto &tree = Config::getB("proc_tree"); + const auto &show_detailed = Config::getB("show_detailed"); + const size_t detailed_pid = Config::getI("detailed_pid"); + bool should_filter = current_filter != filter; + if (should_filter) current_filter = filter; + const bool sorted_change = (sorting != current_sort or reverse != current_rev or should_filter); + if (sorted_change) { + current_sort = sorting; + current_rev = reverse; + } + + const int cmult = (per_core) ? Shared::coreCount : 1; + bool got_detailed = false; + + vector> cpu_time(Shared::coreCount); + size_t size = sizeof(long) * CPUSTATES * Shared::coreCount; + if (sysctlbyname("kern.cp_times", &cpu_time[0], &size, NULL, 0) == -1) { + Logger::error("failed to get CPU times"); + } + cputimes = 0; + for (const auto core : cpu_time) { + for (const unsigned int c_state : {CP_USER, CP_NICE, CP_SYS, CP_IDLE}) { + cputimes += core[c_state]; + } + } + + //* Use pids from last update if only changing filter, sorting or tree options + if (no_update and not current_procs.empty()) { + if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, current_procs); + } else { + //* ---------------------------------------------Collection start---------------------------------------------- + + should_filter = true; + vector found; + struct timeval currentTime; + gettimeofday(¤tTime, NULL); + const double timeNow = currentTime.tv_sec + (currentTime.tv_usec / 1'000'000); + + int count = 0; + char buf[_POSIX2_LINE_MAX]; + kvm_openfiles_wrapper kd(NULL, _PATH_DEVNULL, NULL, O_RDONLY, buf); + const struct kinfo_proc* kprocs = kvm_getprocs(kd(), KERN_PROC_PROC, 0, &count); + + for (int i = 0; i < count; i++) { + const struct kinfo_proc* kproc = &kprocs[i]; + const size_t pid = (size_t)kproc->ki_pid; + if (pid < 1) continue; + found.push_back(pid); + + //? Check if pid already exists in current_procs + bool no_cache = false; + auto find_old = rng::find(current_procs, pid, &proc_info::pid); + if (find_old == current_procs.end()) { + current_procs.push_back({pid}); + find_old = current_procs.end() - 1; + no_cache = true; + } + + auto &new_proc = *find_old; + + //? Get program name, command, username, parent pid, nice and status + if (no_cache) { + if (kproc->ki_comm == NULL or kproc->ki_comm == "idle"s) { + current_procs.pop_back(); + continue; + } + new_proc.name = kproc->ki_comm; + char** argv = kvm_getargv(kd(), kproc, 0); + if (argv) { + for (int i = 0; argv[i]; i++) { + new_proc.cmd += argv[i] + " "s; + } + if (not new_proc.cmd.empty()) new_proc.cmd.pop_back(); + } + if (new_proc.cmd.empty()) new_proc.cmd = new_proc.name; + new_proc.ppid = kproc->ki_ppid; + new_proc.cpu_s = round(kproc->ki_start.tv_sec); + struct passwd *pwd = getpwuid(kproc->ki_uid); + if (pwd) + new_proc.user = pwd->pw_name; + } + new_proc.p_nice = kproc->ki_nice; + new_proc.state = kproc->ki_stat; + + int cpu_t = 0; + cpu_t = kproc->ki_rusage.ru_utime.tv_sec * 1'000'000 + kproc->ki_rusage.ru_utime.tv_usec + + kproc->ki_rusage.ru_stime.tv_sec * 1'000'000 + kproc->ki_rusage.ru_stime.tv_usec; + + new_proc.mem = kproc->ki_rssize * Shared::pageSize; + new_proc.threads = kproc->ki_numthreads; + + //? Process cpu usage since last update + new_proc.cpu_p = clamp((100.0 * ((cpu_t - new_proc.cpu_t) / 1'000'000.0) / max((uint64_t)1, (cputimes - old_cputimes) * Shared::clkTck)) * cmult / 100'000.0, 0.0, 100.0 * Shared::coreCount); + + //? Process cumulative cpu usage since process start + new_proc.cpu_c = (double)(cpu_t * Shared::clkTck / 1'000'000) / max(1.0, timeNow - new_proc.cpu_s); + + //? Update cached value with latest cpu times + new_proc.cpu_t = cpu_t; + + if (show_detailed and not got_detailed and new_proc.pid == detailed_pid) { + got_detailed = true; + } + + // //? Clear dead processes from current_procs + auto eraser = rng::remove_if(current_procs, [&](const auto &element) { return not v_contains(found, element.pid); }); + current_procs.erase(eraser.begin(), eraser.end()); + + //? Update the details info box for process if active + if (show_detailed and got_detailed) { + _collect_details(detailed_pid, current_procs); + } else if (show_detailed and not got_detailed and detailed.status != "Dead") { + detailed.status = "Dead"; + redraw = true; + } + + old_cputimes = cputimes; + } + } + + //* ---------------------------------------------Collection done----------------------------------------------- + + //* Sort processes + if (sorted_change or not no_update) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::sort(current_procs, rng::greater{}, &proc_info::pid); break; + case 1: rng::sort(current_procs, rng::greater{}, &proc_info::name); break; + case 2: rng::sort(current_procs, rng::greater{}, &proc_info::cmd); break; + case 3: rng::sort(current_procs, rng::greater{}, &proc_info::threads); break; + case 4: rng::sort(current_procs, rng::greater{}, &proc_info::user); break; + case 5: rng::sort(current_procs, rng::greater{}, &proc_info::mem); break; + case 6: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + } + if (reverse) rng::reverse(current_procs); + + //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage + if (not tree and not reverse and sorting == "cpu lazy") { + double max = 10.0, target = 30.0; + for (size_t i = 0, x = 0, offset = 0; i < current_procs.size(); i++) { + if (i <= 5 and current_procs.at(i).cpu_p > max) + max = current_procs.at(i).cpu_p; + else if (i == 6) + target = (max > 30.0) ? max : 10.0; + if (i == offset and current_procs.at(i).cpu_p > 30.0) + offset++; + else if (current_procs.at(i).cpu_p > target) { + rotate(current_procs.begin() + offset, current_procs.begin() + i, current_procs.begin() + i + 1); + if (++x > 10) break; + } + } + } + } + + //* Match filter if defined + if (should_filter) { + filter_found = 0; + for (auto &p : current_procs) { + if (not tree and not filter.empty()) { + if (not s_contains(to_string(p.pid), filter) and not s_contains(p.name, filter) and not s_contains(p.cmd, filter) and not s_contains(p.user, filter)) { + p.filtered = true; + filter_found++; + } else { + p.filtered = false; + } + } else { + p.filtered = false; + } + } + } + + //* Generate tree view if enabled + if (tree and (not no_update or should_filter or sorted_change)) { + if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { + auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); + if (collapser != current_procs.end()) { + if (collapse == expand) { + collapser->collapsed = not collapser->collapsed; + } else if (collapse > -1) { + collapser->collapsed = true; + } else if (expand > -1) { + collapser->collapsed = false; + } + } + collapse = expand = -1; + } + if (should_filter or not filter.empty()) filter_found = 0; + + vector> tree_procs; + tree_procs.reserve(current_procs.size()); + + //? Stable sort to retain selected sorting among processes with the same parent + rng::stable_sort(current_procs, rng::less{}, &proc_info::ppid); + + //? Start recursive iteration over processes with the lowest shared parent pids + for (auto &p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { + _tree_gen(p, current_procs, tree_procs, 0, false, filter, false, no_update, should_filter); + } + + //? Final sort based on tree index + rng::sort(current_procs, rng::less{}, &proc_info::tree_index); + if (reverse) rng::reverse(current_procs); + } + + numpids = (int)current_procs.size() - filter_found; + return current_procs; + } +} // namespace Proc + +namespace Tools { + double system_uptime() { + struct timeval ts, currTime; + std::size_t len = sizeof(ts); + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + if (sysctl(mib, 2, &ts, &len, NULL, 0) != -1) { + gettimeofday(&currTime, NULL); + return currTime.tv_sec - ts.tv_sec; + } + return 0.0; + } +} // namespace Tools From 60223db2be9a0fb5405f0641e4a33f6246941d46 Mon Sep 17 00:00:00 2001 From: Marco Radocchia Date: Wed, 12 Jan 2022 11:34:14 +0100 Subject: [PATCH 162/289] Added theme gruvbox_material_dark --- themes/gruvbox_material_dark.theme | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/themes/gruvbox_material_dark.theme b/themes/gruvbox_material_dark.theme index 7133e3f..928cd4f 100644 --- a/themes/gruvbox_material_dark.theme +++ b/themes/gruvbox_material_dark.theme @@ -1,5 +1,5 @@ -#Bashtop gruvbox (https://github.com/morhetz/gruvbox) theme -#by BachoSeven +# Btop gruvbox material dark (https://github.com/sainnhe/gruvbox-material) theme +# by Marco Radocchia # Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" # example for white: "#FFFFFF", "#ff" or "255 255 255". @@ -58,35 +58,35 @@ theme[temp_end]="#ea6962" # CPU graph colors theme[cpu_start]="#a9b665" -theme[cpu_mid]="d8a657" +theme[cpu_mid]="#d8a657" theme[cpu_end]="#ea6962" # Mem/Disk free meter theme[free_start]="#89b482" theme[free_mid]="" -theme[free_end]="#89b482" +theme[free_end]="" # Mem/Disk cached meter theme[cached_start]="#7daea3" theme[cached_mid]="" -theme[cached_end]="#7daea3" +theme[cached_end]="" # Mem/Disk available meter theme[available_start]="#d8a657" theme[available_mid]="" -theme[available_end]="#d8a657" +theme[available_end]="" # Mem/Disk used meter theme[used_start]="#ea6962" theme[used_mid]="" -theme[used_end]="#ea6962" +theme[used_end]="2" # Download graph colors theme[download_start]="#e78a4e" theme[download_mid]="" -theme[download_end]="#e78a4e" +theme[download_end]="" # Upload graph colors theme[upload_start]="#d3869b" theme[upload_mid]="" -theme[upload_end]="#d3869b" +theme[upload_end]="" From 64cdb4434371adee47c497c961eb5a4b2f447a4d Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 12 Jan 2022 20:49:27 +0100 Subject: [PATCH 163/289] Fixed: Net speed rollover for 32-bit --- src/freebsd/btop_collect.cpp | 22 ++++++++++++---------- src/linux/btop_collect.cpp | 4 ++-- src/osx/btop_collect.cpp | 8 +------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index e913c79..8531762 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -758,7 +758,7 @@ namespace Mem { disk_ios = 0; collect_disk(disks, mapping); - + old_uptime = uptime; } return mem; @@ -864,19 +864,21 @@ namespace Net { for (const string dir : {"download", "upload"}) { auto &saved_stat = net.at(iface).stat.at(dir); auto &bandwidth = net.at(iface).bandwidth.at(dir); - auto dirval = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); - uint64_t val = saved_stat.last; - try { - val = max(dirval, val); - } catch (const std::invalid_argument &) { - } catch (const std::out_of_range &) { - } + uint64_t val = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); //? Update speed, total and top values + if (val < saved_stat.last) { + saved_stat.rollover += saved_stat.last; + saved_stat.last = 0; + } + if (cmp_greater((unsigned long long)saved_stat.rollover + (unsigned long long)val, numeric_limits::max())) { + saved_stat.rollover = 0; + saved_stat.last = 0; + } saved_stat.speed = round((double)(val - saved_stat.last) / ((double)(new_timestamp - timestamp) / 1000)); if (saved_stat.speed > saved_stat.top) saved_stat.top = saved_stat.speed; - if (saved_stat.offset > val) saved_stat.offset = 0; - saved_stat.total = val - saved_stat.offset; + if (saved_stat.offset > val + saved_stat.rollover) saved_stat.offset = 0; + saved_stat.total = (val + saved_stat.rollover) - saved_stat.offset; saved_stat.last = val; //? Add values to graph diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 4fe120d..79a6eac 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1097,8 +1097,8 @@ namespace Net { auto& saved_stat = net.at(iface).stat.at(dir); auto& bandwidth = net.at(iface).bandwidth.at(dir); - uint64_t val = saved_stat.last; - try { val = max((uint64_t)stoull(readfile(sys_file, "0")), val); } + uint64_t val = 0; + try { val = (uint64_t)stoull(readfile(sys_file, "0")); } catch (const std::invalid_argument&) {} catch (const std::out_of_range&) {} diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 5537d75..2451ea6 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -918,13 +918,7 @@ namespace Net { for (const string dir : {"download", "upload"}) { auto &saved_stat = net.at(iface).stat.at(dir); auto &bandwidth = net.at(iface).bandwidth.at(dir); - auto dirval = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); - uint64_t val = saved_stat.last; - try { - val = max(dirval, val); - } catch (const std::invalid_argument &) { - } catch (const std::out_of_range &) { - } + uint64_t val = dir == "download" ? std::get<0>(ifstats[iface]) : std::get<1>(ifstats[iface]); //? Update speed, total and top values if (val < saved_stat.last) { From fcc247bc1acfab67c1d7f23a5449dc9f729f35bb Mon Sep 17 00:00:00 2001 From: "Jakob P. Liljenberg" Date: Thu, 13 Jan 2022 07:52:34 +0100 Subject: [PATCH 164/289] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index faa7b5e..3c937d1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,6 +7,10 @@ assignees: aristocratos --- +**Read the README.md and search for similar issues before posting a bug report!** + +Any bug that can be solved by just reading the [prerequisites](https://github.com/aristocratos/btop#prerequisites) section of the README will likely be ignored. + **Describe the bug** [A clear and concise description of what the bug is.] From 0c18393ff32a7aeb80463f0d5f2ec995eb4430ab Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 16 Jan 2022 12:43:24 +0100 Subject: [PATCH 165/289] Changed: process-per-core defaults to false --- src/btop_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index c9a5a42..37e7d9c 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -212,7 +212,7 @@ namespace Config { {"proc_tree", false}, {"proc_colors", true}, {"proc_gradient", true}, - {"proc_per_core", true}, + {"proc_per_core", false}, {"proc_mem_bytes", true}, {"proc_info_smaps", false}, {"proc_left", false}, From f46989ad35803103e1554063194cf2f6c1969e49 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 16 Jan 2022 12:45:27 +0100 Subject: [PATCH 166/289] Fixed (freebsd): Process cpu usage, sorting and warnings --- src/freebsd/btop_collect.cpp | 46 ++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 8531762..028dbe3 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -111,7 +111,7 @@ namespace Shared { fs::path passwd_path; uint64_t totalMem; long pageSize, clkTck, coreCount, physicalCoreCount, arg_max; - int totalMem_len; + int totalMem_len, kfscale; long bootTime; void init() { @@ -154,6 +154,11 @@ namespace Shared { bootTime = result.tv_sec; } + size = sizeof(kfscale); + if (sysctlbyname("kern.fscale", &kfscale, &size, NULL, 0) == -1) { + kfscale = 2048; + } + //* Get maximum length of process arguments arg_max = sysconf(_SC_ARG_MAX); @@ -567,7 +572,7 @@ namespace Mem { char buf[512]; size_t len = 512; while (not std::feof(f())) { - uint64_t nread, nwritten; + uint64_t nread = 0, nwritten = 0; if (fgets(buf, len, f())) { char *name = std::strtok(buf, ": \n"); char *value = std::strtok(NULL, ": \n"); @@ -1219,7 +1224,7 @@ namespace Proc { new_proc.threads = kproc->ki_numthreads; //? Process cpu usage since last update - new_proc.cpu_p = clamp((100.0 * ((cpu_t - new_proc.cpu_t) / 1'000'000.0) / max((uint64_t)1, (cputimes - old_cputimes) * Shared::clkTck)) * cmult / 100'000.0, 0.0, 100.0 * Shared::coreCount); + new_proc.cpu_p = clamp((100.0 * kproc->ki_pctcpu / Shared::kfscale) * cmult, 0.0, 100.0 * Shared::coreCount); //? Process cumulative cpu usage since process start new_proc.cpu_c = (double)(cpu_t * Shared::clkTck / 1'000'000) / max(1.0, timeNow - new_proc.cpu_s); @@ -1251,17 +1256,29 @@ namespace Proc { //* Sort processes if (sorted_change or not no_update) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + if (reverse) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; + } + } else { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; + case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; + case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; + case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; + case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; + case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; + case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; + } } - if (reverse) rng::reverse(current_procs); //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage if (not tree and not reverse and sorting == "cpu lazy") { @@ -1327,8 +1344,7 @@ namespace Proc { } //? Final sort based on tree index - rng::sort(current_procs, rng::less{}, &proc_info::tree_index); - if (reverse) rng::reverse(current_procs); + rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); } numpids = (int)current_procs.size() - filter_found; From 989427ff3a3f5be9f628da4bfa76c71f4b8a1021 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 16 Jan 2022 13:39:50 +0100 Subject: [PATCH 167/289] Added: Option for base 10 bytes/bits --- src/btop_config.cpp | 3 +++ src/btop_menu.cpp | 11 +++++++++++ src/btop_tools.cpp | 36 ++++++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 37e7d9c..1883dfa 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -123,6 +123,8 @@ namespace Config { {"temp_scale", "#* Which temperature scale to use, available values: \"celsius\", \"fahrenheit\", \"kelvin\" and \"rankine\"."}, + {"base_10_sizes", "#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024."}, + {"show_cpu_freq", "#* Show CPU frequency."}, {"clock_format", "#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.\n" @@ -233,6 +235,7 @@ namespace Config { {"use_fstab", true}, {"show_io_stat", true}, {"io_mode", false}, + {"base_10_sizes", false}, {"io_graph_combined", false}, {"net_auto", true}, {"net_sync", false}, diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index c526521..3fb24bf 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -257,6 +257,14 @@ namespace Menu { "\"%H\" = 24h hour, \"%I\" = 12h hour", "\"%M\" = minute, \"%S\" = second", "\"%d\" = day, \"%m\" = month, \"%y\" = year"}, + {"base_10_sizes", + "Use base 10 for bits and bytes sizes.", + "", + "Uses KB = 1000 instead of KiB = 1024,", + "MB = 1000KB instead of MiB = 1024KiB,", + "and so on.", + "", + "True or False."}, {"background_update", "Update main ui when menus are showing.", "", @@ -1134,6 +1142,9 @@ namespace Menu { else if (option == "background_update") { Runner::pause_output = false; } + else if (option == "base_10_sizes") { + recollect = true; + } } else if (selPred.test(isBrowseable)) { auto& optList = optionsList.at(option).get(); diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index b7e80da..1f0f49b 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -32,6 +32,7 @@ tab-size = 4 #include #include +#include using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map; namespace fs = std::filesystem; @@ -288,23 +289,38 @@ namespace Tools { string floating_humanizer(uint64_t value, const bool shorten, size_t start, const bool bit, const bool per_second) { string out; const size_t mult = (bit) ? 8 : 1; - static const array Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"}; - static const array Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"}; - const auto& units = (bit) ? Units_bit : Units_byte; + const bool mega = Config::getB("base_10_sizes"); + static const array mebiUnits_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"}; + static const array mebiUnits_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"}; + static const array megaUnits_bit = {"bit", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb", "Bb", "Gb"}; + static const array megaUnits_byte = {"Byte", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB", "GB"}; + const auto& units = (bit) ? ( mega ? megaUnits_bit : mebiUnits_bit) : ( mega ? megaUnits_byte : mebiUnits_byte); value *= 100 * mult; - while (value >= 102400) { - value >>= 10; - if (value < 100) { - out = to_string(value); - break; + if (mega) { + while (value >= 100000) { + value /= 1000; + if (value < 100) { + out = to_string(value); + break; + } + start++; + } + } + else { + while (value >= 102400) { + value >>= 10; + if (value < 100) { + out = to_string(value); + break; + } + start++; } - start++; } if (out.empty()) { out = to_string(value); - if (out.size() == 4 and start > 0) { out.pop_back(); out.insert(2, ".");} + if (not mega and out.size() == 4 and start > 0) { out.pop_back(); out.insert(2, ".");} else if (out.size() == 3 and start > 0) out.insert(1, "."); else if (out.size() >= 2) out.resize(out.size() - 2); } From 22061fa627e3bab2f0f59cdcc3fbe498baa51c1e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 16 Jan 2022 14:19:31 +0100 Subject: [PATCH 168/289] v1.2.0 FreeBSD Support --- CHANGELOG.md | 14 ++++++++ Makefile | 2 +- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/btop.cpp | 9 +++-- 4 files changed, 110 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5b6797..004c8c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.2.0 + +* Added: Support for FreeBSD, by @joske and @aristocratos + +* Fixed (again): Account for system rolling over net speeds in Net::collect() + +* Added: Theme gruvbox_material_dark, by @marcoradocchia + +* Added: Option for base 10 bytes/bits + +## v1.1.5 + +* Fixed: Account for system rolling over net speeds in Net::collect() + ## v1.1.4 * Fixed: Create dependency files in build directory when compiling, by @stwnt diff --git a/Makefile b/Makefile index f844c21..a3e743f 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ ifeq ($(PLATFORM_LC),linux) else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) - SU_GROUP := root + SU_GROUP := wheel override ADDFLAGS += -lstdc++ -lm -lkvm -ldevstat -Wl,-rpath=/usr/local/lib/gcc11 export MAKE = gmake else ifeq ($(PLATFORM_LC),macos) diff --git a/README.md b/README.md index 7450962..483adaa 100644 --- a/README.md +++ b/README.md @@ -31,13 +31,20 @@ * [Installation Linux/OSX](#installation) * [Compilation Linux](#compilation-linux) * [Compilation OSX](#compilation-osx) +* [Compilation FreeBSD](#compilation-freebsd) * [Installing the snap](#installing-the-snap) * [Configurability](#configurability) * [License](#license) ## News -### Under development +##### 16 January 2022 + +Release v1.2.0 with FreeBSD support. No release binaries for FreeBSD provided as of yet. + +Again a big thanks to [@joske](https://github.com/joske) for his porting efforts! + +Since compatibility with Linux, MacOS and FreeBSD are done, the focus going forward will be on new features like GPU monitoring. ##### 13 November 2021 @@ -460,6 +467,89 @@ Also needs a UTF8 locale and a font that covers: gmake help ``` +## Compilation FreeBSD + + Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary). + + Note that GNU make (`gmake`) is required to compile on FreeBSD. + +1. **Install dependencies** + + ``` bash + sudo pkg install gmake gcc11 coreutils git + ``` + +2. **Clone repository** + + ``` bash + git clone https://github.com/aristocratos/btop.git + cd btop + ``` + +3. **Compile** + + Append `STATIC=true` to `make` command for static compilation. + + Append `QUIET=true` for less verbose output. + + Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). + + Append `ARCH=` to manually set the target architecture. + If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. + + Use `ADDFLAGS` variable for appending flags to both compiler and linker. + + For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + + ``` bash + gmake + ``` + +4. **Install** + + Append `PREFIX=/target/dir` to set target, default: `/usr/local` + + Notice! Only use "sudo" when installing to a NON user owned directory. + + ``` bash + sudo gmake install + ``` + +5. **(Recommended) Set suid bit to make btop always run as root (or other user)** + + No need for `sudo` to see information for non user owned processes and to enable signal sending to any process. + + Run after make install and use same PREFIX if any was used at install. + + Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `wheel` + + ``` bash + sudo gmake setuid + ``` + +* **Uninstall** + + ``` bash + sudo gmake uninstall + ``` + +* **Remove any object files from source dir** + + ```bash + gmake clean + ``` + +* **Remove all object files, binaries and created directories in source dir** + + ```bash + gmake distclean + ``` + +* **Show help** + + ```bash + gmake help + ``` ## Installing the snap [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop) diff --git a/src/btop.cpp b/src/btop.cpp index 6bf3ff4..02367d2 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -20,7 +20,7 @@ tab-size = 4 #include #include #ifdef __FreeBSD__ -#include + #include #endif #include #include @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.1.4"; + const string Version = "1.2.0"; int coreCount; string overlay; @@ -209,14 +209,14 @@ void clean_quit(int sig) { if (Global::_runner_started) { #ifdef __APPLE__ if (pthread_join(Runner::runner_id, NULL) != 0) { - Logger::error("Failed to join _runner thread!"); + Logger::warning("Failed to join _runner thread on exit!"); pthread_cancel(Runner::runner_id); } #else struct timespec ts; ts.tv_sec = 5; if (pthread_timedjoin_np(Runner::runner_id, NULL, &ts) != 0) { - Logger::error("Failed to join _runner thread!"); + Logger::warning("Failed to join _runner thread on exit!"); pthread_cancel(Runner::runner_id); } #endif @@ -243,7 +243,6 @@ void clean_quit(int sig) { const auto excode = (sig != -1 ? sig : 0); - //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor #ifdef __APPLE__ _Exit(excode); #else From 53d2c6ebe38dccac7ab93c1b6b13ff0ae61069a8 Mon Sep 17 00:00:00 2001 From: "Jakob P. Liljenberg" Date: Sat, 29 Jan 2022 10:59:27 +0100 Subject: [PATCH 169/289] Fixed: bad value for theme[used_end] --- themes/gruvbox_material_dark.theme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/gruvbox_material_dark.theme b/themes/gruvbox_material_dark.theme index 928cd4f..749c7a7 100644 --- a/themes/gruvbox_material_dark.theme +++ b/themes/gruvbox_material_dark.theme @@ -79,7 +79,7 @@ theme[available_end]="" # Mem/Disk used meter theme[used_start]="#ea6962" theme[used_mid]="" -theme[used_end]="2" +theme[used_end]="" # Download graph colors theme[download_start]="#e78a4e" From f033c57be5f0117f342c11243cab4199ea626590 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 31 Jan 2022 17:04:13 +0100 Subject: [PATCH 170/289] README: Update openSUSE install section The package is available in the official default repos for Tumbleweed. For Leap, the package is available in the development repository. Linking to the generic page, which has the current information - independent of distro releases and package submissions. The user's repository is obsolete/not necessary any more. --- README.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c7844ff..dbdb414 100644 --- a/README.md +++ b/README.md @@ -269,18 +269,12 @@ Also needs a UTF8 locale and a font that covers: **Binary release (from native os repo)** * **openSUSE** - * **Add repo** - ```bash - sudo zypper ar --refresh obs://home:Werwolf2517 home:Werwolf2517 - ``` - * **Refresh metadata** - ```bash - sudo zypper ref - ``` - * **Install package** - ```bash - sudo zypper in btop - ``` + * **Tumbleweed:** + ```bash + sudo zypper in btop + ``` + * For all other versions, see [openSUSE Software: btop](https://software.opensuse.org/package/btop) + **Binary release on Homebrew (macOS (x86_64 & ARM64) / Linux (x86_64))** From 4c5e48c6a80419923e1d50b7b1b83b5a2a7a5911 Mon Sep 17 00:00:00 2001 From: NavigationHazard Date: Sun, 6 Feb 2022 18:29:33 +0100 Subject: [PATCH 171/289] Added Request https://github.com/aristocratos/btop/issues/234 --- src/btop_input.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 39fbd8a..f83dcf0 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -294,6 +294,10 @@ namespace Input { Config::set("proc_filtering", false); old_filter.clear(); } + else if (key == "down") { + Config::set("proc_filter", Proc::filter.text); + Config::set("proc_filtering", false); + } else if (key == "escape" or key == "mouse_click") { Config::set("proc_filter", old_filter); Config::set("proc_filtering", false); From 079052081818b29f4d700067e7a2b0e1834109fb Mon Sep 17 00:00:00 2001 From: NavigationHazard Date: Sun, 6 Feb 2022 18:32:35 +0100 Subject: [PATCH 172/289] Added Request - Arrow only after use of "f" in Process search --- src/btop_input.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index f83dcf0..ca4e085 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -297,6 +297,7 @@ namespace Input { else if (key == "down") { Config::set("proc_filter", Proc::filter.text); Config::set("proc_filtering", false); + old_filter.clear(); } else if (key == "escape" or key == "mouse_click") { Config::set("proc_filter", old_filter); From eebcb08e49d7204dd91a8e459a3825e50ce89676 Mon Sep 17 00:00:00 2001 From: NavigationHazard Date: Tue, 8 Feb 2022 01:24:28 +0100 Subject: [PATCH 173/289] Best of Both Worlds. Both ways are workings now. Using enter and then moving with arrows or just using arrow down. --- src/btop_input.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index ca4e085..273990d 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -292,13 +292,14 @@ namespace Input { if (key == "enter") { Config::set("proc_filter", Proc::filter.text); Config::set("proc_filtering", false); - old_filter.clear(); - } + old_filter.clear(); + } else if (key == "down") { - Config::set("proc_filter", Proc::filter.text); + Config::set("proc_filter", Proc::filter.text); Config::set("proc_filtering", false); old_filter.clear(); - } + process("down"); + } else if (key == "escape" or key == "mouse_click") { Config::set("proc_filter", old_filter); Config::set("proc_filtering", false); From 3887389e0ac813451592bab0f60dfacab2f1381e Mon Sep 17 00:00:00 2001 From: NavigationHazard Date: Tue, 8 Feb 2022 10:36:21 +0100 Subject: [PATCH 174/289] Added or and if statement --- src/btop_input.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 273990d..14cbbe3 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -289,17 +289,15 @@ namespace Input { bool no_update = true; bool redraw = true; if (filtering) { - if (key == "enter") { + if (key == "enter" or key == "down") { Config::set("proc_filter", Proc::filter.text); Config::set("proc_filtering", false); old_filter.clear(); + if(key == "down"){ + process("down"); + return; + } } - else if (key == "down") { - Config::set("proc_filter", Proc::filter.text); - Config::set("proc_filtering", false); - old_filter.clear(); - process("down"); - } else if (key == "escape" or key == "mouse_click") { Config::set("proc_filter", old_filter); Config::set("proc_filtering", false); From 3b9144dff32b4ec59a490cf2dc090a46ce5fe583 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 15:38:05 +0100 Subject: [PATCH 175/289] Fixed: Fx::uncolor not removing all escapes --- src/btop_tools.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 1f0f49b..f48584e 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -143,16 +143,19 @@ namespace Term { namespace Fx { string uncolor(const string& s) { string out = s; - for (size_t offset = 0, start_pos = 0, end_pos = 0, next_pos = 0;;) { - if ((start_pos = next_pos > 0 ? next_pos : out.find('\x1b', offset)) == string::npos) + for (size_t offset = 0, start_pos = 0, end_pos = 0;;) { + start_pos = out.find('\x1b', offset); + if (start_pos == string::npos) break; - offset = ++start_pos; - if ((end_pos = out.find('m', offset)) == string::npos) + offset = start_pos + 1; + for (end_pos = out.find('m', offset); end_pos != string::npos and not isdigit(out.at(end_pos - 1)); end_pos = out.find('m', end_pos + 1)); + if (end_pos == string::npos) break; - else if (next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos - start_pos > next_pos - start_pos) + else if (auto next_pos = out.find('\x1b', offset); end_pos >= next_pos) { continue; - out.replace(start_pos, end_pos - start_pos, ""); - next_pos = 0; + } + out.erase(start_pos, (end_pos - start_pos)+1); + offset = 0; } out.shrink_to_fit(); return out; From 1f4b724d6031cd0050ac76273ae948ac750da14e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 15:38:48 +0100 Subject: [PATCH 176/289] Fixed: Text alignment for popup boxes --- src/btop_menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 3fb24bf..b6ec7e8 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -605,7 +605,7 @@ namespace Menu { box_contents = Draw::createBox(x, y, width, height, Theme::c("hi_fg"), true, title) + Mv::d(1); for (const auto& line : content) { - box_contents += Mv::save + Mv::r(width / 2 - Fx::uncolor(line).size() / 2 - 1) + line + Mv::restore + Mv::d(1); + box_contents += Mv::save + Mv::r(max(0ul, (width / 2) - (Fx::uncolor(line).size() / 2) - 1)) + line + Mv::restore + Mv::d(1); } } From ec4bc6823f60fe6e8acfa0b9a3d7bccb0f339aa1 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 15:39:50 +0100 Subject: [PATCH 177/289] Description correction --- src/btop_tools.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index f22de84..705180c 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -286,7 +286,7 @@ namespace Tools { void atomic_wait_for(const atomic& atom, const bool old=true, const uint64_t wait_ms=0) noexcept; - //* Waits for atomic to be false and sets it to true on construct, sets to false on destruct + //* Sets atomic to true on construct, sets to false on destruct class atomic_lock { atomic& atom; bool not_true = false; From c77aee221102cc86a32ae53f837fd260628ee78c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 15:42:09 +0100 Subject: [PATCH 178/289] Fixed: Terminal resize warning getting stuck --- src/btop.cpp | 12 +++++++++--- src/btop_input.cpp | 2 ++ src/btop_input.hpp | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 02367d2..69bb96c 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -157,6 +157,11 @@ void argumentParser(const int& argc, char **argv) { //* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true void term_resize(bool force) { static atomic resizing (false); + if (Input::polling) { + Global::resized = true; + Input::interrupt = true; + return; + } atomic_lock lck(resizing, true); if (auto refreshed = Term::refresh(true); refreshed or force) { if (force and refreshed) force = false; @@ -182,8 +187,9 @@ void term_resize(bool force) { << Mv::to((Term::height / 2) + 1, (Term::width / 2) - 12) << Global::fg_white << "Needed for current config:" << Mv::to((Term::height / 2) + 2, (Term::width / 2) - 10) << "Width = " << min_size.at(0) << " Height = " << min_size.at(1) << flush; - while (not Term::refresh() and not Input::poll()) sleep_ms(10); - if (Input::poll()) { + bool got_key = false; + for (; not Term::refresh() and not got_key; got_key = Input::poll(10)); + if (got_key) { auto key = Input::get(); if (key == "q") clean_quit(0); @@ -899,7 +905,7 @@ int main(int argc, char **argv) { else if (Global::should_sleep) { Global::should_sleep = false; _sleep(); } //? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly) - term_resize(); + term_resize(Global::resized); //? Trigger secondary thread to redraw if terminal has been resized if (Global::resized) { diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 14cbbe3..0694340 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -74,6 +74,7 @@ namespace Input { }; std::atomic interrupt (false); + std::atomic polling (false); array mouse_pos; unordered_flat_map mouse_mappings; @@ -133,6 +134,7 @@ namespace Input { }; bool poll(int timeout) { + atomic_lock lck(polling); if (timeout < 1) return InputThr::instance().avail() > 0; while (timeout > 0) { if (interrupt) { diff --git a/src/btop_input.hpp b/src/btop_input.hpp index fdcf6e2..7342709 100644 --- a/src/btop_input.hpp +++ b/src/btop_input.hpp @@ -42,6 +42,7 @@ namespace Input { extern unordered_flat_map mouse_mappings; extern atomic interrupt; + extern atomic polling; //* Mouse column and line position extern array mouse_pos; From 932bb15e796a90a3f0ab646d0cfc418df37b7870 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 15:45:28 +0100 Subject: [PATCH 179/289] Fixed: Wrong type for max() in msgBox --- src/btop_menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index b6ec7e8..3e212df 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -605,7 +605,7 @@ namespace Menu { box_contents = Draw::createBox(x, y, width, height, Theme::c("hi_fg"), true, title) + Mv::d(1); for (const auto& line : content) { - box_contents += Mv::save + Mv::r(max(0ul, (width / 2) - (Fx::uncolor(line).size() / 2) - 1)) + line + Mv::restore + Mv::d(1); + box_contents += Mv::save + Mv::r(max((size_t)0, (width / 2) - (Fx::uncolor(line).size() / 2) - 1)) + line + Mv::restore + Mv::d(1); } } From 897769a90d768f26afb359fab015e4e2b64aebf3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 21:58:41 +0100 Subject: [PATCH 180/289] Fixed: Logic of Fx::uncolor() --- src/btop_tools.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index f48584e..23ea8ae 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -148,12 +148,12 @@ namespace Fx { if (start_pos == string::npos) break; offset = start_pos + 1; - for (end_pos = out.find('m', offset); end_pos != string::npos and not isdigit(out.at(end_pos - 1)); end_pos = out.find('m', end_pos + 1)); + end_pos = out.find('m', offset); if (end_pos == string::npos) break; - else if (auto next_pos = out.find('\x1b', offset); end_pos >= next_pos) { - continue; - } + else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) + continue; + out.erase(start_pos, (end_pos - start_pos)+1); offset = 0; } From 08f395781732537b5818aa7701b888c3fed20ff5 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 22:08:27 +0100 Subject: [PATCH 181/289] Fixed: Fx::uncolor() optimization --- src/btop_tools.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 23ea8ae..e9bfc2c 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -144,15 +144,17 @@ namespace Fx { string uncolor(const string& s) { string out = s; for (size_t offset = 0, start_pos = 0, end_pos = 0;;) { - start_pos = out.find('\x1b', offset); + start_pos = (offset == 0) ? out.find('\x1b') : offset; if (start_pos == string::npos) break; offset = start_pos + 1; end_pos = out.find('m', offset); if (end_pos == string::npos) break; - else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) - continue; + else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) { + offset = next_pos; + continue; + } out.erase(start_pos, (end_pos - start_pos)+1); offset = 0; From 8e81bf2ccb2c50314c783799c0e3f81970b7aef9 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Feb 2022 22:30:53 +0100 Subject: [PATCH 182/289] Removed: Unnecessary counter for atomic_lock --- src/btop.cpp | 5 ----- src/btop_tools.cpp | 9 ++------- src/btop_tools.hpp | 1 - 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 69bb96c..d6510cd 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -230,11 +230,6 @@ void clean_quit(int sig) { Config::write(); - //? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms - for (int i = 0; Tools::active_locks > 0 and i < 100; i++) { - sleep_ms(10); - } - if (Term::initialized) { Input::clear(); Term::restore(); diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index e9bfc2c..e283cb1 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -166,8 +166,6 @@ namespace Fx { namespace Tools { - atomic active_locks (0); - string uresize(string str, const size_t len, const bool wide) { if (len < 1 or str.empty()) return ""; for (size_t x = 0, i = 0; i < str.size(); i++) { @@ -367,14 +365,11 @@ namespace Tools { } atomic_lock::atomic_lock(atomic& atom, bool wait) : atom(atom) { - active_locks++; - if (wait) { - while (not this->atom.compare_exchange_strong(this->not_true, true)); - } else this->atom.store(true); + if (wait) while (not this->atom.compare_exchange_strong(this->not_true, true)); + else this->atom.store(true); } atomic_lock::~atomic_lock() { - active_locks--; this->atom.store(false); } diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 705180c..6da5cb3 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -131,7 +131,6 @@ namespace Term { namespace Tools { constexpr auto SSmax = std::numeric_limits::max(); - extern atomic active_locks; //* Return number of UTF8 characters in a string (wide=true counts UTF-8 characters with a width > 1 as 2 characters) inline size_t ulen(const string& str, const bool wide=false) { From 951423dba56543d9804f79561fe5580c394306f6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 10 Feb 2022 08:46:39 +0100 Subject: [PATCH 183/289] Added: Percentage progress to Makefile --- Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a3e743f..742d115 100644 --- a/Makefile +++ b/Makefile @@ -133,8 +133,14 @@ SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)) SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)) +SOURCE_COUNT := $(words $(SOURCES)) + OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) +PROGRESS = expr $$(find $(BUILDDIR) -maxdepth 2 -type f -name *.o | wc -l) '*' 90 / $(SOURCE_COUNT) + +P := %% + #? Default Make all: $(PRE) directories btop @@ -219,7 +225,7 @@ btop: $(OBJECTS) @TSTAMP=$$(date +%s 2>/dev/null || echo "0") @$(QUIET) || printf "\n\033[1;92mLinking and optimizing binary\033[37m...\033[0m\n" @$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS) || exit 1 - @printf "\033[1;92m-> \033[1;37m$(TARGETDIR)/btop \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" + @printf "\033[1;92m100$(P) -> \033[1;37m$(TARGETDIR)/btop \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" @printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n" #? Compile @@ -229,7 +235,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) @TSTAMP=$$(date +%s 2>/dev/null || echo "0") @$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n" @$(CXX) $(CXXFLAGS) $(INC) -MMD -c -o $@ $< || exit 1 - @printf "\033[1;92m-> \033[1;37m$@ \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" + @printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" #? Non-File Targets .PHONY: all msg help pre From 31555d8a7ecea6726c39d68fa38fddc35f902693 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 11 Feb 2022 19:30:06 +0100 Subject: [PATCH 184/289] Fixed: Alignment of columns in proc box when wide UTF8 characters are used --- include/widechar_width.hpp | 1491 ++++++++++++++++++++++++++++++++++++ src/btop_draw.cpp | 6 +- src/btop_tools.cpp | 45 +- src/btop_tools.hpp | 8 +- 4 files changed, 1537 insertions(+), 13 deletions(-) create mode 100644 include/widechar_width.hpp diff --git a/include/widechar_width.hpp b/include/widechar_width.hpp new file mode 100644 index 0000000..a5b4c85 --- /dev/null +++ b/include/widechar_width.hpp @@ -0,0 +1,1491 @@ +/** + * widechar_width.h, generated on 2022-02-11. + * See https://github.com/ridiculousfish/widecharwidth/ + * + * SHA1 file hashes: + * UnicodeData.txt: 8a5c26bfb27df8cfab23cf2c34c62d8d3075ae4d + * EastAsianWidth.txt: 8ec36ccac3852bf0c2f02e37c6151551cd14db72 + * emoji-data.txt: 3f0ec08c001c4bc6df0b07d01068fc73808bfb4c + */ + +#ifndef WIDECHAR_WIDTH_H +#define WIDECHAR_WIDTH_H + +#include +#include +#include +#include + +namespace utf8 { + +/* Special width values */ +enum { + widechar_nonprint = 0, // The character is not printable. + widechar_combining = 0, // The character is a zero-width combiner. + widechar_ambiguous = 1, // The character is East-Asian ambiguous width. + widechar_private_use = 1, // The character is for private use. + widechar_unassigned = 0, // The character is unassigned. + widechar_widened_in_9 = 2, // Width is 1 in Unicode 8, 2 in Unicode 9+. + widechar_non_character = 0 // The character is a noncharacter. +}; + +/* An inclusive range of characters. */ +struct widechar_range { + uint32_t lo; + uint32_t hi; +}; + +/* Simple ASCII characters - used a lot, so we check them first. */ +static const struct widechar_range widechar_ascii_table[] = { + {0x00020, 0x0007E} +}; + +/* Private usage range. */ +static const struct widechar_range widechar_private_table[] = { + {0x0E000, 0x0F8FF}, + {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD} +}; + +/* Nonprinting characters. */ +static const struct widechar_range widechar_nonprint_table[] = { + {0x00000, 0x0001F}, + {0x0007F, 0x0009F}, + {0x000AD, 0x000AD}, + {0x00600, 0x00605}, + {0x0061C, 0x0061C}, + {0x006DD, 0x006DD}, + {0x0070F, 0x0070F}, + {0x00890, 0x00891}, + {0x008E2, 0x008E2}, + {0x0180E, 0x0180E}, + {0x0200B, 0x0200F}, + {0x02028, 0x0202E}, + {0x02060, 0x02064}, + {0x02066, 0x0206F}, + {0x0D800, 0x0DFFF}, + {0x0FEFF, 0x0FEFF}, + {0x0FFF9, 0x0FFFB}, + {0x110BD, 0x110BD}, + {0x110CD, 0x110CD}, + {0x13430, 0x13438}, + {0x1BCA0, 0x1BCA3}, + {0x1D173, 0x1D17A}, + {0xE0001, 0xE0001}, + {0xE0020, 0xE007F} +}; + +/* Width 0 combining marks. */ +static const struct widechar_range widechar_combining_table[] = { + {0x00300, 0x0036F}, + {0x00483, 0x00489}, + {0x00591, 0x005BD}, + {0x005BF, 0x005BF}, + {0x005C1, 0x005C2}, + {0x005C4, 0x005C5}, + {0x005C7, 0x005C7}, + {0x00610, 0x0061A}, + {0x0064B, 0x0065F}, + {0x00670, 0x00670}, + {0x006D6, 0x006DC}, + {0x006DF, 0x006E4}, + {0x006E7, 0x006E8}, + {0x006EA, 0x006ED}, + {0x00711, 0x00711}, + {0x00730, 0x0074A}, + {0x007A6, 0x007B0}, + {0x007EB, 0x007F3}, + {0x007FD, 0x007FD}, + {0x00816, 0x00819}, + {0x0081B, 0x00823}, + {0x00825, 0x00827}, + {0x00829, 0x0082D}, + {0x00859, 0x0085B}, + {0x00898, 0x0089F}, + {0x008CA, 0x008E1}, + {0x008E3, 0x00903}, + {0x0093A, 0x0093C}, + {0x0093E, 0x0094F}, + {0x00951, 0x00957}, + {0x00962, 0x00963}, + {0x00981, 0x00983}, + {0x009BC, 0x009BC}, + {0x009BE, 0x009C4}, + {0x009C7, 0x009C8}, + {0x009CB, 0x009CD}, + {0x009D7, 0x009D7}, + {0x009E2, 0x009E3}, + {0x009FE, 0x009FE}, + {0x00A01, 0x00A03}, + {0x00A3C, 0x00A3C}, + {0x00A3E, 0x00A42}, + {0x00A47, 0x00A48}, + {0x00A4B, 0x00A4D}, + {0x00A51, 0x00A51}, + {0x00A70, 0x00A71}, + {0x00A75, 0x00A75}, + {0x00A81, 0x00A83}, + {0x00ABC, 0x00ABC}, + {0x00ABE, 0x00AC5}, + {0x00AC7, 0x00AC9}, + {0x00ACB, 0x00ACD}, + {0x00AE2, 0x00AE3}, + {0x00AFA, 0x00AFF}, + {0x00B01, 0x00B03}, + {0x00B3C, 0x00B3C}, + {0x00B3E, 0x00B44}, + {0x00B47, 0x00B48}, + {0x00B4B, 0x00B4D}, + {0x00B55, 0x00B57}, + {0x00B62, 0x00B63}, + {0x00B82, 0x00B82}, + {0x00BBE, 0x00BC2}, + {0x00BC6, 0x00BC8}, + {0x00BCA, 0x00BCD}, + {0x00BD7, 0x00BD7}, + {0x00C00, 0x00C04}, + {0x00C3C, 0x00C3C}, + {0x00C3E, 0x00C44}, + {0x00C46, 0x00C48}, + {0x00C4A, 0x00C4D}, + {0x00C55, 0x00C56}, + {0x00C62, 0x00C63}, + {0x00C81, 0x00C83}, + {0x00CBC, 0x00CBC}, + {0x00CBE, 0x00CC4}, + {0x00CC6, 0x00CC8}, + {0x00CCA, 0x00CCD}, + {0x00CD5, 0x00CD6}, + {0x00CE2, 0x00CE3}, + {0x00D00, 0x00D03}, + {0x00D3B, 0x00D3C}, + {0x00D3E, 0x00D44}, + {0x00D46, 0x00D48}, + {0x00D4A, 0x00D4D}, + {0x00D57, 0x00D57}, + {0x00D62, 0x00D63}, + {0x00D81, 0x00D83}, + {0x00DCA, 0x00DCA}, + {0x00DCF, 0x00DD4}, + {0x00DD6, 0x00DD6}, + {0x00DD8, 0x00DDF}, + {0x00DF2, 0x00DF3}, + {0x00E31, 0x00E31}, + {0x00E34, 0x00E3A}, + {0x00E47, 0x00E4E}, + {0x00EB1, 0x00EB1}, + {0x00EB4, 0x00EBC}, + {0x00EC8, 0x00ECD}, + {0x00F18, 0x00F19}, + {0x00F35, 0x00F35}, + {0x00F37, 0x00F37}, + {0x00F39, 0x00F39}, + {0x00F3E, 0x00F3F}, + {0x00F71, 0x00F84}, + {0x00F86, 0x00F87}, + {0x00F8D, 0x00F97}, + {0x00F99, 0x00FBC}, + {0x00FC6, 0x00FC6}, + {0x0102B, 0x0103E}, + {0x01056, 0x01059}, + {0x0105E, 0x01060}, + {0x01062, 0x01064}, + {0x01067, 0x0106D}, + {0x01071, 0x01074}, + {0x01082, 0x0108D}, + {0x0108F, 0x0108F}, + {0x0109A, 0x0109D}, + {0x0135D, 0x0135F}, + {0x01712, 0x01715}, + {0x01732, 0x01734}, + {0x01752, 0x01753}, + {0x01772, 0x01773}, + {0x017B4, 0x017D3}, + {0x017DD, 0x017DD}, + {0x0180B, 0x0180D}, + {0x0180F, 0x0180F}, + {0x01885, 0x01886}, + {0x018A9, 0x018A9}, + {0x01920, 0x0192B}, + {0x01930, 0x0193B}, + {0x01A17, 0x01A1B}, + {0x01A55, 0x01A5E}, + {0x01A60, 0x01A7C}, + {0x01A7F, 0x01A7F}, + {0x01AB0, 0x01ACE}, + {0x01B00, 0x01B04}, + {0x01B34, 0x01B44}, + {0x01B6B, 0x01B73}, + {0x01B80, 0x01B82}, + {0x01BA1, 0x01BAD}, + {0x01BE6, 0x01BF3}, + {0x01C24, 0x01C37}, + {0x01CD0, 0x01CD2}, + {0x01CD4, 0x01CE8}, + {0x01CED, 0x01CED}, + {0x01CF4, 0x01CF4}, + {0x01CF7, 0x01CF9}, + {0x01DC0, 0x01DFF}, + {0x020D0, 0x020F0}, + {0x02CEF, 0x02CF1}, + {0x02D7F, 0x02D7F}, + {0x02DE0, 0x02DFF}, + {0x0302A, 0x0302F}, + {0x03099, 0x0309A}, + {0x0A66F, 0x0A672}, + {0x0A674, 0x0A67D}, + {0x0A69E, 0x0A69F}, + {0x0A6F0, 0x0A6F1}, + {0x0A802, 0x0A802}, + {0x0A806, 0x0A806}, + {0x0A80B, 0x0A80B}, + {0x0A823, 0x0A827}, + {0x0A82C, 0x0A82C}, + {0x0A880, 0x0A881}, + {0x0A8B4, 0x0A8C5}, + {0x0A8E0, 0x0A8F1}, + {0x0A8FF, 0x0A8FF}, + {0x0A926, 0x0A92D}, + {0x0A947, 0x0A953}, + {0x0A980, 0x0A983}, + {0x0A9B3, 0x0A9C0}, + {0x0A9E5, 0x0A9E5}, + {0x0AA29, 0x0AA36}, + {0x0AA43, 0x0AA43}, + {0x0AA4C, 0x0AA4D}, + {0x0AA7B, 0x0AA7D}, + {0x0AAB0, 0x0AAB0}, + {0x0AAB2, 0x0AAB4}, + {0x0AAB7, 0x0AAB8}, + {0x0AABE, 0x0AABF}, + {0x0AAC1, 0x0AAC1}, + {0x0AAEB, 0x0AAEF}, + {0x0AAF5, 0x0AAF6}, + {0x0ABE3, 0x0ABEA}, + {0x0ABEC, 0x0ABED}, + {0x0FB1E, 0x0FB1E}, + {0x0FE00, 0x0FE0F}, + {0x0FE20, 0x0FE2F}, + {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, + {0x10376, 0x1037A}, + {0x10A01, 0x10A03}, + {0x10A05, 0x10A06}, + {0x10A0C, 0x10A0F}, + {0x10A38, 0x10A3A}, + {0x10A3F, 0x10A3F}, + {0x10AE5, 0x10AE6}, + {0x10D24, 0x10D27}, + {0x10EAB, 0x10EAC}, + {0x10F46, 0x10F50}, + {0x10F82, 0x10F85}, + {0x11000, 0x11002}, + {0x11038, 0x11046}, + {0x11070, 0x11070}, + {0x11073, 0x11074}, + {0x1107F, 0x11082}, + {0x110B0, 0x110BA}, + {0x110C2, 0x110C2}, + {0x11100, 0x11102}, + {0x11127, 0x11134}, + {0x11145, 0x11146}, + {0x11173, 0x11173}, + {0x11180, 0x11182}, + {0x111B3, 0x111C0}, + {0x111C9, 0x111CC}, + {0x111CE, 0x111CF}, + {0x1122C, 0x11237}, + {0x1123E, 0x1123E}, + {0x112DF, 0x112EA}, + {0x11300, 0x11303}, + {0x1133B, 0x1133C}, + {0x1133E, 0x11344}, + {0x11347, 0x11348}, + {0x1134B, 0x1134D}, + {0x11357, 0x11357}, + {0x11362, 0x11363}, + {0x11366, 0x1136C}, + {0x11370, 0x11374}, + {0x11435, 0x11446}, + {0x1145E, 0x1145E}, + {0x114B0, 0x114C3}, + {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, + {0x115DC, 0x115DD}, + {0x11630, 0x11640}, + {0x116AB, 0x116B7}, + {0x1171D, 0x1172B}, + {0x1182C, 0x1183A}, + {0x11930, 0x11935}, + {0x11937, 0x11938}, + {0x1193B, 0x1193E}, + {0x11940, 0x11940}, + {0x11942, 0x11943}, + {0x119D1, 0x119D7}, + {0x119DA, 0x119E0}, + {0x119E4, 0x119E4}, + {0x11A01, 0x11A0A}, + {0x11A33, 0x11A39}, + {0x11A3B, 0x11A3E}, + {0x11A47, 0x11A47}, + {0x11A51, 0x11A5B}, + {0x11A8A, 0x11A99}, + {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, + {0x11C92, 0x11CA7}, + {0x11CA9, 0x11CB6}, + {0x11D31, 0x11D36}, + {0x11D3A, 0x11D3A}, + {0x11D3C, 0x11D3D}, + {0x11D3F, 0x11D45}, + {0x11D47, 0x11D47}, + {0x11D8A, 0x11D8E}, + {0x11D90, 0x11D91}, + {0x11D93, 0x11D97}, + {0x11EF3, 0x11EF6}, + {0x16AF0, 0x16AF4}, + {0x16B30, 0x16B36}, + {0x16F4F, 0x16F4F}, + {0x16F51, 0x16F87}, + {0x16F8F, 0x16F92}, + {0x16FE4, 0x16FE4}, + {0x16FF0, 0x16FF1}, + {0x1BC9D, 0x1BC9E}, + {0x1CF00, 0x1CF2D}, + {0x1CF30, 0x1CF46}, + {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, + {0x1D17B, 0x1D182}, + {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, + {0x1D242, 0x1D244}, + {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, + {0x1DA75, 0x1DA75}, + {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, + {0x1DAA1, 0x1DAAF}, + {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, + {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, + {0x1E130, 0x1E136}, + {0x1E2AE, 0x1E2AE}, + {0x1E2EC, 0x1E2EF}, + {0x1E8D0, 0x1E8D6}, + {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF} +}; + +/* Width 0 combining letters. */ +static const struct widechar_range widechar_combiningletters_table[] = { + {0x01160, 0x011FF}, + {0x0D7B0, 0x0D7FF} +}; + +/* Width 2 characters. */ +static const struct widechar_range widechar_doublewide_table[] = { + {0x01100, 0x0115F}, + {0x02329, 0x0232A}, + {0x02E80, 0x02E99}, + {0x02E9B, 0x02EF3}, + {0x02F00, 0x02FD5}, + {0x02FF0, 0x02FFB}, + {0x03000, 0x0303E}, + {0x03041, 0x03096}, + {0x03099, 0x030FF}, + {0x03105, 0x0312F}, + {0x03131, 0x0318E}, + {0x03190, 0x031E3}, + {0x031F0, 0x0321E}, + {0x03220, 0x03247}, + {0x03250, 0x04DBF}, + {0x04E00, 0x0A48C}, + {0x0A490, 0x0A4C6}, + {0x0A960, 0x0A97C}, + {0x0AC00, 0x0D7A3}, + {0x0F900, 0x0FAFF}, + {0x0FE10, 0x0FE19}, + {0x0FE30, 0x0FE52}, + {0x0FE54, 0x0FE66}, + {0x0FE68, 0x0FE6B}, + {0x0FF01, 0x0FF60}, + {0x0FFE0, 0x0FFE6}, + {0x16FE0, 0x16FE4}, + {0x16FF0, 0x16FF1}, + {0x17000, 0x187F7}, + {0x18800, 0x18CD5}, + {0x18D00, 0x18D08}, + {0x1AFF0, 0x1AFF3}, + {0x1AFF5, 0x1AFFB}, + {0x1AFFD, 0x1AFFE}, + {0x1B000, 0x1B122}, + {0x1B150, 0x1B152}, + {0x1B164, 0x1B167}, + {0x1B170, 0x1B2FB}, + {0x1F200, 0x1F200}, + {0x1F202, 0x1F202}, + {0x1F210, 0x1F219}, + {0x1F21B, 0x1F22E}, + {0x1F230, 0x1F231}, + {0x1F237, 0x1F237}, + {0x1F23B, 0x1F23B}, + {0x1F240, 0x1F248}, + {0x1F260, 0x1F265}, + {0x1F57A, 0x1F57A}, + {0x1F5A4, 0x1F5A4}, + {0x1F6D1, 0x1F6D2}, + {0x1F6D5, 0x1F6D7}, + {0x1F6DD, 0x1F6DF}, + {0x1F6F4, 0x1F6FC}, + {0x1F7E0, 0x1F7EB}, + {0x1F7F0, 0x1F7F0}, + {0x1F90C, 0x1F90F}, + {0x1F919, 0x1F93A}, + {0x1F93C, 0x1F945}, + {0x1F947, 0x1F97F}, + {0x1F985, 0x1F9BF}, + {0x1F9C1, 0x1F9FF}, + {0x1FA70, 0x1FA74}, + {0x1FA78, 0x1FA7C}, + {0x1FA80, 0x1FA86}, + {0x1FA90, 0x1FAAC}, + {0x1FAB0, 0x1FABA}, + {0x1FAC0, 0x1FAC5}, + {0x1FAD0, 0x1FAD9}, + {0x1FAE0, 0x1FAE7}, + {0x1FAF0, 0x1FAF6}, + {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD} +}; + +/* Ambiguous-width characters. */ +static const struct widechar_range widechar_ambiguous_table[] = { + {0x000A1, 0x000A1}, + {0x000A4, 0x000A4}, + {0x000A7, 0x000A8}, + {0x000AA, 0x000AA}, + {0x000AD, 0x000AE}, + {0x000B0, 0x000B4}, + {0x000B6, 0x000BA}, + {0x000BC, 0x000BF}, + {0x000C6, 0x000C6}, + {0x000D0, 0x000D0}, + {0x000D7, 0x000D8}, + {0x000DE, 0x000E1}, + {0x000E6, 0x000E6}, + {0x000E8, 0x000EA}, + {0x000EC, 0x000ED}, + {0x000F0, 0x000F0}, + {0x000F2, 0x000F3}, + {0x000F7, 0x000FA}, + {0x000FC, 0x000FC}, + {0x000FE, 0x000FE}, + {0x00101, 0x00101}, + {0x00111, 0x00111}, + {0x00113, 0x00113}, + {0x0011B, 0x0011B}, + {0x00126, 0x00127}, + {0x0012B, 0x0012B}, + {0x00131, 0x00133}, + {0x00138, 0x00138}, + {0x0013F, 0x00142}, + {0x00144, 0x00144}, + {0x00148, 0x0014B}, + {0x0014D, 0x0014D}, + {0x00152, 0x00153}, + {0x00166, 0x00167}, + {0x0016B, 0x0016B}, + {0x001CE, 0x001CE}, + {0x001D0, 0x001D0}, + {0x001D2, 0x001D2}, + {0x001D4, 0x001D4}, + {0x001D6, 0x001D6}, + {0x001D8, 0x001D8}, + {0x001DA, 0x001DA}, + {0x001DC, 0x001DC}, + {0x00251, 0x00251}, + {0x00261, 0x00261}, + {0x002C4, 0x002C4}, + {0x002C7, 0x002C7}, + {0x002C9, 0x002CB}, + {0x002CD, 0x002CD}, + {0x002D0, 0x002D0}, + {0x002D8, 0x002DB}, + {0x002DD, 0x002DD}, + {0x002DF, 0x002DF}, + {0x00300, 0x0036F}, + {0x00391, 0x003A1}, + {0x003A3, 0x003A9}, + {0x003B1, 0x003C1}, + {0x003C3, 0x003C9}, + {0x00401, 0x00401}, + {0x00410, 0x0044F}, + {0x00451, 0x00451}, + {0x02010, 0x02010}, + {0x02013, 0x02016}, + {0x02018, 0x02019}, + {0x0201C, 0x0201D}, + {0x02020, 0x02022}, + {0x02024, 0x02027}, + {0x02030, 0x02030}, + {0x02032, 0x02033}, + {0x02035, 0x02035}, + {0x0203B, 0x0203B}, + {0x0203E, 0x0203E}, + {0x02074, 0x02074}, + {0x0207F, 0x0207F}, + {0x02081, 0x02084}, + {0x020AC, 0x020AC}, + {0x02103, 0x02103}, + {0x02105, 0x02105}, + {0x02109, 0x02109}, + {0x02113, 0x02113}, + {0x02116, 0x02116}, + {0x02121, 0x02122}, + {0x02126, 0x02126}, + {0x0212B, 0x0212B}, + {0x02153, 0x02154}, + {0x0215B, 0x0215E}, + {0x02160, 0x0216B}, + {0x02170, 0x02179}, + {0x02189, 0x02189}, + {0x02190, 0x02199}, + {0x021B8, 0x021B9}, + {0x021D2, 0x021D2}, + {0x021D4, 0x021D4}, + {0x021E7, 0x021E7}, + {0x02200, 0x02200}, + {0x02202, 0x02203}, + {0x02207, 0x02208}, + {0x0220B, 0x0220B}, + {0x0220F, 0x0220F}, + {0x02211, 0x02211}, + {0x02215, 0x02215}, + {0x0221A, 0x0221A}, + {0x0221D, 0x02220}, + {0x02223, 0x02223}, + {0x02225, 0x02225}, + {0x02227, 0x0222C}, + {0x0222E, 0x0222E}, + {0x02234, 0x02237}, + {0x0223C, 0x0223D}, + {0x02248, 0x02248}, + {0x0224C, 0x0224C}, + {0x02252, 0x02252}, + {0x02260, 0x02261}, + {0x02264, 0x02267}, + {0x0226A, 0x0226B}, + {0x0226E, 0x0226F}, + {0x02282, 0x02283}, + {0x02286, 0x02287}, + {0x02295, 0x02295}, + {0x02299, 0x02299}, + {0x022A5, 0x022A5}, + {0x022BF, 0x022BF}, + {0x02312, 0x02312}, + {0x02460, 0x024E9}, + {0x024EB, 0x0254B}, + {0x02550, 0x02573}, + {0x02580, 0x0258F}, + {0x02592, 0x02595}, + {0x025A0, 0x025A1}, + {0x025A3, 0x025A9}, + {0x025B2, 0x025B3}, + {0x025B6, 0x025B7}, + {0x025BC, 0x025BD}, + {0x025C0, 0x025C1}, + {0x025C6, 0x025C8}, + {0x025CB, 0x025CB}, + {0x025CE, 0x025D1}, + {0x025E2, 0x025E5}, + {0x025EF, 0x025EF}, + {0x02605, 0x02606}, + {0x02609, 0x02609}, + {0x0260E, 0x0260F}, + {0x0261C, 0x0261C}, + {0x0261E, 0x0261E}, + {0x02640, 0x02640}, + {0x02642, 0x02642}, + {0x02660, 0x02661}, + {0x02663, 0x02665}, + {0x02667, 0x0266A}, + {0x0266C, 0x0266D}, + {0x0266F, 0x0266F}, + {0x0269E, 0x0269F}, + {0x026BF, 0x026BF}, + {0x026C6, 0x026CD}, + {0x026CF, 0x026D3}, + {0x026D5, 0x026E1}, + {0x026E3, 0x026E3}, + {0x026E8, 0x026E9}, + {0x026EB, 0x026F1}, + {0x026F4, 0x026F4}, + {0x026F6, 0x026F9}, + {0x026FB, 0x026FC}, + {0x026FE, 0x026FF}, + {0x0273D, 0x0273D}, + {0x02776, 0x0277F}, + {0x02B56, 0x02B59}, + {0x03248, 0x0324F}, + {0x0E000, 0x0F8FF}, + {0x0FE00, 0x0FE0F}, + {0x0FFFD, 0x0FFFD}, + {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, + {0x1F130, 0x1F169}, + {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, + {0x1F19B, 0x1F1AC}, + {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD} +}; + +/* Unassigned characters. */ +static const struct widechar_range widechar_unassigned_table[] = { + {0x00378, 0x00379}, + {0x00380, 0x00383}, + {0x0038B, 0x0038B}, + {0x0038D, 0x0038D}, + {0x003A2, 0x003A2}, + {0x00530, 0x00530}, + {0x00557, 0x00558}, + {0x0058B, 0x0058C}, + {0x00590, 0x00590}, + {0x005C8, 0x005CF}, + {0x005EB, 0x005EE}, + {0x005F5, 0x005FF}, + {0x0070E, 0x0070E}, + {0x0074B, 0x0074C}, + {0x007B2, 0x007BF}, + {0x007FB, 0x007FC}, + {0x0082E, 0x0082F}, + {0x0083F, 0x0083F}, + {0x0085C, 0x0085D}, + {0x0085F, 0x0085F}, + {0x0086B, 0x0086F}, + {0x0088F, 0x0088F}, + {0x00892, 0x00897}, + {0x00984, 0x00984}, + {0x0098D, 0x0098E}, + {0x00991, 0x00992}, + {0x009A9, 0x009A9}, + {0x009B1, 0x009B1}, + {0x009B3, 0x009B5}, + {0x009BA, 0x009BB}, + {0x009C5, 0x009C6}, + {0x009C9, 0x009CA}, + {0x009CF, 0x009D6}, + {0x009D8, 0x009DB}, + {0x009DE, 0x009DE}, + {0x009E4, 0x009E5}, + {0x009FF, 0x00A00}, + {0x00A04, 0x00A04}, + {0x00A0B, 0x00A0E}, + {0x00A11, 0x00A12}, + {0x00A29, 0x00A29}, + {0x00A31, 0x00A31}, + {0x00A34, 0x00A34}, + {0x00A37, 0x00A37}, + {0x00A3A, 0x00A3B}, + {0x00A3D, 0x00A3D}, + {0x00A43, 0x00A46}, + {0x00A49, 0x00A4A}, + {0x00A4E, 0x00A50}, + {0x00A52, 0x00A58}, + {0x00A5D, 0x00A5D}, + {0x00A5F, 0x00A65}, + {0x00A77, 0x00A80}, + {0x00A84, 0x00A84}, + {0x00A8E, 0x00A8E}, + {0x00A92, 0x00A92}, + {0x00AA9, 0x00AA9}, + {0x00AB1, 0x00AB1}, + {0x00AB4, 0x00AB4}, + {0x00ABA, 0x00ABB}, + {0x00AC6, 0x00AC6}, + {0x00ACA, 0x00ACA}, + {0x00ACE, 0x00ACF}, + {0x00AD1, 0x00ADF}, + {0x00AE4, 0x00AE5}, + {0x00AF2, 0x00AF8}, + {0x00B00, 0x00B00}, + {0x00B04, 0x00B04}, + {0x00B0D, 0x00B0E}, + {0x00B11, 0x00B12}, + {0x00B29, 0x00B29}, + {0x00B31, 0x00B31}, + {0x00B34, 0x00B34}, + {0x00B3A, 0x00B3B}, + {0x00B45, 0x00B46}, + {0x00B49, 0x00B4A}, + {0x00B4E, 0x00B54}, + {0x00B58, 0x00B5B}, + {0x00B5E, 0x00B5E}, + {0x00B64, 0x00B65}, + {0x00B78, 0x00B81}, + {0x00B84, 0x00B84}, + {0x00B8B, 0x00B8D}, + {0x00B91, 0x00B91}, + {0x00B96, 0x00B98}, + {0x00B9B, 0x00B9B}, + {0x00B9D, 0x00B9D}, + {0x00BA0, 0x00BA2}, + {0x00BA5, 0x00BA7}, + {0x00BAB, 0x00BAD}, + {0x00BBA, 0x00BBD}, + {0x00BC3, 0x00BC5}, + {0x00BC9, 0x00BC9}, + {0x00BCE, 0x00BCF}, + {0x00BD1, 0x00BD6}, + {0x00BD8, 0x00BE5}, + {0x00BFB, 0x00BFF}, + {0x00C0D, 0x00C0D}, + {0x00C11, 0x00C11}, + {0x00C29, 0x00C29}, + {0x00C3A, 0x00C3B}, + {0x00C45, 0x00C45}, + {0x00C49, 0x00C49}, + {0x00C4E, 0x00C54}, + {0x00C57, 0x00C57}, + {0x00C5B, 0x00C5C}, + {0x00C5E, 0x00C5F}, + {0x00C64, 0x00C65}, + {0x00C70, 0x00C76}, + {0x00C8D, 0x00C8D}, + {0x00C91, 0x00C91}, + {0x00CA9, 0x00CA9}, + {0x00CB4, 0x00CB4}, + {0x00CBA, 0x00CBB}, + {0x00CC5, 0x00CC5}, + {0x00CC9, 0x00CC9}, + {0x00CCE, 0x00CD4}, + {0x00CD7, 0x00CDC}, + {0x00CDF, 0x00CDF}, + {0x00CE4, 0x00CE5}, + {0x00CF0, 0x00CF0}, + {0x00CF3, 0x00CFF}, + {0x00D0D, 0x00D0D}, + {0x00D11, 0x00D11}, + {0x00D45, 0x00D45}, + {0x00D49, 0x00D49}, + {0x00D50, 0x00D53}, + {0x00D64, 0x00D65}, + {0x00D80, 0x00D80}, + {0x00D84, 0x00D84}, + {0x00D97, 0x00D99}, + {0x00DB2, 0x00DB2}, + {0x00DBC, 0x00DBC}, + {0x00DBE, 0x00DBF}, + {0x00DC7, 0x00DC9}, + {0x00DCB, 0x00DCE}, + {0x00DD5, 0x00DD5}, + {0x00DD7, 0x00DD7}, + {0x00DE0, 0x00DE5}, + {0x00DF0, 0x00DF1}, + {0x00DF5, 0x00E00}, + {0x00E3B, 0x00E3E}, + {0x00E5C, 0x00E80}, + {0x00E83, 0x00E83}, + {0x00E85, 0x00E85}, + {0x00E8B, 0x00E8B}, + {0x00EA4, 0x00EA4}, + {0x00EA6, 0x00EA6}, + {0x00EBE, 0x00EBF}, + {0x00EC5, 0x00EC5}, + {0x00EC7, 0x00EC7}, + {0x00ECE, 0x00ECF}, + {0x00EDA, 0x00EDB}, + {0x00EE0, 0x00EFF}, + {0x00F48, 0x00F48}, + {0x00F6D, 0x00F70}, + {0x00F98, 0x00F98}, + {0x00FBD, 0x00FBD}, + {0x00FCD, 0x00FCD}, + {0x00FDB, 0x00FFF}, + {0x010C6, 0x010C6}, + {0x010C8, 0x010CC}, + {0x010CE, 0x010CF}, + {0x01249, 0x01249}, + {0x0124E, 0x0124F}, + {0x01257, 0x01257}, + {0x01259, 0x01259}, + {0x0125E, 0x0125F}, + {0x01289, 0x01289}, + {0x0128E, 0x0128F}, + {0x012B1, 0x012B1}, + {0x012B6, 0x012B7}, + {0x012BF, 0x012BF}, + {0x012C1, 0x012C1}, + {0x012C6, 0x012C7}, + {0x012D7, 0x012D7}, + {0x01311, 0x01311}, + {0x01316, 0x01317}, + {0x0135B, 0x0135C}, + {0x0137D, 0x0137F}, + {0x0139A, 0x0139F}, + {0x013F6, 0x013F7}, + {0x013FE, 0x013FF}, + {0x0169D, 0x0169F}, + {0x016F9, 0x016FF}, + {0x01716, 0x0171E}, + {0x01737, 0x0173F}, + {0x01754, 0x0175F}, + {0x0176D, 0x0176D}, + {0x01771, 0x01771}, + {0x01774, 0x0177F}, + {0x017DE, 0x017DF}, + {0x017EA, 0x017EF}, + {0x017FA, 0x017FF}, + {0x0181A, 0x0181F}, + {0x01879, 0x0187F}, + {0x018AB, 0x018AF}, + {0x018F6, 0x018FF}, + {0x0191F, 0x0191F}, + {0x0192C, 0x0192F}, + {0x0193C, 0x0193F}, + {0x01941, 0x01943}, + {0x0196E, 0x0196F}, + {0x01975, 0x0197F}, + {0x019AC, 0x019AF}, + {0x019CA, 0x019CF}, + {0x019DB, 0x019DD}, + {0x01A1C, 0x01A1D}, + {0x01A5F, 0x01A5F}, + {0x01A7D, 0x01A7E}, + {0x01A8A, 0x01A8F}, + {0x01A9A, 0x01A9F}, + {0x01AAE, 0x01AAF}, + {0x01ACF, 0x01AFF}, + {0x01B4D, 0x01B4F}, + {0x01B7F, 0x01B7F}, + {0x01BF4, 0x01BFB}, + {0x01C38, 0x01C3A}, + {0x01C4A, 0x01C4C}, + {0x01C89, 0x01C8F}, + {0x01CBB, 0x01CBC}, + {0x01CC8, 0x01CCF}, + {0x01CFB, 0x01CFF}, + {0x01F16, 0x01F17}, + {0x01F1E, 0x01F1F}, + {0x01F46, 0x01F47}, + {0x01F4E, 0x01F4F}, + {0x01F58, 0x01F58}, + {0x01F5A, 0x01F5A}, + {0x01F5C, 0x01F5C}, + {0x01F5E, 0x01F5E}, + {0x01F7E, 0x01F7F}, + {0x01FB5, 0x01FB5}, + {0x01FC5, 0x01FC5}, + {0x01FD4, 0x01FD5}, + {0x01FDC, 0x01FDC}, + {0x01FF0, 0x01FF1}, + {0x01FF5, 0x01FF5}, + {0x01FFF, 0x01FFF}, + {0x02065, 0x02065}, + {0x02072, 0x02073}, + {0x0208F, 0x0208F}, + {0x0209D, 0x0209F}, + {0x020C1, 0x020CF}, + {0x020F1, 0x020FF}, + {0x0218C, 0x0218F}, + {0x02427, 0x0243F}, + {0x0244B, 0x0245F}, + {0x02B74, 0x02B75}, + {0x02B96, 0x02B96}, + {0x02CF4, 0x02CF8}, + {0x02D26, 0x02D26}, + {0x02D28, 0x02D2C}, + {0x02D2E, 0x02D2F}, + {0x02D68, 0x02D6E}, + {0x02D71, 0x02D7E}, + {0x02D97, 0x02D9F}, + {0x02DA7, 0x02DA7}, + {0x02DAF, 0x02DAF}, + {0x02DB7, 0x02DB7}, + {0x02DBF, 0x02DBF}, + {0x02DC7, 0x02DC7}, + {0x02DCF, 0x02DCF}, + {0x02DD7, 0x02DD7}, + {0x02DDF, 0x02DDF}, + {0x02E5E, 0x02E7F}, + {0x02E9A, 0x02E9A}, + {0x02EF4, 0x02EFF}, + {0x02FD6, 0x02FEF}, + {0x02FFC, 0x02FFF}, + {0x03040, 0x03040}, + {0x03097, 0x03098}, + {0x03100, 0x03104}, + {0x03130, 0x03130}, + {0x0318F, 0x0318F}, + {0x031E4, 0x031EF}, + {0x0321F, 0x0321F}, + {0x03401, 0x04DBE}, + {0x04E01, 0x09FFE}, + {0x0A48D, 0x0A48F}, + {0x0A4C7, 0x0A4CF}, + {0x0A62C, 0x0A63F}, + {0x0A6F8, 0x0A6FF}, + {0x0A7CB, 0x0A7CF}, + {0x0A7D2, 0x0A7D2}, + {0x0A7D4, 0x0A7D4}, + {0x0A7DA, 0x0A7F1}, + {0x0A82D, 0x0A82F}, + {0x0A83A, 0x0A83F}, + {0x0A878, 0x0A87F}, + {0x0A8C6, 0x0A8CD}, + {0x0A8DA, 0x0A8DF}, + {0x0A954, 0x0A95E}, + {0x0A97D, 0x0A97F}, + {0x0A9CE, 0x0A9CE}, + {0x0A9DA, 0x0A9DD}, + {0x0A9FF, 0x0A9FF}, + {0x0AA37, 0x0AA3F}, + {0x0AA4E, 0x0AA4F}, + {0x0AA5A, 0x0AA5B}, + {0x0AAC3, 0x0AADA}, + {0x0AAF7, 0x0AB00}, + {0x0AB07, 0x0AB08}, + {0x0AB0F, 0x0AB10}, + {0x0AB17, 0x0AB1F}, + {0x0AB27, 0x0AB27}, + {0x0AB2F, 0x0AB2F}, + {0x0AB6C, 0x0AB6F}, + {0x0ABEE, 0x0ABEF}, + {0x0ABFA, 0x0ABFF}, + {0x0AC01, 0x0D7A2}, + {0x0D7A4, 0x0D7AF}, + {0x0D7C7, 0x0D7CA}, + {0x0D7FC, 0x0D7FF}, + {0x0FA6E, 0x0FA6F}, + {0x0FADA, 0x0FAFF}, + {0x0FB07, 0x0FB12}, + {0x0FB18, 0x0FB1C}, + {0x0FB37, 0x0FB37}, + {0x0FB3D, 0x0FB3D}, + {0x0FB3F, 0x0FB3F}, + {0x0FB42, 0x0FB42}, + {0x0FB45, 0x0FB45}, + {0x0FBC3, 0x0FBD2}, + {0x0FD90, 0x0FD91}, + {0x0FDC8, 0x0FDCE}, + {0x0FE1A, 0x0FE1F}, + {0x0FE53, 0x0FE53}, + {0x0FE67, 0x0FE67}, + {0x0FE6C, 0x0FE6F}, + {0x0FE75, 0x0FE75}, + {0x0FEFD, 0x0FEFE}, + {0x0FF00, 0x0FF00}, + {0x0FFBF, 0x0FFC1}, + {0x0FFC8, 0x0FFC9}, + {0x0FFD0, 0x0FFD1}, + {0x0FFD8, 0x0FFD9}, + {0x0FFDD, 0x0FFDF}, + {0x0FFE7, 0x0FFE7}, + {0x0FFEF, 0x0FFF8}, + {0x1000C, 0x1000C}, + {0x10027, 0x10027}, + {0x1003B, 0x1003B}, + {0x1003E, 0x1003E}, + {0x1004E, 0x1004F}, + {0x1005E, 0x1007F}, + {0x100FB, 0x100FF}, + {0x10103, 0x10106}, + {0x10134, 0x10136}, + {0x1018F, 0x1018F}, + {0x1019D, 0x1019F}, + {0x101A1, 0x101CF}, + {0x101FE, 0x1027F}, + {0x1029D, 0x1029F}, + {0x102D1, 0x102DF}, + {0x102FC, 0x102FF}, + {0x10324, 0x1032C}, + {0x1034B, 0x1034F}, + {0x1037B, 0x1037F}, + {0x1039E, 0x1039E}, + {0x103C4, 0x103C7}, + {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, + {0x104AA, 0x104AF}, + {0x104D4, 0x104D7}, + {0x104FC, 0x104FF}, + {0x10528, 0x1052F}, + {0x10564, 0x1056E}, + {0x1057B, 0x1057B}, + {0x1058B, 0x1058B}, + {0x10593, 0x10593}, + {0x10596, 0x10596}, + {0x105A2, 0x105A2}, + {0x105B2, 0x105B2}, + {0x105BA, 0x105BA}, + {0x105BD, 0x105FF}, + {0x10737, 0x1073F}, + {0x10756, 0x1075F}, + {0x10768, 0x1077F}, + {0x10786, 0x10786}, + {0x107B1, 0x107B1}, + {0x107BB, 0x107FF}, + {0x10806, 0x10807}, + {0x10809, 0x10809}, + {0x10836, 0x10836}, + {0x10839, 0x1083B}, + {0x1083D, 0x1083E}, + {0x10856, 0x10856}, + {0x1089F, 0x108A6}, + {0x108B0, 0x108DF}, + {0x108F3, 0x108F3}, + {0x108F6, 0x108FA}, + {0x1091C, 0x1091E}, + {0x1093A, 0x1093E}, + {0x10940, 0x1097F}, + {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, + {0x10A04, 0x10A04}, + {0x10A07, 0x10A0B}, + {0x10A14, 0x10A14}, + {0x10A18, 0x10A18}, + {0x10A36, 0x10A37}, + {0x10A3B, 0x10A3E}, + {0x10A49, 0x10A4F}, + {0x10A59, 0x10A5F}, + {0x10AA0, 0x10ABF}, + {0x10AE7, 0x10AEA}, + {0x10AF7, 0x10AFF}, + {0x10B36, 0x10B38}, + {0x10B56, 0x10B57}, + {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, + {0x10B9D, 0x10BA8}, + {0x10BB0, 0x10BFF}, + {0x10C49, 0x10C7F}, + {0x10CB3, 0x10CBF}, + {0x10CF3, 0x10CF9}, + {0x10D28, 0x10D2F}, + {0x10D3A, 0x10E5F}, + {0x10E7F, 0x10E7F}, + {0x10EAA, 0x10EAA}, + {0x10EAE, 0x10EAF}, + {0x10EB2, 0x10EFF}, + {0x10F28, 0x10F2F}, + {0x10F5A, 0x10F6F}, + {0x10F8A, 0x10FAF}, + {0x10FCC, 0x10FDF}, + {0x10FF7, 0x10FFF}, + {0x1104E, 0x11051}, + {0x11076, 0x1107E}, + {0x110C3, 0x110CC}, + {0x110CE, 0x110CF}, + {0x110E9, 0x110EF}, + {0x110FA, 0x110FF}, + {0x11135, 0x11135}, + {0x11148, 0x1114F}, + {0x11177, 0x1117F}, + {0x111E0, 0x111E0}, + {0x111F5, 0x111FF}, + {0x11212, 0x11212}, + {0x1123F, 0x1127F}, + {0x11287, 0x11287}, + {0x11289, 0x11289}, + {0x1128E, 0x1128E}, + {0x1129E, 0x1129E}, + {0x112AA, 0x112AF}, + {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, + {0x11304, 0x11304}, + {0x1130D, 0x1130E}, + {0x11311, 0x11312}, + {0x11329, 0x11329}, + {0x11331, 0x11331}, + {0x11334, 0x11334}, + {0x1133A, 0x1133A}, + {0x11345, 0x11346}, + {0x11349, 0x1134A}, + {0x1134E, 0x1134F}, + {0x11351, 0x11356}, + {0x11358, 0x1135C}, + {0x11364, 0x11365}, + {0x1136D, 0x1136F}, + {0x11375, 0x113FF}, + {0x1145C, 0x1145C}, + {0x11462, 0x1147F}, + {0x114C8, 0x114CF}, + {0x114DA, 0x1157F}, + {0x115B6, 0x115B7}, + {0x115DE, 0x115FF}, + {0x11645, 0x1164F}, + {0x1165A, 0x1165F}, + {0x1166D, 0x1167F}, + {0x116BA, 0x116BF}, + {0x116CA, 0x116FF}, + {0x1171B, 0x1171C}, + {0x1172C, 0x1172F}, + {0x11747, 0x117FF}, + {0x1183C, 0x1189F}, + {0x118F3, 0x118FE}, + {0x11907, 0x11908}, + {0x1190A, 0x1190B}, + {0x11914, 0x11914}, + {0x11917, 0x11917}, + {0x11936, 0x11936}, + {0x11939, 0x1193A}, + {0x11947, 0x1194F}, + {0x1195A, 0x1199F}, + {0x119A8, 0x119A9}, + {0x119D8, 0x119D9}, + {0x119E5, 0x119FF}, + {0x11A48, 0x11A4F}, + {0x11AA3, 0x11AAF}, + {0x11AF9, 0x11BFF}, + {0x11C09, 0x11C09}, + {0x11C37, 0x11C37}, + {0x11C46, 0x11C4F}, + {0x11C6D, 0x11C6F}, + {0x11C90, 0x11C91}, + {0x11CA8, 0x11CA8}, + {0x11CB7, 0x11CFF}, + {0x11D07, 0x11D07}, + {0x11D0A, 0x11D0A}, + {0x11D37, 0x11D39}, + {0x11D3B, 0x11D3B}, + {0x11D3E, 0x11D3E}, + {0x11D48, 0x11D4F}, + {0x11D5A, 0x11D5F}, + {0x11D66, 0x11D66}, + {0x11D69, 0x11D69}, + {0x11D8F, 0x11D8F}, + {0x11D92, 0x11D92}, + {0x11D99, 0x11D9F}, + {0x11DAA, 0x11EDF}, + {0x11EF9, 0x11FAF}, + {0x11FB1, 0x11FBF}, + {0x11FF2, 0x11FFE}, + {0x1239A, 0x123FF}, + {0x1246F, 0x1246F}, + {0x12475, 0x1247F}, + {0x12544, 0x12F8F}, + {0x12FF3, 0x12FFF}, + {0x1342F, 0x1342F}, + {0x13439, 0x143FF}, + {0x14647, 0x167FF}, + {0x16A39, 0x16A3F}, + {0x16A5F, 0x16A5F}, + {0x16A6A, 0x16A6D}, + {0x16ABF, 0x16ABF}, + {0x16ACA, 0x16ACF}, + {0x16AEE, 0x16AEF}, + {0x16AF6, 0x16AFF}, + {0x16B46, 0x16B4F}, + {0x16B5A, 0x16B5A}, + {0x16B62, 0x16B62}, + {0x16B78, 0x16B7C}, + {0x16B90, 0x16E3F}, + {0x16E9B, 0x16EFF}, + {0x16F4B, 0x16F4E}, + {0x16F88, 0x16F8E}, + {0x16FA0, 0x16FDF}, + {0x16FE5, 0x16FEF}, + {0x16FF2, 0x16FFF}, + {0x17001, 0x187F6}, + {0x187F8, 0x187FF}, + {0x18CD6, 0x18CFF}, + {0x18D01, 0x18D07}, + {0x18D09, 0x1AFEF}, + {0x1AFF4, 0x1AFF4}, + {0x1AFFC, 0x1AFFC}, + {0x1AFFF, 0x1AFFF}, + {0x1B123, 0x1B14F}, + {0x1B153, 0x1B163}, + {0x1B168, 0x1B16F}, + {0x1B2FC, 0x1BBFF}, + {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, + {0x1BC89, 0x1BC8F}, + {0x1BC9A, 0x1BC9B}, + {0x1BCA4, 0x1CEFF}, + {0x1CF2E, 0x1CF2F}, + {0x1CF47, 0x1CF4F}, + {0x1CFC4, 0x1CFFF}, + {0x1D0F6, 0x1D0FF}, + {0x1D127, 0x1D128}, + {0x1D1EB, 0x1D1FF}, + {0x1D246, 0x1D2DF}, + {0x1D2F4, 0x1D2FF}, + {0x1D357, 0x1D35F}, + {0x1D379, 0x1D3FF}, + {0x1D455, 0x1D455}, + {0x1D49D, 0x1D49D}, + {0x1D4A0, 0x1D4A1}, + {0x1D4A3, 0x1D4A4}, + {0x1D4A7, 0x1D4A8}, + {0x1D4AD, 0x1D4AD}, + {0x1D4BA, 0x1D4BA}, + {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, + {0x1D506, 0x1D506}, + {0x1D50B, 0x1D50C}, + {0x1D515, 0x1D515}, + {0x1D51D, 0x1D51D}, + {0x1D53A, 0x1D53A}, + {0x1D53F, 0x1D53F}, + {0x1D545, 0x1D545}, + {0x1D547, 0x1D549}, + {0x1D551, 0x1D551}, + {0x1D6A6, 0x1D6A7}, + {0x1D7CC, 0x1D7CD}, + {0x1DA8C, 0x1DA9A}, + {0x1DAA0, 0x1DAA0}, + {0x1DAB0, 0x1DEFF}, + {0x1DF1F, 0x1DFFF}, + {0x1E007, 0x1E007}, + {0x1E019, 0x1E01A}, + {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, + {0x1E02B, 0x1E0FF}, + {0x1E12D, 0x1E12F}, + {0x1E13E, 0x1E13F}, + {0x1E14A, 0x1E14D}, + {0x1E150, 0x1E28F}, + {0x1E2AF, 0x1E2BF}, + {0x1E2FA, 0x1E2FE}, + {0x1E300, 0x1E7DF}, + {0x1E7E7, 0x1E7E7}, + {0x1E7EC, 0x1E7EC}, + {0x1E7EF, 0x1E7EF}, + {0x1E7FF, 0x1E7FF}, + {0x1E8C5, 0x1E8C6}, + {0x1E8D7, 0x1E8FF}, + {0x1E94C, 0x1E94F}, + {0x1E95A, 0x1E95D}, + {0x1E960, 0x1EC70}, + {0x1ECB5, 0x1ED00}, + {0x1ED3E, 0x1EDFF}, + {0x1EE04, 0x1EE04}, + {0x1EE20, 0x1EE20}, + {0x1EE23, 0x1EE23}, + {0x1EE25, 0x1EE26}, + {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, + {0x1EE38, 0x1EE38}, + {0x1EE3A, 0x1EE3A}, + {0x1EE3C, 0x1EE41}, + {0x1EE43, 0x1EE46}, + {0x1EE48, 0x1EE48}, + {0x1EE4A, 0x1EE4A}, + {0x1EE4C, 0x1EE4C}, + {0x1EE50, 0x1EE50}, + {0x1EE53, 0x1EE53}, + {0x1EE55, 0x1EE56}, + {0x1EE58, 0x1EE58}, + {0x1EE5A, 0x1EE5A}, + {0x1EE5C, 0x1EE5C}, + {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, + {0x1EE63, 0x1EE63}, + {0x1EE65, 0x1EE66}, + {0x1EE6B, 0x1EE6B}, + {0x1EE73, 0x1EE73}, + {0x1EE78, 0x1EE78}, + {0x1EE7D, 0x1EE7D}, + {0x1EE7F, 0x1EE7F}, + {0x1EE8A, 0x1EE8A}, + {0x1EE9C, 0x1EEA0}, + {0x1EEA4, 0x1EEA4}, + {0x1EEAA, 0x1EEAA}, + {0x1EEBC, 0x1EEEF}, + {0x1EEF2, 0x1EFFF}, + {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, + {0x1F0AF, 0x1F0B0}, + {0x1F0C0, 0x1F0C0}, + {0x1F0D0, 0x1F0D0}, + {0x1F0F6, 0x1F0FF}, + {0x1F1AE, 0x1F1E5}, + {0x1F203, 0x1F20F}, + {0x1F23C, 0x1F23F}, + {0x1F249, 0x1F24F}, + {0x1F252, 0x1F25F}, + {0x1F266, 0x1F2FF}, + {0x1F6D8, 0x1F6DC}, + {0x1F6ED, 0x1F6EF}, + {0x1F6FD, 0x1F6FF}, + {0x1F774, 0x1F77F}, + {0x1F7D9, 0x1F7DF}, + {0x1F7EC, 0x1F7EF}, + {0x1F7F1, 0x1F7FF}, + {0x1F80C, 0x1F80F}, + {0x1F848, 0x1F84F}, + {0x1F85A, 0x1F85F}, + {0x1F888, 0x1F88F}, + {0x1F8AE, 0x1F8AF}, + {0x1F8B2, 0x1F8FF}, + {0x1FA54, 0x1FA5F}, + {0x1FA6E, 0x1FA6F}, + {0x1FA75, 0x1FA77}, + {0x1FA7D, 0x1FA7F}, + {0x1FA87, 0x1FA8F}, + {0x1FAAD, 0x1FAAF}, + {0x1FABB, 0x1FABF}, + {0x1FAC6, 0x1FACF}, + {0x1FADA, 0x1FADF}, + {0x1FAE8, 0x1FAEF}, + {0x1FAF7, 0x1FAFF}, + {0x1FB93, 0x1FB93}, + {0x1FBCB, 0x1FBEF}, + {0x1FBFA, 0x1FFFD}, + {0x20001, 0x2A6DE}, + {0x2A6E0, 0x2A6FF}, + {0x2A701, 0x2B737}, + {0x2B739, 0x2B73F}, + {0x2B741, 0x2B81C}, + {0x2B81E, 0x2B81F}, + {0x2B821, 0x2CEA0}, + {0x2CEA2, 0x2CEAF}, + {0x2CEB1, 0x2EBDF}, + {0x2EBE1, 0x2F7FF}, + {0x2FA1E, 0x2FFFD}, + {0x30001, 0x31349}, + {0x3134B, 0x3FFFD}, + {0x40000, 0x4FFFD}, + {0x50000, 0x5FFFD}, + {0x60000, 0x6FFFD}, + {0x70000, 0x7FFFD}, + {0x80000, 0x8FFFD}, + {0x90000, 0x9FFFD}, + {0xA0000, 0xAFFFD}, + {0xB0000, 0xBFFFD}, + {0xC0000, 0xCFFFD}, + {0xD0000, 0xDFFFD}, + {0xE0000, 0xE0000}, + {0xE0002, 0xE001F}, + {0xE0080, 0xE00FF}, + {0xE01F0, 0xEFFFD} +}; + +/* Non-characters. */ +static const struct widechar_range widechar_nonchar_table[] = { + {0x0FDD0, 0x0FDEF}, + {0x0FFFE, 0x0FFFF}, + {0x1FFFE, 0x1FFFF}, + {0x2FFFE, 0x2FFFF}, + {0x3FFFE, 0x3FFFF}, + {0x4FFFE, 0x4FFFF}, + {0x5FFFE, 0x5FFFF}, + {0x6FFFE, 0x6FFFF}, + {0x7FFFE, 0x7FFFF}, + {0x8FFFE, 0x8FFFF}, + {0x9FFFE, 0x9FFFF}, + {0xAFFFE, 0xAFFFF}, + {0xBFFFE, 0xBFFFF}, + {0xCFFFE, 0xCFFFF}, + {0xDFFFE, 0xDFFFF}, + {0xEFFFE, 0xEFFFF}, + {0xFFFFE, 0xFFFFF}, + {0x10FFFE, 0x10FFFF} +}; + +/* Characters that were widened from width 1 to 2 in Unicode 9. */ +static const struct widechar_range widechar_widened_table[] = { + {0x0231A, 0x0231B}, + {0x023E9, 0x023EC}, + {0x023F0, 0x023F0}, + {0x023F3, 0x023F3}, + {0x025FD, 0x025FE}, + {0x02614, 0x02615}, + {0x02648, 0x02653}, + {0x0267F, 0x0267F}, + {0x02693, 0x02693}, + {0x026A1, 0x026A1}, + {0x026AA, 0x026AB}, + {0x026BD, 0x026BE}, + {0x026C4, 0x026C5}, + {0x026CE, 0x026CE}, + {0x026D4, 0x026D4}, + {0x026EA, 0x026EA}, + {0x026F2, 0x026F3}, + {0x026F5, 0x026F5}, + {0x026FA, 0x026FA}, + {0x026FD, 0x026FD}, + {0x02705, 0x02705}, + {0x0270A, 0x0270B}, + {0x02728, 0x02728}, + {0x0274C, 0x0274C}, + {0x0274E, 0x0274E}, + {0x02753, 0x02755}, + {0x02757, 0x02757}, + {0x02795, 0x02797}, + {0x027B0, 0x027B0}, + {0x027BF, 0x027BF}, + {0x02B1B, 0x02B1C}, + {0x02B50, 0x02B50}, + {0x02B55, 0x02B55}, + {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, + {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, + {0x1F201, 0x1F201}, + {0x1F21A, 0x1F21A}, + {0x1F22F, 0x1F22F}, + {0x1F232, 0x1F236}, + {0x1F238, 0x1F23A}, + {0x1F250, 0x1F251}, + {0x1F300, 0x1F320}, + {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F393}, + {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, + {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, + {0x1F440, 0x1F440}, + {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, + {0x1F550, 0x1F567}, + {0x1F595, 0x1F596}, + {0x1F5FB, 0x1F64F}, + {0x1F680, 0x1F6C5}, + {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D0}, + {0x1F6EB, 0x1F6EC}, + {0x1F910, 0x1F918}, + {0x1F980, 0x1F984}, + {0x1F9C0, 0x1F9C0} +}; + +template +bool widechar_in_table(const Collection &arr, uint32_t c) { + auto where = std::lower_bound(std::begin(arr), std::end(arr), c, + [](widechar_range p, uint32_t c) { return p.hi < c; }); + return where != std::end(arr) && where->lo <= c; +} + +/* Return the width of character c, or a special negative value. */ +int wcwidth(uint32_t c) { + if (widechar_in_table(widechar_ascii_table, c)) + return 1; + if (widechar_in_table(widechar_private_table, c)) + return widechar_private_use; + if (widechar_in_table(widechar_nonprint_table, c)) + return widechar_nonprint; + if (widechar_in_table(widechar_nonchar_table, c)) + return widechar_non_character; + if (widechar_in_table(widechar_combining_table, c)) + return widechar_combining; + if (widechar_in_table(widechar_combiningletters_table, c)) + return widechar_combining; + if (widechar_in_table(widechar_doublewide_table, c)) + return 2; + if (widechar_in_table(widechar_ambiguous_table, c)) + return widechar_ambiguous; + if (widechar_in_table(widechar_unassigned_table, c)) + return widechar_unassigned; + if (widechar_in_table(widechar_widened_table, c)) + return widechar_widened_in_9; + return 1; +} + +} // namespace +#endif // WIDECHAR_WIDTH_H diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index a309834..d0fc088 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1399,7 +1399,7 @@ namespace Proc { out += Mv::to(y+2+lc, x+1) + g_color + rjust(to_string(p.pid), 8) + ' ' + c_color + ljust(p.name, prog_size, true) + ' ' + end - + (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, true) + ' ' : ""); + + (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, true) + Mv::to(y+2+lc, x+11+prog_size+cmd_size) + ' ' : ""); } //? Tree view line else { @@ -1412,10 +1412,10 @@ namespace Proc { width_left -= (ulen(p.name) + 1); } if (width_left > 7 and p.short_cmd != p.name) { - out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ") "; + out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ')'; width_left -= (ulen(p.short_cmd, true) + 3); } - out += string(max(0, width_left), ' '); + out += Mv::to(y+2+lc, x+2+tree_size); } //? Common end of line string cpu_str = to_string(p.cpu_p); diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index e283cb1..20d8514 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -25,6 +25,7 @@ tab-size = 4 #include #include #include +#include #include #include @@ -166,17 +167,47 @@ namespace Fx { namespace Tools { + size_t wide_ulen(const string& str) { + unsigned int chars = 0; + std::wstring_convert> conv; + auto w_str = conv.from_bytes(str.c_str()); + + for (auto c : w_str) { + chars += utf8::wcwidth(c); + } + + return chars; + } + + size_t wide_ulen(const std::wstring& w_str) { + unsigned int chars = 0; + + for (auto c : w_str) { + chars += utf8::wcwidth(c); + } + + return chars; + } + string uresize(string str, const size_t len, const bool wide) { if (len < 1 or str.empty()) return ""; - for (size_t x = 0, i = 0; i < str.size(); i++) { - if (wide and static_cast(str.at(i)) > 0xef) x += 2; - else if ((static_cast(str.at(i)) & 0xC0) != 0x80) x++; - if (x >= len + 1) { - str.resize(i); - str.shrink_to_fit(); - break; + if (wide) { + std::wstring_convert> conv; + auto w_str = conv.from_bytes(str.c_str()); + while (wide_ulen(w_str) > len) + w_str.pop_back(); + str = conv.to_bytes(w_str); + } + else { + for (size_t x = 0, i = 0; i < str.size(); i++) { + if ((static_cast(str.at(i)) & 0xC0) != 0x80) x++; + if (x >= len + 1) { + str.resize(i); + break; + } } } + str.shrink_to_fit(); return str; } diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 6da5cb3..e11775c 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -132,10 +132,12 @@ namespace Term { namespace Tools { constexpr auto SSmax = std::numeric_limits::max(); - //* Return number of UTF8 characters in a string (wide=true counts UTF-8 characters with a width > 1 as 2 characters) + size_t wide_ulen(const string& str); + size_t wide_ulen(const std::wstring& w_str); + + //* Return number of UTF8 characters in a string (wide=true for column size needed on terminal) inline size_t ulen(const string& str, const bool wide=false) { - return std::ranges::count_if(str, [](char c) { return (static_cast(c) & 0xC0) != 0x80; }) - + (wide ? std::ranges::count_if(str, [](char c) { return (static_cast(c) > 0xef); }) : 0); + return (wide ? wide_ulen(str) : std::ranges::count_if(str, [](char c) { return (static_cast(c) & 0xC0) != 0x80; })); } //* Resize a string consisting of UTF8 characters (only reduces size) From ac5ad8712100365d0de2182b74a31d39db0633d8 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 11 Feb 2022 19:46:29 +0100 Subject: [PATCH 185/289] Fixed: Battery meter draw fix --- src/btop_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index d0fc088..9992808 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -574,7 +574,7 @@ namespace Cpu { out += Mv::to(y, bat_pos) + title_left + Theme::c("title") + Fx::b + "BAT" + bat_symbol + ' ' + str_percent + (Term::width >= 100 ? Fx::ub + ' ' + bat_meter(percent) + Fx::b : "") - + (not str_time.empty() ? ' ' + Theme::c("title") + str_time : "") + Fx::ub + title_right; + + (not str_time.empty() ? ' ' + Theme::c("title") + str_time : " ") + Fx::ub + title_right; } } else if (bat_pos > 0) { From fc1500007c1aaf868ef2796b442cc57c34d584df Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 11 Feb 2022 20:02:21 +0100 Subject: [PATCH 186/289] v1.2.1 Bug fixes --- CHANGELOG.md | 18 ++++++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 004c8c1..a6add45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## v1.2.1 + +* Added: Arrow only after use of "f" when filtering processes, by @NavigationHazard + +* Fixed: Fx::uncolor not removing all escapes + +* Fixed: Text alignment for popup boxes + +* Fixed: Terminal resize warning getting stuck + +* Removed: Unnecessary counter for atomic_lock + +* Added: Percentage progress to Makefile + +* Fixed: Alignment of columns in proc box when wide UTF8 characters are used + +* Fixed: Battery meter draw fix + ## v1.2.0 * Added: Support for FreeBSD, by @joske and @aristocratos diff --git a/src/btop.cpp b/src/btop.cpp index d6510cd..690adc8 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.0"; + const string Version = "1.2.1"; int coreCount; string overlay; From d804d3ab338b1f179fad04a8d493622bf7f35c92 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 12 Feb 2022 22:27:11 +0100 Subject: [PATCH 187/289] Changed: Reverted uncolor() back to using regex --- src/btop_tools.cpp | 45 +++++++++++++++++++++++---------------------- src/btop_tools.hpp | 10 +++++++++- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 20d8514..e913739 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -141,29 +141,30 @@ namespace Term { //? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- -namespace Fx { - string uncolor(const string& s) { - string out = s; - for (size_t offset = 0, start_pos = 0, end_pos = 0;;) { - start_pos = (offset == 0) ? out.find('\x1b') : offset; - if (start_pos == string::npos) - break; - offset = start_pos + 1; - end_pos = out.find('m', offset); - if (end_pos == string::npos) - break; - else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) { - offset = next_pos; - continue; - } +// ! Dsiabled due to issue when compiling with musl, reverted back to using regex +// namespace Fx { +// string uncolor(const string& s) { +// string out = s; +// for (size_t offset = 0, start_pos = 0, end_pos = 0;;) { +// start_pos = (offset == 0) ? out.find('\x1b') : offset; +// if (start_pos == string::npos) +// break; +// offset = start_pos + 1; +// end_pos = out.find('m', offset); +// if (end_pos == string::npos) +// break; +// else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) { +// offset = next_pos; +// continue; +// } - out.erase(start_pos, (end_pos - start_pos)+1); - offset = 0; - } - out.shrink_to_fit(); - return out; - } -} +// out.erase(start_pos, (end_pos - start_pos)+1); +// offset = 0; +// } +// out.shrink_to_fit(); +// return out; +// } +// } namespace Tools { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index e11775c..63723cc 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -22,6 +22,7 @@ tab-size = 4 #include #include #include +#include #include #include #include @@ -64,8 +65,15 @@ namespace Fx { //* Reset text effects and restore theme foregrund and background color extern string reset; + //* Regex for matching color, style and cursor move escape sequences + const std::regex escape_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m|f|s|u|C|D|A|B){1}"); + + //* Regex for matching only color and style escape sequences + const std::regex color_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m){1}"); + //* Return a string with all colors and text styling removed - string uncolor(const string& s); + inline string uncolor(const string& s) { return std::regex_replace(s, color_regex, ""); } + // string uncolor(const string& s); } From baabbe78b2a355d375b7ab5dc181a12b60fcd76e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 13 Feb 2022 00:33:20 +0100 Subject: [PATCH 188/289] Added: Toggle for showing free disk space for privileged or normal users --- src/btop_config.cpp | 3 +++ src/btop_menu.cpp | 11 +++++++++-- src/linux/btop_collect.cpp | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 1883dfa..c509a8a 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -151,6 +151,8 @@ namespace Config { {"use_fstab", "#* Read disks list from /etc/fstab. This also disables only_physical."}, + {"disk_free_priv", "#* Set to true to show available disk space for privileged users."}, + {"show_io_stat", "#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view."}, {"io_mode", "#* Toggles io mode for disks, showing big graphs for disk read/write speeds."}, @@ -242,6 +244,7 @@ namespace Config { {"show_battery", true}, {"vim_keys", false}, {"tty_mode", false}, + {"disk_free_priv", false}, {"force_tty", false}, {"lowcolor", false}, {"show_detailed", false}, diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 3e212df..3eeedd8 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -464,12 +464,19 @@ namespace Menu { "", "True or False."}, {"use_fstab", - "Read disks list from /etc/fstab.", - "(Has no effect on macOS X)", + "(Linux) Read disks list from /etc/fstab.", "", "This also disables only_physical.", "", "True or False."}, + {"disk_free_priv", + "(Linux) Type of available disk space.", + "", + "Set to true to show how much disk space is", + "available for privileged users.", + "", + "Set to false to show available for normal", + "users."}, {"disks_filter", "Optional filter for shown disks.", "", diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 79a6eac..62ae505 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -817,6 +817,7 @@ namespace Mem { //? Get disks stats if (show_disks) { double uptime = system_uptime(); + auto free_priv = Config::getB("disk_free_priv"); try { auto& disks_filter = Config::getS("disks_filter"); bool filter_exclude = false; @@ -943,7 +944,7 @@ namespace Mem { continue; } disk.total = vfs.f_blocks * vfs.f_frsize; - disk.free = vfs.f_bfree * vfs.f_frsize; + disk.free = (free_priv ? vfs.f_bfree : vfs.f_bavail) * vfs.f_frsize; disk.used = disk.total - disk.free; disk.used_percent = round((double)disk.used * 100 / disk.total); disk.free_percent = 100 - disk.used_percent; From 36a3c7fb8caca89167193d11458bc2d83a79c67e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 13 Feb 2022 00:44:55 +0100 Subject: [PATCH 189/289] Added: Clarification on signal screen that number can be manually entered --- src/btop_menu.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 3eeedd8..248a769 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -694,7 +694,7 @@ namespace Menu { if (redraw) { x = Term::width/2 - 40; y = Term::height/2 - 9; - bg = Draw::createBox(x + 2, y, 78, 18, Theme::c("hi_fg"), true, "signals"); + bg = Draw::createBox(x + 2, y, 78, 19, Theme::c("hi_fg"), true, "signals"); bg += Mv::to(y+2, x+3) + Theme::c("title") + Fx::b + cjust("Send signal to PID " + to_string(s_pid) + " (" + uresize((s_pid == Config::getI("detailed_pid") ? Proc::detailed.entry.name : Config::getS("selected_name")), 30) + ")", 76); } @@ -776,11 +776,12 @@ namespace Menu { } cy++; - out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 38) + Theme::c("main_fg") + Fx::ub + " | To send signal."; - mouse_mappings["enter"] = {cy, x, 1, 78}; - out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓ ← →", 38, true) + Theme::c("main_fg") + Fx::ub + " | To choose signal."; - out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or \"q\"", 38) + Theme::c("main_fg") + Fx::ub + " | To abort."; - mouse_mappings["escape"] = {cy, x, 1, 78}; + out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓ ← →", 33, true) + Theme::c("main_fg") + Fx::ub + " | To choose signal."; + out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("0-9", 33) + Theme::c("main_fg") + Fx::ub + " | Enter manually."; + out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 33) + Theme::c("main_fg") + Fx::ub + " | To send signal."; + mouse_mappings["enter"] = {cy, x, 1, 73}; + out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or \"q\"", 33) + Theme::c("main_fg") + Fx::ub + " | To abort."; + mouse_mappings["escape"] = {cy, x, 1, 73}; out += Fx::reset; } From edece28eecd7c7b2f925ee807b8c6cce0daac501 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 13 Feb 2022 00:51:35 +0100 Subject: [PATCH 190/289] Updated example config file --- README.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index dbdb414..91c833c 100644 --- a/README.md +++ b/README.md @@ -557,7 +557,7 @@ Also needs a UTF8 locale and a font that covers: ``` sudo snap install btop --edge ``` - + * **Connect the interface** ```bash @@ -573,14 +573,14 @@ Config and log files stored in `$XDG_CONFIG_HOME/btop` or `$HOME/.config/btop` f #### btop.cfg: (auto generated if not found) ```bash -#? Config file for btop v. 0.1.0 +#? Config file for btop v. 1.2.2 #* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. #* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" color_theme = "Default" #* If the theme set background should be shown, set to False if you want terminal background transparency. -theme_background = False +theme_background = True #* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. truecolor = True @@ -595,6 +595,10 @@ force_tty = False #* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" +#* Set to True to enable "h,j,k,l" keys for directional control in lists. +#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. +vim_keys = False + #* Rounded corners on boxes, is ignored if TTY mode is ON. rounded_corners = True @@ -618,10 +622,10 @@ graph_symbol_net = "default" graph_symbol_proc = "default" #* Manually set which boxes to show. Available values are "cpu mem net proc", separate values with whitespace. -shown_boxes = "cpu mem net proc" +shown_boxes = "proc cpu mem net" #* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs. -update_ms = 2000 +update_ms = 1500 #* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive", #* "cpu lazy" sorts top process over time (easier to follow), "cpu responsive" updates top process directly. @@ -689,6 +693,9 @@ cpu_core_map = "" #* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine". temp_scale = "celsius" +#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. +base_10_sizes = False + #* Show CPU frequency. show_cpu_freq = True @@ -727,6 +734,9 @@ only_physical = True #* Read disks list from /etc/fstab. This also disables only_physical. use_fstab = False +#* Set to true to show available disk space for privileged users. +disk_free_priv = False + #* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. show_io_stat = True @@ -757,6 +767,9 @@ net_iface = "br0" #* Show battery stats in top right if battery is present. show_battery = True +#* Which battery to use if multiple are present. "Auto" for auto detection. +selected_battery = "Auto" + #* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG". #* The level set includes all lower levels, i.e. "DEBUG" will show all logging info. log_level = "DEBUG" From 18457d118143e3e9d416d62e82ee5470aa128537 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 13 Feb 2022 00:59:00 +0100 Subject: [PATCH 191/289] v1.2.2 Bug fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6add45..fcdc3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.2.2 + +* Changed: Reverted uncolor() back to using regex to fix delay in opening menu when compiled with musl + +* Added: Toggle for showing free disk space for privileged or normal users + +* Added: Clarification on signal screen that number can be manually entered + ## v1.2.1 * Added: Arrow only after use of "f" when filtering processes, by @NavigationHazard diff --git a/src/btop.cpp b/src/btop.cpp index 690adc8..1504ecf 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.1"; + const string Version = "1.2.2"; int coreCount; string overlay; From f9a7cdbe09784f24dd9098fc47d1212fd07bb8e2 Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" Date: Sun, 13 Feb 2022 03:51:13 +0100 Subject: [PATCH 192/289] Sort input file list so that btop builds in a reproducible way in spite of indeterministic filesystem readdir order See https://reproducible-builds.org/ for why this is good. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 742d115..effae85 100644 --- a/Makefile +++ b/Makefile @@ -129,9 +129,9 @@ ifdef DEBUG override OPTFLAGS := -O0 -g endif -SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)) +SOURCES := $(sort $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT))) -SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)) +SOURCES += $(sort $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT))) SOURCE_COUNT := $(words $(SOURCES)) From 5ceb967b94a58ac58d86457fdc151f32b5f2b2e6 Mon Sep 17 00:00:00 2001 From: "Jakob P. Liljenberg" Date: Sun, 13 Feb 2022 19:43:27 +0100 Subject: [PATCH 193/289] btop.cfg -> btop.conf --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91c833c..22b9cde 100644 --- a/README.md +++ b/README.md @@ -570,7 +570,7 @@ Also needs a UTF8 locale and a font that covers: All options changeable from within UI. Config and log files stored in `$XDG_CONFIG_HOME/btop` or `$HOME/.config/btop` folder -#### btop.cfg: (auto generated if not found) +#### btop.conf: (auto generated if not found) ```bash #? Config file for btop v. 1.2.2 From 2fa800e21e2a74f3b12f52178a75e067ce349648 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 14 Feb 2022 12:45:17 +0100 Subject: [PATCH 194/289] Changed: floating_humanizer() now shows fractionals when shortened < 10 --- src/btop_tools.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index e913739..ba82ab4 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -360,7 +360,9 @@ namespace Tools { else if (out.size() >= 2) out.resize(out.size() - 2); } if (shorten) { - if (out.find('.') != string::npos) out = to_string((int)round(stof(out))); + auto f_pos = out.find('.'); + if (f_pos == 1 and out.size() > 3) out = out.substr(0,2) + to_string((int)round(stof(out.substr(2)) / 10)); + else if (f_pos != string::npos) out = to_string((int)round(stof(out))); if (out.size() > 3) { out = to_string((int)(out[0] - '0') + 1); start++;} out.push_back(units[start][0]); } From 49b415d733524e52dd601e94fd9fc1c6d717863b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 14 Feb 2022 22:01:21 +0100 Subject: [PATCH 195/289] Makefile progress accuracy --- Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index effae85..ec5c9cd 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m█ override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") +override DATESTAMP := $(shell date '+%Y-%m-%d %H:%M:%S' || echo "5 minutes ago") ifeq ($(shell command -v gdate >/dev/null; echo $$?),0) DATE_CMD := gdate else @@ -133,11 +134,20 @@ SOURCES := $(sort $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT))) SOURCES += $(sort $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT))) +#? Setup percentage progress SOURCE_COUNT := $(words $(SOURCES)) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) -PROGRESS = expr $$(find $(BUILDDIR) -maxdepth 2 -type f -name *.o | wc -l) '*' 90 / $(SOURCE_COUNT) +ifneq ($(wildcard $(BUILDDIR)/.*),) + SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null)) + override SOURCE_COUNT := $(shell expr $(SOURCE_COUNT) - $(words $(SKIPPED_SOURCES))) + ifeq ($(SOURCE_COUNT),0) + override SOURCE_COUNT = $(words $(SOURCES)) + endif +endif + +PROGRESS = expr $$(find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2 P := %% From f630a8da3b55f3f5ae825b512346009f1ca7970a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 14 Feb 2022 22:19:26 +0100 Subject: [PATCH 196/289] Makefile fixed fallback for outdated find --- Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index ec5c9cd..7268fdc 100644 --- a/Makefile +++ b/Makefile @@ -139,16 +139,19 @@ SOURCE_COUNT := $(words $(SOURCES)) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) -ifneq ($(wildcard $(BUILDDIR)/.*),) - SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null)) - override SOURCE_COUNT := $(shell expr $(SOURCE_COUNT) - $(words $(SKIPPED_SOURCES))) - ifeq ($(SOURCE_COUNT),0) - override SOURCE_COUNT = $(words $(SOURCES)) +ifeq ($(shell find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o; echo $$?),0) + ifneq ($(wildcard $(BUILDDIR)/.*),) + SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null)) + override SOURCE_COUNT := $(shell expr $(SOURCE_COUNT) - $(words $(SKIPPED_SOURCES))) + ifeq ($(SOURCE_COUNT),0) + override SOURCE_COUNT = $(words $(SOURCES)) + endif endif + PROGRESS = expr $$(find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2 +else + PROGRESS = expr $$(find $(BUILDDIR) -type f -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2 endif -PROGRESS = expr $$(find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2 - P := %% #? Default Make From c88169fc855241bfa2d28d82f50d5c6450fc9fd7 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 14 Feb 2022 22:21:50 +0100 Subject: [PATCH 197/289] Makefile supress find test error --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7268fdc..37bde6b 100644 --- a/Makefile +++ b/Makefile @@ -139,7 +139,7 @@ SOURCE_COUNT := $(words $(SOURCES)) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) -ifeq ($(shell find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o; echo $$?),0) +ifeq ($(shell find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o >/dev/null 2>&1; echo $$?),0) ifneq ($(wildcard $(BUILDDIR)/.*),) SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null)) override SOURCE_COUNT := $(shell expr $(SOURCE_COUNT) - $(words $(SKIPPED_SOURCES))) From 58846af5169582692f95ee3244161b1f7a6caf9d Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 15 Feb 2022 06:58:22 +0100 Subject: [PATCH 198/289] Fixed: Process tree not redrawing properly --- src/btop_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 9992808..bf43cc5 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1412,10 +1412,10 @@ namespace Proc { width_left -= (ulen(p.name) + 1); } if (width_left > 7 and p.short_cmd != p.name) { - out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ')'; + out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ") "; width_left -= (ulen(p.short_cmd, true) + 3); } - out += Mv::to(y+2+lc, x+2+tree_size); + out += string(max(0, width_left), ' ') + Mv::to(y+2+lc, x+2+tree_size); } //? Common end of line string cpu_str = to_string(p.cpu_p); From 2aeae24b880651291a684f14bc7b9a356e8f3980 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 15 Feb 2022 07:11:22 +0100 Subject: [PATCH 199/289] Fixed: string to wstring conversion crash when string is too big --- src/btop_tools.cpp | 4 ++-- src/linux/btop_collect.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index ba82ab4..58c319b 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -171,7 +171,7 @@ namespace Tools { size_t wide_ulen(const string& str) { unsigned int chars = 0; std::wstring_convert> conv; - auto w_str = conv.from_bytes(str.c_str()); + auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); for (auto c : w_str) { chars += utf8::wcwidth(c); @@ -194,7 +194,7 @@ namespace Tools { if (len < 1 or str.empty()) return ""; if (wide) { std::wstring_convert> conv; - auto w_str = conv.from_bytes(str.c_str()); + auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); while (wide_ulen(w_str) > len) w_str.pop_back(); str = conv.to_bytes(w_str); diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 62ae505..3e165a8 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1493,7 +1493,13 @@ namespace Proc { pread.open(d.path() / "cmdline"); if (not pread.good()) continue; long_string.clear(); - while(getline(pread, long_string, '\0')) new_proc.cmd += long_string + ' '; + while(getline(pread, long_string, '\0')) { + new_proc.cmd += long_string + ' '; + if (new_proc.cmd.size() > 1000) { + new_proc.cmd.resize(1000); + break; + } + } pread.close(); if (not new_proc.cmd.empty()) new_proc.cmd.pop_back(); From 17979139c3c4f3dc197cb7c23370c7f807f25387 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 15 Feb 2022 18:39:36 +0100 Subject: [PATCH 200/289] v1.2.3 Bug fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcdc3d0..2588935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.2.3 + +* Changed: floating_humanizer() now show fractions when shortened and value is < 10 + +* Fixed: Process tree not redrawing properly + +* Fixed: string to wstring conversion crash when string is too big + ## v1.2.2 * Changed: Reverted uncolor() back to using regex to fix delay in opening menu when compiled with musl diff --git a/src/btop.cpp b/src/btop.cpp index 1504ecf..6a4942b 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.2"; + const string Version = "1.2.3"; int coreCount; string overlay; From f7860f9d1be6d2553d118d1d2edf4ac1df42e015 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 16 Feb 2022 08:06:24 +0100 Subject: [PATCH 201/289] Optimization: Proc::draw() --- src/btop_draw.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index bf43cc5..59c9486 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1024,6 +1024,7 @@ namespace Proc { int selected_pid = 0; string selected_name; unordered_flat_map p_graphs; + unordered_flat_map p_wide_cmd; unordered_flat_map p_counters; int counter = 0; Draw::TextEdit filter; @@ -1394,12 +1395,14 @@ namespace Proc { } } + if (not p_wide_cmd.contains(p.pid)) p_wide_cmd[p.pid] = ulen(p.cmd) != ulen(p.cmd, true); + //? Normal view line if (not proc_tree) { out += Mv::to(y+2+lc, x+1) + g_color + rjust(to_string(p.pid), 8) + ' ' + c_color + ljust(p.name, prog_size, true) + ' ' + end - + (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, true) + Mv::to(y+2+lc, x+11+prog_size+cmd_size) + ' ' : ""); + + (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, p_wide_cmd[p.pid]) + Mv::to(y+2+lc, x+11+prog_size+cmd_size) + ' ' : ""); } //? Tree view line else { @@ -1412,7 +1415,7 @@ namespace Proc { width_left -= (ulen(p.name) + 1); } if (width_left > 7 and p.short_cmd != p.name) { - out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ") "; + out += g_color + '(' + uresize(p.short_cmd, width_left - 3, p_wide_cmd[p.pid]) + ") "; width_left -= (ulen(p.short_cmd, true) + 3); } out += string(max(0, width_left), ' ') + Mv::to(y+2+lc, x+2+tree_size); @@ -1473,6 +1476,15 @@ namespace Proc { } p_graphs.compact(); p_counters.compact(); + + for (auto element = p_wide_cmd.begin(); element != p_wide_cmd.end();) { + if (rng::find(plist, element->first, &proc_info::pid) == plist.end()) { + element = p_wide_cmd.erase(element); + } + else + ++element; + } + p_wide_cmd.compact(); } if (selected == 0 and selected_pid != 0) { From 4e7a212f83205bc7432dcbf3399f013710d57fff Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 17 Feb 2022 22:28:10 +0100 Subject: [PATCH 202/289] Fixed: Ignore duplicate disks with same mountpoint --- src/linux/btop_collect.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 3e165a8..29d3396 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -885,6 +885,9 @@ namespace Mem { while (not diskread.eof()) { std::error_code ec; diskread >> dev >> mountpoint >> fstype; + diskread.ignore(SSmax, '\n'); + + if (v_contains(found, mountpoint)) continue; //? Match filter if not empty if (not filter.empty()) { @@ -918,7 +921,6 @@ namespace Mem { } } - diskread.ignore(SSmax, '\n'); } //? Remove disks no longer mounted or filtered out if (swap_disk and has_swap) found.push_back("swap"); @@ -1494,7 +1496,7 @@ namespace Proc { if (not pread.good()) continue; long_string.clear(); while(getline(pread, long_string, '\0')) { - new_proc.cmd += long_string + ' '; + new_proc.cmd += long_string + ' '; if (new_proc.cmd.size() > 1000) { new_proc.cmd.resize(1000); break; From 7b3d996a7347944956a31d4fbcea7a7d90df6e74 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 20 Feb 2022 00:27:03 +0100 Subject: [PATCH 203/289] Changed: Restrict command line for processes to 1000 characters to fix utf8 conversion errors --- src/freebsd/btop_collect.cpp | 6 +++++- src/osx/btop_collect.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 028dbe3..69a9dc6 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -1201,12 +1201,16 @@ namespace Proc { new_proc.name = kproc->ki_comm; char** argv = kvm_getargv(kd(), kproc, 0); if (argv) { - for (int i = 0; argv[i]; i++) { + for (int i = 0; argv[i] and cmp_less(new_proc.cmd.size(), 1000); i++) { new_proc.cmd += argv[i] + " "s; } if (not new_proc.cmd.empty()) new_proc.cmd.pop_back(); } if (new_proc.cmd.empty()) new_proc.cmd = new_proc.name; + if (new_proc.cmd.size() > 1000) { + new_proc.cmd.resize(1000); + new_proc.cmd.shrink_to_fit(); + } new_proc.ppid = kproc->ki_ppid; new_proc.cpu_s = round(kproc->ki_start.tv_sec); struct passwd *pwd = getpwuid(kproc->ki_uid); diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 2451ea6..1e427a5 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -1258,7 +1258,7 @@ namespace Proc { std::string_view proc_args(proc_chars.get(), argmax); if (size_t null_pos = proc_args.find('\0', sizeof(argc)); null_pos != string::npos) { if (size_t start_pos = proc_args.find_first_not_of('\0', null_pos); start_pos != string::npos) { - while (argc-- > 0 and null_pos != string::npos) { + while (argc-- > 0 and null_pos != string::npos and cmp_less(new_proc.cmd.size(), 1000)) { null_pos = proc_args.find('\0', start_pos); new_proc.cmd += (string)proc_args.substr(start_pos, null_pos - start_pos) + ' '; start_pos = null_pos + 1; @@ -1269,6 +1269,10 @@ namespace Proc { } } if (new_proc.cmd.empty()) new_proc.cmd = f_name; + if (new_proc.cmd.size() > 1000) { + new_proc.cmd.resize(1000); + new_proc.cmd.shrink_to_fit(); + } new_proc.ppid = kproc.kp_eproc.e_ppid; new_proc.cpu_s = kproc.kp_proc.p_starttime.tv_sec * 1'000'000 + kproc.kp_proc.p_starttime.tv_usec; struct passwd *pwd = getpwuid(kproc.kp_eproc.e_ucred.cr_uid); From 682313027f31ec3cee0320b593fb7181f4f1f850 Mon Sep 17 00:00:00 2001 From: mohammad hashemy Date: Mon, 21 Feb 2022 20:45:38 +0330 Subject: [PATCH 204/289] add "g" and "G" to vim keys --- README.md | 2 +- src/btop_config.cpp | 2 +- src/btop_draw.cpp | 4 ++-- src/btop_input.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 22b9cde..f444f5d 100644 --- a/README.md +++ b/README.md @@ -595,7 +595,7 @@ force_tty = False #* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" -#* Set to True to enable "h,j,k,l" keys for directional control in lists. +#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. #* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. vim_keys = False diff --git a/src/btop_config.cpp b/src/btop_config.cpp index c509a8a..8e55ad3 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -54,7 +54,7 @@ namespace Config { "#* Use withespace \" \" as separator between different presets.\n" "#* Example: \"cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty\""}, - {"vim_keys", "#* Set to True to enable \"h,j,k,l\" keys for directional control in lists.\n" + {"vim_keys", "#* Set to True to enable \"h,j,k,l,g,G\" keys for directional control in lists.\n" "#* Conflicting keys for h:\"help\" and k:\"kill\" is accessible while holding shift."}, {"rounded_corners", "#* Rounded corners on boxes, is ignored if TTY mode is ON."}, diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 59c9486..2fa300d 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1070,11 +1070,11 @@ namespace Proc { if (selected > 0 and start >= numpids - select_max) selected = select_max; else start = clamp(start + select_max, 0, max(0, numpids - select_max)); } - else if (cmd_key == "home") { + else if (cmd_key == "home" or (vim_keys and cmd_key == "g")) { start = 0; if (selected > 0) selected = 1; } - else if (cmd_key == "end") { + else if (cmd_key == "end" or (vim_keys and cmd_key == "G")) { start = max(0, numpids - select_max); if (selected > 0) selected = select_max; } diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 0694340..d21feec 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -416,7 +416,7 @@ namespace Input { Menu::show(Menu::Menus::SignalChoose); return; } - else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k"))) { + else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k", "g", "G"))) { proc_mouse_scroll: redraw = false; auto old_selected = Config::getI("proc_selected"); From b4334a590dbb259aa6c3ec7534263b7fd73fe3ec Mon Sep 17 00:00:00 2001 From: NMrocks Date: Wed, 23 Feb 2022 20:04:46 +0530 Subject: [PATCH 205/289] Fixed a string in the options menu The "Proc Sorting" option in the proc section of the options menu has "cpu direct" as the 7th option but the description of the option mentioned it using its older name, "cpu responsive". Changed this to "cpu direct" in the description. --- src/btop_menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 248a769..92aea75 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -550,10 +550,10 @@ namespace Menu { "Possible values:", "\"pid\", \"program\", \"arguments\", \"threads\",", "\"user\", \"memory\", \"cpu lazy\" and", - "\"cpu responsive\".", + "\"cpu direct\".", "", "\"cpu lazy\" updates top process over time.", - "\"cpu responsive\" updates top process", + "\"cpu direct\" updates top process", "directly."}, {"proc_reversed", "Reverse processes sorting order.", From 8dd587dac25a97df547891fb09c80a2057ecbf03 Mon Sep 17 00:00:00 2001 From: NMrocks Date: Wed, 23 Feb 2022 21:19:44 +0530 Subject: [PATCH 206/289] Fixed the "cpu responsive" string in btop_config.cpp as well See previous commit for more info --- src/btop_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 8e55ad3..61476e1 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -77,8 +77,8 @@ namespace Config { {"update_ms", "#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs."}, - {"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"cpu lazy\" \"cpu responsive\",\n" - "#* \"cpu lazy\" sorts top process over time (easier to follow), \"cpu responsive\" updates top process directly."}, + {"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"cpu lazy\" \"cpu direct\",\n" + "#* \"cpu lazy\" sorts top process over time (easier to follow), \"cpu direct\" updates top process directly."}, {"proc_reversed", "#* Reverse sorting order, True or False."}, From ccfbf182e3ff83c0768701f7f443fde705cfdcef Mon Sep 17 00:00:00 2001 From: mrdotx Date: Thu, 24 Feb 2022 11:55:16 +0100 Subject: [PATCH 207/289] fix: title_left symbol between auto and zero in the net box is not displayed --- src/btop_draw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 2fa300d..6fc9f8a 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -962,9 +962,9 @@ namespace Net { //? Interface selector and buttons - out += Mv::to(y, x+width - i_size - 10) + title_left + Fx::b + Theme::c("hi_fg") + "" + title_right - + Mv::to(y, x+width - i_size - 16) + title_left + Theme::c("hi_fg") + (net.stat.at("download").offset + net.stat.at("upload").offset > 0 ? Fx::b : "") + 'z' + + Mv::to(y, x+width - i_size - 15) + title_left + Theme::c("hi_fg") + (net.stat.at("download").offset + net.stat.at("upload").offset > 0 ? Fx::b : "") + 'z' + Theme::c("title") + "ero" + title_right; Input::mouse_mappings["b"] = {y, x+width - i_size - 9, 1, 3}; Input::mouse_mappings["n"] = {y, x+width - 6, 1, 3}; @@ -1662,4 +1662,4 @@ namespace Draw { box = createBox(x, y, width, height, Theme::c("proc_box"), true, "proc", "", 4); } } -} \ No newline at end of file +} From a98b031a0d8f789523f39ce38d86cdd47a1383db Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 27 Feb 2022 14:24:39 +0100 Subject: [PATCH 208/289] v1.2.4 Bug fixes --- CHANGELOG.md | 10 ++++++++++ src/btop.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2588935..9a3475a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.2.4 + +* Optimization: Proc::draw() + +* Fixed: Ignore duplicate disks with same mountpoint + +* Changed: Restrict command line for processes to 1000 characters to fix utf8 conversion errors + +* Added: add "g" and "G" to vim keys, by @mohi001 + ## v1.2.3 * Changed: floating_humanizer() now show fractions when shortened and value is < 10 diff --git a/src/btop.cpp b/src/btop.cpp index 6a4942b..7f13641 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.3"; + const string Version = "1.2.4"; int coreCount; string overlay; From 12d7ba9e303a971316b3f36726bc74d3dedbd2be Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 27 Feb 2022 09:36:34 -0500 Subject: [PATCH 209/289] Add files via upload --- themes/HotPurpleTrafficLight.theme | 94 ++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 themes/HotPurpleTrafficLight.theme diff --git a/themes/HotPurpleTrafficLight.theme b/themes/HotPurpleTrafficLight.theme new file mode 100644 index 0000000..317e8a4 --- /dev/null +++ b/themes/HotPurpleTrafficLight.theme @@ -0,0 +1,94 @@ +#HotPurpleTrafficLight +#by Pete Allebone - mess with the best... you know the rest. +#Designed to flash up bright red with danger when loads are high and attention is needed. + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#000000" + +# Main text color +theme[main_fg]="#d1d1e0" + +# Title color for boxes +theme[title]="#d1d1e0" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#9933ff" + +# Background color of selected item in processes box +theme[selected_bg]="#6666ff" + +# Foreground color of selected item in processes box +theme[selected_fg]="#d1d1e0" + +# Color of inactive/disabled text +theme[inactive_fg]="#9999ff" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#9933ff" + +# Background color of the percentage meters +theme[meter_bg]="#4d4dff" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#9933ff" + +# Cpu box outline color +theme[cpu_box]="#a64dff" + +# Memory/disks box outline color +theme[mem_box]="#a64dff" + +# Net up/down box outline color +theme[net_box]="#a64dff" + +# Processes box outline color +theme[proc_box]="#a64dff" + +# Box divider line and small boxes line color +theme[div_line]="#4d4dff" + +# Temperature graph colors +theme[temp_start]="#00ff00" +theme[temp_mid]="#ff9933" +theme[temp_end]="#ff0000" + +# CPU graph colors +theme[cpu_start]="#00ff00" +theme[cpu_mid]="#ccff66" +theme[cpu_end]="#ff0000" + +# Mem/Disk free meter +theme[free_end]="#00ff00" +theme[free_mid]="#ccff66" +theme[free_start]="#ff0000" + +# Mem/Disk cached meter +theme[cached_start]="#00ff00" +theme[cached_mid]="#ccff66" +theme[cached_end]="#ff0000" + +# Mem/Disk available meter +theme[available_start]="#00ff00" +theme[available_mid]="#ccff66" +theme[available_end]="#ff0000" + +# Mem/Disk used meter +theme[used_start]="#00ff00" +theme[used_mid]="#ccff66" +theme[used_end]="#ff0000" + +# Download graph colors +theme[download_start]="#00ff00" +theme[download_mid]="#ff9933" +theme[download_end]="#ff0000" + +# Upload graph colors +theme[upload_start]="#00ff00" +theme[upload_mid]="#ff9933" +theme[upload_end]="#ff0000" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#9999ff" +theme[process_mid]="#4d4dff" +theme[process_end]="#a64dff" + From 82f7294be9178127d3789e7c9c700e8e67fc04b2 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 27 Feb 2022 09:46:00 -0500 Subject: [PATCH 210/289] Add files via upload --- themes/HotPurpleTrafficLight.theme | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/HotPurpleTrafficLight.theme b/themes/HotPurpleTrafficLight.theme index 317e8a4..59f2c02 100644 --- a/themes/HotPurpleTrafficLight.theme +++ b/themes/HotPurpleTrafficLight.theme @@ -68,9 +68,9 @@ theme[cached_mid]="#ccff66" theme[cached_end]="#ff0000" # Mem/Disk available meter -theme[available_start]="#00ff00" +theme[available_start]="#ff0000" theme[available_mid]="#ccff66" -theme[available_end]="#ff0000" +theme[available_end]="#00ff00" # Mem/Disk used meter theme[used_start]="#00ff00" From 0ccc19aa8028f1dc0266c354ebb6ca462576cdb2 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 27 Feb 2022 09:48:31 -0500 Subject: [PATCH 211/289] Add files via upload --- HotPurpleTrafficLight.theme | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 HotPurpleTrafficLight.theme diff --git a/HotPurpleTrafficLight.theme b/HotPurpleTrafficLight.theme new file mode 100644 index 0000000..59f2c02 --- /dev/null +++ b/HotPurpleTrafficLight.theme @@ -0,0 +1,94 @@ +#HotPurpleTrafficLight +#by Pete Allebone - mess with the best... you know the rest. +#Designed to flash up bright red with danger when loads are high and attention is needed. + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#000000" + +# Main text color +theme[main_fg]="#d1d1e0" + +# Title color for boxes +theme[title]="#d1d1e0" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#9933ff" + +# Background color of selected item in processes box +theme[selected_bg]="#6666ff" + +# Foreground color of selected item in processes box +theme[selected_fg]="#d1d1e0" + +# Color of inactive/disabled text +theme[inactive_fg]="#9999ff" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#9933ff" + +# Background color of the percentage meters +theme[meter_bg]="#4d4dff" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#9933ff" + +# Cpu box outline color +theme[cpu_box]="#a64dff" + +# Memory/disks box outline color +theme[mem_box]="#a64dff" + +# Net up/down box outline color +theme[net_box]="#a64dff" + +# Processes box outline color +theme[proc_box]="#a64dff" + +# Box divider line and small boxes line color +theme[div_line]="#4d4dff" + +# Temperature graph colors +theme[temp_start]="#00ff00" +theme[temp_mid]="#ff9933" +theme[temp_end]="#ff0000" + +# CPU graph colors +theme[cpu_start]="#00ff00" +theme[cpu_mid]="#ccff66" +theme[cpu_end]="#ff0000" + +# Mem/Disk free meter +theme[free_end]="#00ff00" +theme[free_mid]="#ccff66" +theme[free_start]="#ff0000" + +# Mem/Disk cached meter +theme[cached_start]="#00ff00" +theme[cached_mid]="#ccff66" +theme[cached_end]="#ff0000" + +# Mem/Disk available meter +theme[available_start]="#ff0000" +theme[available_mid]="#ccff66" +theme[available_end]="#00ff00" + +# Mem/Disk used meter +theme[used_start]="#00ff00" +theme[used_mid]="#ccff66" +theme[used_end]="#ff0000" + +# Download graph colors +theme[download_start]="#00ff00" +theme[download_mid]="#ff9933" +theme[download_end]="#ff0000" + +# Upload graph colors +theme[upload_start]="#00ff00" +theme[upload_mid]="#ff9933" +theme[upload_end]="#ff0000" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#9999ff" +theme[process_mid]="#4d4dff" +theme[process_end]="#a64dff" + From 2536a676ff9d9ef2ed5f96eeaa4f533c1e9599d8 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 27 Feb 2022 12:49:13 -0500 Subject: [PATCH 212/289] Delete HotPurpleTrafficLight.theme --- HotPurpleTrafficLight.theme | 94 ------------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 HotPurpleTrafficLight.theme diff --git a/HotPurpleTrafficLight.theme b/HotPurpleTrafficLight.theme deleted file mode 100644 index 59f2c02..0000000 --- a/HotPurpleTrafficLight.theme +++ /dev/null @@ -1,94 +0,0 @@ -#HotPurpleTrafficLight -#by Pete Allebone - mess with the best... you know the rest. -#Designed to flash up bright red with danger when loads are high and attention is needed. - -# Main background, empty for terminal default, need to be empty if you want transparent background -theme[main_bg]="#000000" - -# Main text color -theme[main_fg]="#d1d1e0" - -# Title color for boxes -theme[title]="#d1d1e0" - -# Highlight color for keyboard shortcuts -theme[hi_fg]="#9933ff" - -# Background color of selected item in processes box -theme[selected_bg]="#6666ff" - -# Foreground color of selected item in processes box -theme[selected_fg]="#d1d1e0" - -# Color of inactive/disabled text -theme[inactive_fg]="#9999ff" - -# Color of text appearing on top of graphs, i.e uptime and current network graph scaling -theme[graph_text]="#9933ff" - -# Background color of the percentage meters -theme[meter_bg]="#4d4dff" - -# Misc colors for processes box including mini cpu graphs, details memory graph and details status text -theme[proc_misc]="#9933ff" - -# Cpu box outline color -theme[cpu_box]="#a64dff" - -# Memory/disks box outline color -theme[mem_box]="#a64dff" - -# Net up/down box outline color -theme[net_box]="#a64dff" - -# Processes box outline color -theme[proc_box]="#a64dff" - -# Box divider line and small boxes line color -theme[div_line]="#4d4dff" - -# Temperature graph colors -theme[temp_start]="#00ff00" -theme[temp_mid]="#ff9933" -theme[temp_end]="#ff0000" - -# CPU graph colors -theme[cpu_start]="#00ff00" -theme[cpu_mid]="#ccff66" -theme[cpu_end]="#ff0000" - -# Mem/Disk free meter -theme[free_end]="#00ff00" -theme[free_mid]="#ccff66" -theme[free_start]="#ff0000" - -# Mem/Disk cached meter -theme[cached_start]="#00ff00" -theme[cached_mid]="#ccff66" -theme[cached_end]="#ff0000" - -# Mem/Disk available meter -theme[available_start]="#ff0000" -theme[available_mid]="#ccff66" -theme[available_end]="#00ff00" - -# Mem/Disk used meter -theme[used_start]="#00ff00" -theme[used_mid]="#ccff66" -theme[used_end]="#ff0000" - -# Download graph colors -theme[download_start]="#00ff00" -theme[download_mid]="#ff9933" -theme[download_end]="#ff0000" - -# Upload graph colors -theme[upload_start]="#00ff00" -theme[upload_mid]="#ff9933" -theme[upload_end]="#ff0000" - -# Process box color gradient for threads, mem and cpu usage -theme[process_start]="#9999ff" -theme[process_mid]="#4d4dff" -theme[process_end]="#a64dff" - From 27791602ff8ec4ce5c055c1278d3e190d89d65e2 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 4 Mar 2022 19:39:06 +0100 Subject: [PATCH 213/289] Fixed: Fallback to less accurate UTF8 char count if conversion to wstring fails --- src/btop_tools.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 58c319b..e3d0597 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -170,11 +170,16 @@ namespace Tools { size_t wide_ulen(const string& str) { unsigned int chars = 0; - std::wstring_convert> conv; - auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); + try { + std::wstring_convert> conv; + auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); - for (auto c : w_str) { - chars += utf8::wcwidth(c); + for (auto c : w_str) { + chars += utf8::wcwidth(c); + } + } + catch (...) { + return ulen(str); } return chars; @@ -193,11 +198,17 @@ namespace Tools { string uresize(string str, const size_t len, const bool wide) { if (len < 1 or str.empty()) return ""; if (wide) { - std::wstring_convert> conv; - auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); - while (wide_ulen(w_str) > len) - w_str.pop_back(); - str = conv.to_bytes(w_str); + try { + std::wstring_convert> conv; + auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str())); + while (wide_ulen(w_str) > len) + w_str.pop_back(); + string n_str = conv.to_bytes(w_str); + return n_str; + } + catch (...) { + return uresize(str, len, false); + } } else { for (size_t x = 0, i = 0; i < str.size(); i++) { From 2b569266d3085230496ea15adabb8b30314af592 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 4 Mar 2022 20:22:46 +0100 Subject: [PATCH 214/289] Fixed: Small ui fixes for mem and disks --- src/btop_draw.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 2fa300d..9a46243 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -816,7 +816,7 @@ namespace Mem { const string humanized = floating_humanizer(mem.stats.at(name)); const string graphics = (use_graphs ? mem_graphs.at(name)(mem.percent.at(name), redraw or data_same) : mem_meters.at(name)(mem.percent.at(name).back())); if (mem_size > 2) { - out += Mv::to(y+1+cy, x+1+cx) + divider + ljust(title, 4, false, false, not big_mem) + ljust(":", (big_mem ? 1 : 6)) + out += Mv::to(y+1+cy, x+1+cx) + divider + title.substr(0, big_mem ? 10 : 5) + ":" + Mv::to(y+1+cy, x+cx + mem_width - 2 - humanized.size()) + trans(humanized) + Mv::to(y+2+cy, x+cx + (graph_height >= 2 ? 0 : 1)) + graphics + up + rjust(to_string(mem.percent.at(name).back()) + "%", 4); cy += (graph_height == 0 ? 2 : graph_height + 1); @@ -836,6 +836,7 @@ namespace Mem { cx = mem_width; cy = 0; const bool big_disk = disks_width >= 25; divider = Mv::l(1) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line * disks_width + Theme::c("mem_box") + Fx::ub + Symbols::div_right + Mv::l(disks_width); + const string hu_div = Theme::c("div_line") + Symbols::h_line + Theme::c("main_fg"); if (io_mode) { for (const auto& mount : mem.disks_order) { if (not disks.contains(mount)) continue; @@ -843,11 +844,11 @@ namespace Mem { const auto& disk = disks.at(mount); if (disk.io_read.empty()) continue; const string total = floating_humanizer(disk.total, not big_disk); - out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - total.size()) + out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 8) + Mv::to(y+1+cy, x+cx + disks_width - total.size()) + trans(total) + Fx::ub; if (big_disk) { const string used_percent = to_string(disk.used_percent); - out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2)) + Theme::c("main_fg") + used_percent + '%'; + out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2) - 1) + hu_div + used_percent + '%' + hu_div; } out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll)) + Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg"); @@ -878,21 +879,21 @@ namespace Mem { if (cy > height - 3) break; const auto& disk = disks.at(mount); auto comb_val = (not disk.io_read.empty() ? disk.io_read.back() + disk.io_write.back() : 0ll); - const string human_io = (comb_val > 0 and big_disk ? (disk.io_write.back() > 0 ? "▼"s : ""s) + (disk.io_read.back() > 0 ? "▲"s : ""s) + const string human_io = (comb_val > 0 ? (disk.io_write.back() > 0 and big_disk ? "▼"s : ""s) + (disk.io_read.back() > 0 and big_disk ? "▲"s : ""s) + floating_humanizer(comb_val, true) : ""); const string human_total = floating_humanizer(disk.total, not big_disk); const string human_used = floating_humanizer(disk.used, not big_disk); const string human_free = floating_humanizer(disk.free, not big_disk); - out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size()) + out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 8) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size()) + trans(human_total) + Fx::ub + Theme::c("main_fg"); if (big_disk and not human_io.empty()) - out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2)) + Theme::c("main_fg") + human_io; + out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2) - 1) + hu_div + human_io + hu_div; if (++cy > height - 3) break; if (show_io_stat and io_graphs.contains(mount + "_activity")) { out += Mv::to(y+1+cy, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll)) + Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg"); - if (not big_disk) out += Mv::to(y+1+cy, x+cx) + Theme::c("main_fg") + human_io; + if (not big_disk) out += Mv::to(y+1+cy, x+cx+1) + Theme::c("main_fg") + human_io; if (++cy > height - 3) break; } From 294b75316441da0610cadfa8b81bcba0f9f13ec6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 4 Mar 2022 20:26:04 +0100 Subject: [PATCH 215/289] Fixed: Mouse mappings for net box --- src/btop_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index a14e5f7..5bea6cb 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -967,9 +967,9 @@ namespace Net { + uresize(selected_iface, 10) + Theme::c("hi_fg") + " n>" + title_right + Mv::to(y, x+width - i_size - 15) + title_left + Theme::c("hi_fg") + (net.stat.at("download").offset + net.stat.at("upload").offset > 0 ? Fx::b : "") + 'z' + Theme::c("title") + "ero" + title_right; - Input::mouse_mappings["b"] = {y, x+width - i_size - 9, 1, 3}; + Input::mouse_mappings["b"] = {y, x+width - i_size - 8, 1, 3}; Input::mouse_mappings["n"] = {y, x+width - 6, 1, 3}; - Input::mouse_mappings["z"] = {y, x+width - i_size - 15, 1, 4}; + Input::mouse_mappings["z"] = {y, x+width - i_size - 14, 1, 4}; if (width - i_size - 20 > 6) { out += Mv::to(y, x+width - i_size - 21) + title_left + Theme::c("hi_fg") + (net_auto ? Fx::b : "") + 'a' + Theme::c("title") + "uto" + title_right; Input::mouse_mappings["a"] = {y, x+width - i_size - 20, 1, 4}; From 76e26b0c518e99a9e207e4167a1162d0c2adeb36 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 6 Mar 2022 00:27:23 +0100 Subject: [PATCH 216/289] v1.2.5 Bug fixes --- CHANGELOG.md | 12 ++++++++++++ src/btop.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a3475a..b1d54c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v1.2.5 + +* Fixed: Fallback to less accurate UTF8 char count if conversion to wstring fails + +* Fixed: Small ui fixes for mem and disks + +* Added: New theme HotPurpleTrafficLight, by @pallebone + +* Fixed: title_left symbol between auto and zero in the net box is not displayed, by @mrdotx + +* Fixed: Mouse mappings for net box + ## v1.2.4 * Optimization: Proc::draw() diff --git a/src/btop.cpp b/src/btop.cpp index 7f13641..f24df03 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.4"; + const string Version = "1.2.5"; int coreCount; string overlay; From c6c08708ec654f4f3ac6138cf0ab506f280d0335 Mon Sep 17 00:00:00 2001 From: mohammad hashemy Date: Mon, 7 Mar 2022 15:56:15 +0330 Subject: [PATCH 217/289] Fixed: Wrong memory unit when shorten and size is less than 10 --- src/btop_tools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index e3d0597..301e554 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -372,7 +372,7 @@ namespace Tools { } if (shorten) { auto f_pos = out.find('.'); - if (f_pos == 1 and out.size() > 3) out = out.substr(0,2) + to_string((int)round(stof(out.substr(2)) / 10)); + if (f_pos == 1 and out.size() > 3) out = to_string(round(stof(out) * 10) / 10).substr(0,3); else if (f_pos != string::npos) out = to_string((int)round(stof(out))); if (out.size() > 3) { out = to_string((int)(out[0] - '0') + 1); start++;} out.push_back(units[start][0]); From b0d5c0378711930c320e19def97307166d80b4d9 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 26 Mar 2022 03:00:54 +0100 Subject: [PATCH 218/289] Fixed: Use cpu cores avarage temp if missing cpu package temp for FreeBSD --- src/freebsd/btop_collect.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 69a9dc6..1cf7a1e 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -266,20 +266,25 @@ namespace Cpu { } void update_sensors() { - int temp; - size_t size = sizeof(temp); - sysctlbyname("hw.acpi.thermal.tz0.temperature", &temp, &size, NULL, 0); - temp = (temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero... - current_cpu.temp.at(0).push_back(temp); - if (current_cpu.temp.at(0).size() > 20) - current_cpu.temp.at(0).pop_front(); + int temp = 0; + int p_temp = 0; + int found = 0; + bool got_package = false; + size_t size = sizeof(p_temp); + if (sysctlbyname("hw.acpi.thermal.tz0.temperature", &p_temp, &size, NULL, 0) >= 0) { + got_package = true; + p_temp = (p_temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero... + } + size = sizeof(temp); for (int i = 0; i < Shared::coreCount; i++) { string s = "dev.cpu." + std::to_string(i) + ".temperature"; - if (sysctlbyname(s.c_str(), &temp, &size, NULL, 0) < 0) { - Logger::warning("Could not get temp sensor - maybe you need to load the coretemp module"); - } else { + if (sysctlbyname(s.c_str(), &temp, &size, NULL, 0) >= 0) { temp = (temp - 2732) / 10; + if (not got_package) { + p_temp += temp; + found++; + } if (cmp_less(i + 1, current_cpu.temp.size())) { current_cpu.temp.at(i + 1).push_back(temp); if (current_cpu.temp.at(i + 1).size() > 20) @@ -288,6 +293,11 @@ namespace Cpu { } } + if (not got_package) p_temp /= found; + current_cpu.temp.at(0).push_back(p_temp); + if (current_cpu.temp.at(0).size() > 20) + current_cpu.temp.at(0).pop_front(); + } string get_cpuHz() { From 87579be5d6d3d3dd1bf4989e1fcce1bb4b0cd7aa Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 6 Apr 2022 13:03:49 +0200 Subject: [PATCH 219/289] updated robin_hood.h to v3.11.5 --- include/robin_hood.h | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/include/robin_hood.h b/include/robin_hood.h index 511a308..0af031f 100644 --- a/include/robin_hood.h +++ b/include/robin_hood.h @@ -36,7 +36,7 @@ // see https://semver.org/ #define ROBIN_HOOD_VERSION_MAJOR 3 // for incompatible API changes #define ROBIN_HOOD_VERSION_MINOR 11 // for adding functionality in a backwards-compatible manner -#define ROBIN_HOOD_VERSION_PATCH 3 // for backwards-compatible bug fixes +#define ROBIN_HOOD_VERSION_PATCH 5 // for backwards-compatible bug fixes #include #include @@ -1820,6 +1820,12 @@ public: InsertionState::key_found != idxAndState.second); } + template + iterator emplace_hint(const_iterator position, Args&&... args) { + (void)position; + return emplace(std::forward(args)...).first; + } + template std::pair try_emplace(const key_type& key, Args&&... args) { return try_emplace_impl(key, std::forward(args)...); @@ -1831,16 +1837,15 @@ public: } template - std::pair try_emplace(const_iterator hint, const key_type& key, - Args&&... args) { + iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args) { (void)hint; - return try_emplace_impl(key, std::forward(args)...); + return try_emplace_impl(key, std::forward(args)...).first; } template - std::pair try_emplace(const_iterator hint, key_type&& key, Args&&... args) { + iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args) { (void)hint; - return try_emplace_impl(std::move(key), std::forward(args)...); + return try_emplace_impl(std::move(key), std::forward(args)...).first; } template @@ -1854,16 +1859,15 @@ public: } template - std::pair insert_or_assign(const_iterator hint, const key_type& key, - Mapped&& obj) { + iterator insert_or_assign(const_iterator hint, const key_type& key, Mapped&& obj) { (void)hint; - return insertOrAssignImpl(key, std::forward(obj)); + return insertOrAssignImpl(key, std::forward(obj)).first; } template - std::pair insert_or_assign(const_iterator hint, key_type&& key, Mapped&& obj) { + iterator insert_or_assign(const_iterator hint, key_type&& key, Mapped&& obj) { (void)hint; - return insertOrAssignImpl(std::move(key), std::forward(obj)); + return insertOrAssignImpl(std::move(key), std::forward(obj)).first; } std::pair insert(const value_type& keyval) { @@ -1871,10 +1875,20 @@ public: return emplace(keyval); } + iterator insert(const_iterator hint, const value_type& keyval) { + (void)hint; + return emplace(keyval).first; + } + std::pair insert(value_type&& keyval) { return emplace(std::move(keyval)); } + iterator insert(const_iterator hint, value_type&& keyval) { + (void)hint; + return emplace(std::move(keyval)).first; + } + // Returns 1 if key is found, 0 otherwise. size_t count(const key_type& key) const { // NOLINT(modernize-use-nodiscard) ROBIN_HOOD_TRACE(this) @@ -2308,13 +2322,14 @@ private: auto const numElementsWithBuffer = calcNumElementsWithBuffer(max_elements); - // calloc also zeroes everything + // malloc & zero mInfo. Faster than calloc everything. auto const numBytesTotal = calcNumBytesTotal(numElementsWithBuffer); ROBIN_HOOD_LOG("std::calloc " << numBytesTotal << " = calcNumBytesTotal(" << numElementsWithBuffer << ")") mKeyVals = reinterpret_cast( - detail::assertNotNull(std::calloc(1, numBytesTotal))); + detail::assertNotNull(std::malloc(numBytesTotal))); mInfo = reinterpret_cast(mKeyVals + numElementsWithBuffer); + std::memset(mInfo, 0, numBytesTotal - numElementsWithBuffer * sizeof(Node)); // set sentinel mInfo[numElementsWithBuffer] = 1; From 2d9399389cb3e967368f2d59f8387f09db90fda9 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 Apr 2022 08:13:39 +0200 Subject: [PATCH 220/289] Changed: Enter symbol to a more common variant --- src/btop_draw.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_draw.hpp b/src/btop_draw.hpp index 203eed1..e425845 100644 --- a/src/btop_draw.hpp +++ b/src/btop_draw.hpp @@ -52,7 +52,7 @@ namespace Symbols { const string down = "↓"; const string left = "←"; const string right = "→"; - const string enter = "↲"; + const string enter = "↵"; } namespace Draw { From df205fb23c4d27bbe67d7e1bca4e7ee6f0e56a2f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 Apr 2022 11:19:47 +0200 Subject: [PATCH 221/289] v1.2.6 Bug fixes --- CHANGELOG.md | 8 ++++++++ src/btop.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d54c2..6e9d63a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.2.6 + +* Fixed: Wrong memory unit when shorten and size is less than 10, by @mohi001 + +* Fixed: Use cpu cores avarage temp if missing cpu package temp for FreeBSD + +* Changed: Enter symbol to a more common variant + ## v1.2.5 * Fixed: Fallback to less accurate UTF8 char count if conversion to wstring fails diff --git a/src/btop.cpp b/src/btop.cpp index f24df03..b94fe4b 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.5"; + const string Version = "1.2.6"; int coreCount; string overlay; From 4bae3c4f864979d99acdd016f9de6167fe799403 Mon Sep 17 00:00:00 2001 From: "Jakob P. Liljenberg" Date: Wed, 13 Apr 2022 11:42:04 +0200 Subject: [PATCH 222/289] Update continuous-build-linux.yml Fix - Unsafe repository stop --- .github/workflows/continuous-build-linux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/continuous-build-linux.yml b/.github/workflows/continuous-build-linux.yml index 846aee8..af32d65 100644 --- a/.github/workflows/continuous-build-linux.yml +++ b/.github/workflows/continuous-build-linux.yml @@ -79,6 +79,9 @@ jobs: - name: Install build tools run: apk add --no-cache coreutils git make tar zstd + - name: Fix - Unsafe repository stop + run: git config --global --add safe.directory /__w/btop/btop + - name: Checkout source uses: actions/checkout@v2 From 0f117a0273271f45908485ea1eebfefd31afee4b Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 Apr 2022 20:43:35 +0200 Subject: [PATCH 223/289] Fixed: Disk IO stats for individual partitions instead of whole disk --- src/linux/btop_collect.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 29d3396..595404d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -911,12 +911,17 @@ namespace Mem { #endif if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); string devname = disks.at(mountpoint).dev.filename(); + int c = 0; while (devname.size() >= 2) { if (fs::exists("/sys/block/" + devname + "/stat", ec) and access(string("/sys/block/" + devname + "/stat").c_str(), R_OK) == 0) { - disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat"; + if (c > 0 and fs::exists("/sys/block/" + devname + '/' + disks.at(mountpoint).dev.filename().string() + "/stat", ec)) + disks.at(mountpoint).stat = "/sys/block/" + devname + '/' + disks.at(mountpoint).dev.filename().string() + "/stat"; + else + disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat"; break; } devname.resize(devname.size() - 1); + c++; } } From abc4fb25c3183b18283f2f1e0b9cb6091ef85dc9 Mon Sep 17 00:00:00 2001 From: abrasumente <345396594@qq.com> Date: Sun, 1 May 2022 01:08:27 +0800 Subject: [PATCH 224/289] Added: Case insensitive process filtering --- src/btop_tools.hpp | 10 ++++++++++ src/freebsd/btop_collect.cpp | 2 +- src/linux/btop_collect.cpp | 8 ++++---- src/osx/btop_collect.cpp | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 63723cc..862981a 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -187,6 +187,16 @@ namespace Tools { return str.find(find_val) != string::npos; } + //* Check if string contains string , while ignoring case + inline bool s_contains_ic(const string& str, const string& find_val) { + auto it = std::search( + str.begin(), str.end(), + find_val.begin(), find_val.end(), + [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); } + ); + return it != str.end(); + } + //* Return index of from vector , returns size of if is not present template inline size_t v_index(const vector& vec, const T& find_val) { diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 1cf7a1e..7c6c07c 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -1317,7 +1317,7 @@ namespace Proc { filter_found = 0; for (auto &p : current_procs) { if (not tree and not filter.empty()) { - if (not s_contains(to_string(p.pid), filter) and not s_contains(p.name, filter) and not s_contains(p.cmd, filter) and not s_contains(p.user, filter)) { + if (not s_contains_ic(to_string(p.pid), filter) and not s_contains_ic(p.name, filter) and not s_contains_ic(p.cmd, filter) and not s_contains_ic(p.user, filter)) { p.filtered = true; filter_found++; } else { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 595404d..680b2ce 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1700,10 +1700,10 @@ namespace Proc { filter_found = 0; for (auto& p : current_procs) { if (not tree and not filter.empty()) { - if (not s_contains(to_string(p.pid), filter) - and not s_contains(p.name, filter) - and not s_contains(p.cmd, filter) - and not s_contains(p.user, filter)) { + if (not s_contains_ic(to_string(p.pid), filter) + and not s_contains_ic(p.name, filter) + and not s_contains_ic(p.cmd, filter) + and not s_contains_ic(p.user, filter)) { p.filtered = true; filter_found++; } diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 1e427a5..c9dbcfe 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -1372,7 +1372,7 @@ namespace Proc { filter_found = 0; for (auto &p : current_procs) { if (not tree and not filter.empty()) { - if (not s_contains(to_string(p.pid), filter) and not s_contains(p.name, filter) and not s_contains(p.cmd, filter) and not s_contains(p.user, filter)) { + if (not s_contains_ic(to_string(p.pid), filter) and not s_contains_ic(p.name, filter) and not s_contains_ic(p.cmd, filter) and not s_contains_ic(p.user, filter)) { p.filtered = true; filter_found++; } else { @@ -1432,4 +1432,4 @@ namespace Tools { } return 0.0; } -} // namespace Tools \ No newline at end of file +} // namespace Tools From a7384483a4e9bc99009cfbf1f2898394ad4222ac Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Fri, 29 Apr 2022 22:08:00 -0500 Subject: [PATCH 225/289] Include ZFS ARC in cached/available memory on Linux --- src/btop_config.cpp | 3 +++ src/btop_menu.cpp | 9 +++++++++ src/linux/btop_collect.cpp | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 61476e1..137b168 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -141,6 +141,8 @@ namespace Config { {"mem_below_net", "#* Show mem box below net box instead of above."}, + {"zfs_arc_cached", "#* Count ZFS ARC in cached and available memory."}, + {"show_swap", "#* If swap memory should be shown in memory box."}, {"swap_disk", "#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk."}, @@ -230,6 +232,7 @@ namespace Config { {"background_update", true}, {"mem_graphs", true}, {"mem_below_net", false}, + {"zfs_arc_cached", true}, {"show_swap", true}, {"swap_disk", true}, {"show_disks", true}, diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 92aea75..65d1639 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -490,6 +490,15 @@ namespace Menu { "", "Example:", "\"exclude=/boot /home/user\""}, + {"zfs_arc_cached", + "(Linux) Count ZFS ARC as cached memory.", + "", + "Add ZFS ARC used to cached memory and", + "ZFS ARC available to available memory.", + "These are otherwise reported by the Linux", + "kernel as used memory.", + "", + "True or False."}, }, { {"graph_symbol_net", diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 595404d..4c82fef 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -732,6 +732,7 @@ namespace Mem { fs::file_time_type fstab_time; int disk_ios = 0; vector last_found; + const std::regex zfs_size_regex("^size\\s+\\d\\s+(\\d+)"); mem_info current_mem {}; @@ -754,11 +755,28 @@ namespace Mem { auto& show_swap = Config::getB("show_swap"); auto& swap_disk = Config::getB("swap_disk"); auto& show_disks = Config::getB("show_disks"); + auto& zfs_arc_cached = Config::getB("zfs_arc_cached"); auto totalMem = get_totalMem(); auto& mem = current_mem; mem.stats.at("swap_total") = 0; + //? Read ZFS ARC info from /proc/spl/kstat/zfs/arcstats + uint64_t arc_size = 0; + if (zfs_arc_cached) { + ifstream arcstats(Shared::procPath / "spl/kstat/zfs/arcstats"); + if (arcstats.good()) { + std::string line; + while (std::getline(arcstats, line)) { + std::smatch match; + if (std::regex_match(line, match, zfs_size_regex) && match.size() == 2) { + arc_size = stoull(match.str(1)); + } + } + } + arcstats.close(); + } + //? Read memory info from /proc/meminfo ifstream meminfo(Shared::procPath / "meminfo"); if (meminfo.good()) { @@ -790,6 +808,10 @@ namespace Mem { meminfo.ignore(SSmax, '\n'); } if (not got_avail) mem.stats.at("available") = mem.stats.at("free") + mem.stats.at("cached"); + if (zfs_arc_cached) { + mem.stats.at("cached") += arc_size; + mem.stats.at("available") += arc_size; + } mem.stats.at("used") = totalMem - mem.stats.at("available"); if (mem.stats.at("swap_total") > 0) mem.stats.at("swap_used") = mem.stats.at("swap_total") - mem.stats.at("swap_free"); } From af56d43c2bd710964b5147d6c628b9998777c16e Mon Sep 17 00:00:00 2001 From: Yonatan Avhar Date: Sat, 7 May 2022 14:09:00 +0300 Subject: [PATCH 226/289] Add btop.desktop --- btop.desktop | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 btop.desktop diff --git a/btop.desktop b/btop.desktop new file mode 100644 index 0000000..489c436 --- /dev/null +++ b/btop.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=btop +GenericName=System Monitor +Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes. +Icon=btop +Exec=btop +Terminal=true +Categories=System;Monitor;ConsoleOnly; +Keywords=system;process;task + From 41148527b9c3caa3ac8c863ccba7a5d561173539 Mon Sep 17 00:00:00 2001 From: Yonatan Avhar Date: Sat, 7 May 2022 14:48:03 +0300 Subject: [PATCH 227/289] Add desktop icon svg and png --- Img/icon.png | Bin 0 -> 1060 bytes Img/icon.svg | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 Img/icon.png create mode 100644 Img/icon.svg diff --git a/Img/icon.png b/Img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cba489022ebcd78cafd2cea5228180d592a145a4 GIT binary patch literal 1060 zcmV+<1l#+GP)D zu&_4|g2;j=7jGgG1ChX*$Yvu3IwXe{;$)KU`sE=p%x33Db#~%RlP?TY!>jjRf9dz5 zUJZD_!G{jqMSOhx_k(;=1EWUi35275fTg9SPXUAw50;mgzb&diaspYFeVOMujYi`E zP?*5TL+Ie(fGbz7V2m;6(H}X1BuTK=o?Cz91fCRLIgok{g?&mG3L26O_`gUd%?%=P&;w8T1{3~R<8Bi^CH}H@J2UTyWJ*95@u&- zy?vHG2TD)CD}>e|*Fxk*h>COWu}1bqo)g@^PXNs+_^Y3--yzPWv<{@TmXE8|Q<)Wl zz!>s8C(AOgvypEOR6^$}q3b?C)tm#Z0YV4Q4m8$Lt=eZAU|k5LlyK7Z2jOyr&_$zO zub-}KwOS$Fu^=!%KhOUD{(qrEmSx^V#)3eWWz5XX{H>Jw9**CF*7|E7-LW75ptasx zTU&dtsNUsB;uMaQl!sb~TDLy%tCU#Jd0@d9raOMWY7Db!N+f0d6L|9jxaa-!_zyG@ z*7nS*yJ5(YCxQ2^CG6+}Zz%=4y8z8S_>6)CN*_X{Cor@s)ND4r_EnPv4iCG^c5Aik z3sh|X5=2wI44YiDFt!)^Fs^1;~6ZClV8YYb~3$0d*>FMd0e0&a-KomvW z8yg$f`t5n9&p?x98EKj_H8th!v-CModIDY{^ar%Hln45FAb+fpy{;7D_BIlpz7D_i zv$YNl6$IKrXszXkO663h0bwmlDTEMSmwjFYEKEvk<4O;C)j7!X<0ZT@&}qj-^ud`1 z7@d3zA$qxc1eYU(E*cXP6J6In7z+Z8MuWqS=9cF<)sA7mAI5@!Qi?c^_l+?>0Yp)R z*7~lG?pP22&|2?oZEd|>RPS;mv4EeqP6rVtTkt5 zep5=_$n%_|9v58ag>w#LOtJEFg3^aj=?N67Le4qjI3|js!JGdl6nX=dN`-U&p*|2n e5O|$^&f;Gh2#l5_P|d3V0000 + + + + + + + + + + + + + + + + + + + + + + + + + + From fee972364b0e373f7099a29312dee8de48c7648d Mon Sep 17 00:00:00 2001 From: Yonatan Avhar Date: Sat, 7 May 2022 15:01:48 +0300 Subject: [PATCH 228/289] Update makefile to install/remove icons and desktop entry --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Makefile b/Makefile index 37bde6b..5ec3a45 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ else endif PREFIX ?= /usr/local +DESKTOPENTRY ?= /usr/share/applications/btop.desktop +ICONDIR ?= /usr/share/icons/hicolor #? Detect PLATFORM and ARCH from uname/gcc if not set PLATFORM ?= $(shell uname -s || echo unknown) @@ -212,6 +214,11 @@ install: @cp -p README.md $(DESTDIR)$(PREFIX)/share/btop @printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n" @cp -pr themes $(DESTDIR)$(PREFIX)/share/btop + @printf "\033[1;92mInstalling desktop entry to: \033[1;97m$(DESKTOPENTRY)\n" + @cp -p btop.desktop $(DESKTOPENTRY) + @printf "\033[1;92mInstalling icons to: \033[1;97m$(ICONDIR)\n" + @cp -p Img/icon.png $(ICONDIR)/48x48/apps/btop.png + @cp -p Img/icon.svg $(ICONDIR)/scalable/apps/btop.svg #? Set SUID bit for btop as $SU_USER in $SU_GROUP @@ -227,6 +234,12 @@ uninstall: @rm -rf $(DESTDIR)$(PREFIX)/bin/btop @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\033[0m\n" @rm -rf $(DESTDIR)$(PREFIX)/share/btop + @printf "\033[1;91mRemoving: \033[1;97m$(DESKTOPENTRY)\033[0m\n" + @rm -rf $(DESKTOPENTRY) + @printf "\033[1;91mRemoving: \033[1;97m$(ICONDIR)/48x48/btop.png\033[0m\n" + @rm -rf $(ICONDIR)/48x48/apps/btop.png + @printf "\033[1;91mRemoving: \033[1;97m$(ICONDIR)/scalable/btop.svg\033[0m\n" + @rm -rf $(ICONDIR)/scalable/apps/btop.svg #? Pull in dependency info for *existing* .o files -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) From b9cb628f9ca5a277f326677335ce728f5ed1d739 Mon Sep 17 00:00:00 2001 From: Yonatan Avhar Date: Sun, 8 May 2022 14:37:48 +0300 Subject: [PATCH 229/289] Fix makefile to install to /usr/local instead of /usr --- Makefile | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 5ec3a45..d1bc95d 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,6 @@ else endif PREFIX ?= /usr/local -DESKTOPENTRY ?= /usr/share/applications/btop.desktop -ICONDIR ?= /usr/share/icons/hicolor #? Detect PLATFORM and ARCH from uname/gcc if not set PLATFORM ?= $(shell uname -s || echo unknown) @@ -214,11 +212,15 @@ install: @cp -p README.md $(DESTDIR)$(PREFIX)/share/btop @printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n" @cp -pr themes $(DESTDIR)$(PREFIX)/share/btop - @printf "\033[1;92mInstalling desktop entry to: \033[1;97m$(DESKTOPENTRY)\n" - @cp -p btop.desktop $(DESKTOPENTRY) - @printf "\033[1;92mInstalling icons to: \033[1;97m$(ICONDIR)\n" - @cp -p Img/icon.png $(ICONDIR)/48x48/apps/btop.png - @cp -p Img/icon.svg $(ICONDIR)/scalable/apps/btop.svg + @printf "\033[1;92mInstalling desktop entry to: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\n" + @mkdir -p $(DESTDIR)$(PREFIX)/share/applications/ + @cp -p btop.desktop $(DESTDIR)$(PREFIX)/share/applications/btop.desktop + @printf "\033[1;92mInstalling PNG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\n" + @mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps + @cp -p Img/icon.png $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png + @printf "\033[1;92mInstalling SVG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\n" + @mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps + @cp -p Img/icon.svg $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg #? Set SUID bit for btop as $SU_USER in $SU_GROUP @@ -234,12 +236,12 @@ uninstall: @rm -rf $(DESTDIR)$(PREFIX)/bin/btop @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\033[0m\n" @rm -rf $(DESTDIR)$(PREFIX)/share/btop - @printf "\033[1;91mRemoving: \033[1;97m$(DESKTOPENTRY)\033[0m\n" - @rm -rf $(DESKTOPENTRY) - @printf "\033[1;91mRemoving: \033[1;97m$(ICONDIR)/48x48/btop.png\033[0m\n" - @rm -rf $(ICONDIR)/48x48/apps/btop.png - @printf "\033[1;91mRemoving: \033[1;97m$(ICONDIR)/scalable/btop.svg\033[0m\n" - @rm -rf $(ICONDIR)/scalable/apps/btop.svg + @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\033[0m\n" + @rm -rf $(DESTDIR)$(PREFIX)/share/applications/btop.desktop + @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\033[0m\n" + @rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png + @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\033[0m\n" + @rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg #? Pull in dependency info for *existing* .o files -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) From e1341a17cbaa222acff46deb6f95606db242d34f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 20 May 2022 23:35:41 +0300 Subject: [PATCH 230/289] Moved to correct version of the code --- src/btop_config.cpp | 4 ++++ src/linux/btop_collect.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 137b168..6b5f88b 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -1,3 +1,4 @@ +// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); @@ -96,6 +97,8 @@ namespace Config { {"proc_left", "#* Show proc box on left side of screen instead of right."}, + {"proc_filter_kernel", "#* Filter processes tied to the Linux kernel(similar behavior to htop)."}, + {"cpu_graph_upper", "#* Sets the CPU stat shown in upper half of the CPU graph, \"total\" is always available.\n" "#* Select from a list of detected attributes from the options menu."}, @@ -222,6 +225,7 @@ namespace Config { {"proc_mem_bytes", true}, {"proc_info_smaps", false}, {"proc_left", false}, + {"proc_filter_kernel", false}, {"cpu_invert_lower", true}, {"cpu_single_graph", false}, {"cpu_bottom", false}, diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 95028eb..45363fa 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -4,7 +4,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -15,6 +15,7 @@ indent = tab tab-size = 4 */ +// clang-format off #include #include @@ -1258,6 +1259,19 @@ namespace Proc { int filter_found = 0; detail_container detailed; + uint64_t kthreadd_pid{}; + + static void filter_kernel(const bool& should_filter) { + if (!should_filter) { + return; + } + + // Filter out kernel processes + auto keraser = rng::remove_if(current_procs, [](const proc_info& curr) { + return curr.pid == kthreadd_pid || curr.ppid == kthreadd_pid; + }); + current_procs.erase(keraser.begin(), keraser.end()); + } //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1425,6 +1439,7 @@ namespace Proc { const auto& reverse = Config::getB("proc_reversed"); const auto& filter = Config::getS("proc_filter"); const auto& per_core = Config::getB("proc_per_core"); + const auto& should_filter_kernel = Config::getB("proc_filter_kernel"); const auto& tree = Config::getB("proc_tree"); const auto& show_detailed = Config::getB("show_detailed"); const size_t detailed_pid = Config::getI("detailed_pid"); @@ -1489,8 +1504,8 @@ namespace Proc { //? Iterate over all pids in /proc vector found; for (const auto& d: fs::directory_iterator(Shared::procPath)) { - if (Runner::stopping) - return current_procs; + if (Runner::stopping) +return current_procs; if (pread.is_open()) pread.close(); const string pid_str = d.path().filename(); @@ -1515,6 +1530,9 @@ namespace Proc { pread.open(d.path() / "comm"); if (not pread.good()) continue; getline(pread, new_proc.name); + if (new_proc.name == "kthreadd") { + kthreadd_pid = new_proc.pid; + } pread.close(); //? Check for whitespace characters in name and set offset to get correct fields from stat file new_proc.name_offset = rng::count(new_proc.name, ' '); @@ -1671,6 +1689,8 @@ namespace Proc { old_cputimes = cputimes; } + + filter_kernel(should_filter_kernel); // Filter here to make sorting faster. //* ---------------------------------------------Collection done----------------------------------------------- //* Sort processes From ba0b34db3f45e754876da64ec806f0fa4d6487c1 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 20 May 2022 23:46:49 +0300 Subject: [PATCH 231/289] Added TUI option for kernel proc filtering. --- src/btop_menu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 65d1639..4dd4cf3 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -1,3 +1,4 @@ +// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); @@ -598,6 +599,10 @@ namespace Menu { " ", "Will show percentage of total memory", "if False."}, + {"proc_filter_kernel", + "Filter kernel processes from output", + "", + "Removes processes most users don't care about."}, } }; From e70dbc1bce7b870389d28dd675982e806160efae Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 20 May 2022 23:48:59 +0300 Subject: [PATCH 232/289] Fixed some formatting issues. --- src/linux/btop_collect.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 45363fa..a9efd64 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1,10 +1,11 @@ +// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -15,7 +16,6 @@ indent = tab tab-size = 4 */ -// clang-format off #include #include @@ -1505,7 +1505,7 @@ namespace Proc { vector found; for (const auto& d: fs::directory_iterator(Shared::procPath)) { if (Runner::stopping) -return current_procs; + return current_procs; if (pread.is_open()) pread.close(); const string pid_str = d.path().filename(); From c0f60841595b1c7f08241b70f26ba0159ed388c4 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 20 May 2022 23:54:07 +0300 Subject: [PATCH 233/289] Replaced $*\s with tabs --- src/linux/btop_collect.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index a9efd64..ec2b2cb 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -5,7 +5,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -1259,19 +1259,19 @@ namespace Proc { int filter_found = 0; detail_container detailed; - uint64_t kthreadd_pid{}; + uint64_t kthreadd_pid{}; - static void filter_kernel(const bool& should_filter) { - if (!should_filter) { - return; - } + static void filter_kernel(const bool& should_filter) { + if (!should_filter) { + return; + } - // Filter out kernel processes - auto keraser = rng::remove_if(current_procs, [](const proc_info& curr) { - return curr.pid == kthreadd_pid || curr.ppid == kthreadd_pid; - }); - current_procs.erase(keraser.begin(), keraser.end()); - } + // Filter out kernel processes + auto keraser = rng::remove_if(current_procs, [](const proc_info& curr) { + return curr.pid == kthreadd_pid || curr.ppid == kthreadd_pid; + }); + current_procs.erase(keraser.begin(), keraser.end()); + } //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1439,7 +1439,7 @@ namespace Proc { const auto& reverse = Config::getB("proc_reversed"); const auto& filter = Config::getS("proc_filter"); const auto& per_core = Config::getB("proc_per_core"); - const auto& should_filter_kernel = Config::getB("proc_filter_kernel"); + const auto& should_filter_kernel = Config::getB("proc_filter_kernel"); const auto& tree = Config::getB("proc_tree"); const auto& show_detailed = Config::getB("show_detailed"); const size_t detailed_pid = Config::getI("detailed_pid"); @@ -1505,7 +1505,7 @@ namespace Proc { vector found; for (const auto& d: fs::directory_iterator(Shared::procPath)) { if (Runner::stopping) - return current_procs; + return current_procs; if (pread.is_open()) pread.close(); const string pid_str = d.path().filename(); @@ -1530,9 +1530,9 @@ namespace Proc { pread.open(d.path() / "comm"); if (not pread.good()) continue; getline(pread, new_proc.name); - if (new_proc.name == "kthreadd") { - kthreadd_pid = new_proc.pid; - } + if (new_proc.name == "kthreadd") { + kthreadd_pid = new_proc.pid; + } pread.close(); //? Check for whitespace characters in name and set offset to get correct fields from stat file new_proc.name_offset = rng::count(new_proc.name, ' '); @@ -1690,7 +1690,7 @@ namespace Proc { old_cputimes = cputimes; } - filter_kernel(should_filter_kernel); // Filter here to make sorting faster. + filter_kernel(should_filter_kernel); // Filter here to make sorting faster. //* ---------------------------------------------Collection done----------------------------------------------- //* Sort processes From 7b50543be3de9ccf3649bb0498da0a043bffbb8a Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 14:37:21 +0300 Subject: [PATCH 234/289] Made kernel process filtering more efficient --- src/linux/btop_collect.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index ec2b2cb..daf1a6b 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1,4 +1,3 @@ -// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); @@ -1259,19 +1258,7 @@ namespace Proc { int filter_found = 0; detail_container detailed; - uint64_t kthreadd_pid{}; - - static void filter_kernel(const bool& should_filter) { - if (!should_filter) { - return; - } - - // Filter out kernel processes - auto keraser = rng::remove_if(current_procs, [](const proc_info& curr) { - return curr.pid == kthreadd_pid || curr.ppid == kthreadd_pid; - }); - current_procs.erase(keraser.begin(), keraser.end()); - } + constexpr size_t KTHREADD = 2ull; //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1512,6 +1499,10 @@ namespace Proc { if (not isdigit(pid_str[0])) continue; const size_t pid = stoul(pid_str); + + if (should_filter_kernel && pid == KTHREADD) { + continue; + } found.push_back(pid); //? Check if pid already exists in current_procs @@ -1530,9 +1521,6 @@ namespace Proc { pread.open(d.path() / "comm"); if (not pread.good()) continue; getline(pread, new_proc.name); - if (new_proc.name == "kthreadd") { - kthreadd_pid = new_proc.pid; - } pread.close(); //? Check for whitespace characters in name and set offset to get correct fields from stat file new_proc.name_offset = rng::count(new_proc.name, ' '); @@ -1608,7 +1596,7 @@ namespace Proc { continue; case 4: //? Parent pid new_proc.ppid = stoull(short_str); - next_x = 14; +next_x = 14; continue; case 14: //? Process utime cpu_t = stoull(short_str); @@ -1647,6 +1635,11 @@ namespace Proc { catch (const std::out_of_range&) { continue; } pread.close(); + + if (should_filter_kernel && new_proc.ppid == KTHREADD) { + current_procs.pop_back(); + found.pop_back(); + } if (x-offset < 24) continue; @@ -1690,7 +1683,6 @@ namespace Proc { old_cputimes = cputimes; } - filter_kernel(should_filter_kernel); // Filter here to make sorting faster. //* ---------------------------------------------Collection done----------------------------------------------- //* Sort processes From 82948c06c1fbb1397025f4926bc11b4beec20623 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 14:40:10 +0300 Subject: [PATCH 235/289] Fixed clang-format off labels --- src/btop_config.cpp | 1 - src/btop_menu.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 6b5f88b..3a66093 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -1,4 +1,3 @@ -// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 4dd4cf3..f8cfd58 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -1,4 +1,3 @@ -// clang-format off /* Copyright 2021 Aristocratos (jakob@qvantnet.com) Licensed under the Apache License, Version 2.0 (the "License"); From 271750999fb6b9b5096fe6fd9fa19e38dfd9fa70 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 14:41:26 +0300 Subject: [PATCH 236/289] Added linux label on the config option --- src/btop_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 3a66093..d555c6a 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -96,7 +96,7 @@ namespace Config { {"proc_left", "#* Show proc box on left side of screen instead of right."}, - {"proc_filter_kernel", "#* Filter processes tied to the Linux kernel(similar behavior to htop)."}, + {"proc_filter_kernel", "#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop)."}, {"cpu_graph_upper", "#* Sets the CPU stat shown in upper half of the CPU graph, \"total\" is always available.\n" "#* Select from a list of detected attributes from the options menu."}, From af0706778212719f9268a4b51d8d8f33734a1ea6 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 14:56:23 +0300 Subject: [PATCH 237/289] Fixed menu description --- src/btop_menu.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index f8cfd58..6dd420c 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -599,9 +599,10 @@ namespace Menu { "Will show percentage of total memory", "if False."}, {"proc_filter_kernel", - "Filter kernel processes from output", - "", - "Removes processes most users don't care about."}, + "(Linux) Filter kernel processes from output.", + "", + "Set to 'True' to filter out internal", + "processes started by the Linux kernel."}, } }; From d53998f37cb34f8e0dab29abe9315e75ad84c23e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 15:03:07 +0300 Subject: [PATCH 238/289] Woops that went unnoticed, didn't it? --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index daf1a6b..8f9d16e 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1258,7 +1258,7 @@ namespace Proc { int filter_found = 0; detail_container detailed; - constexpr size_t KTHREADD = 2ull; + constexpr size_t KTHREADD = 2; //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { From f340fa6a48aa5d23e9f4b8c65a9becd02a26fe66 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 15:06:03 +0300 Subject: [PATCH 239/289] Indentation fix. --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 8f9d16e..20e3500 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1596,7 +1596,7 @@ namespace Proc { continue; case 4: //? Parent pid new_proc.ppid = stoull(short_str); -next_x = 14; + next_x = 14; continue; case 14: //? Process utime cpu_t = stoull(short_str); From 224c065eedcc71bb00d8bae6b17cab78c3153049 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 15:14:16 +0300 Subject: [PATCH 240/289] Replaced my spaces with tabs --- src/linux/btop_collect.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 20e3500..8302018 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -4,7 +4,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -1258,7 +1258,7 @@ namespace Proc { int filter_found = 0; detail_container detailed; - constexpr size_t KTHREADD = 2; + constexpr size_t KTHREADD = 2; //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1491,18 +1491,18 @@ namespace Proc { //? Iterate over all pids in /proc vector found; for (const auto& d: fs::directory_iterator(Shared::procPath)) { - if (Runner::stopping) - return current_procs; + if (Runner::stopping) + return current_procs; if (pread.is_open()) pread.close(); const string pid_str = d.path().filename(); if (not isdigit(pid_str[0])) continue; const size_t pid = stoul(pid_str); - - if (should_filter_kernel && pid == KTHREADD) { - continue; - } + + if (should_filter_kernel && pid == KTHREADD) { + continue; + } found.push_back(pid); //? Check if pid already exists in current_procs @@ -1596,7 +1596,7 @@ namespace Proc { continue; case 4: //? Parent pid new_proc.ppid = stoull(short_str); - next_x = 14; + next_x = 14; continue; case 14: //? Process utime cpu_t = stoull(short_str); @@ -1635,11 +1635,11 @@ namespace Proc { catch (const std::out_of_range&) { continue; } pread.close(); - - if (should_filter_kernel && new_proc.ppid == KTHREADD) { - current_procs.pop_back(); - found.pop_back(); - } + + if (should_filter_kernel && new_proc.ppid == KTHREADD) { + current_procs.pop_back(); + found.pop_back(); + } if (x-offset < 24) continue; @@ -1682,7 +1682,6 @@ namespace Proc { old_cputimes = cputimes; } - //* ---------------------------------------------Collection done----------------------------------------------- //* Sort processes From 3e097faecc821512f1c58ab5fc6bac09c91b2a30 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 21 May 2022 15:16:35 +0300 Subject: [PATCH 241/289] More indentation --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 8302018..e2bfe92 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -4,7 +4,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, From 7eae5fcd2cde86930f6e395c3853546d86fcc52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20J=C3=A4ger?= Date: Sun, 22 May 2022 13:05:39 +0200 Subject: [PATCH 242/289] Added tokyo-night & tokyo-storm theme --- themes/tokyo-night.theme | 81 ++++++++++++++++++++++++++++++++++++++++ themes/tokyo-storm.theme | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 themes/tokyo-night.theme create mode 100644 themes/tokyo-storm.theme diff --git a/themes/tokyo-night.theme b/themes/tokyo-night.theme new file mode 100644 index 0000000..aae6a3b --- /dev/null +++ b/themes/tokyo-night.theme @@ -0,0 +1,81 @@ +# Theme: tokyo-night +# By: Pascal Jaeger + +# Main bg +theme[main_bg]="#1a1b26" + +# Main text color +theme[main_fg]="#cfc9c2" + +# Title color for boxes +theme[title]="#cfc9c2" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#7dcfff" + +# Background color of selected item in processes box +theme[selected_bg]="#414868" + +# Foreground color of selected item in processes box +theme[selected_fg]="#cfc9c2" + +# Color of inactive/disabled text +theme[inactive_fg]="#565f89" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#7dcfff" + +# Cpu box outline color +theme[cpu_box]="#565f89" + +# Memory/disks box outline color +theme[mem_box]="#565f89" + +# Net up/down box outline color +theme[net_box]="#565f89" + +# Processes box outline color +theme[proc_box]="#565f89" + +# Box divider line and small boxes line color +theme[div_line]="#565f89" + +# Temperature graph colors +theme[temp_start]="#9ece6a" +theme[temp_mid]="#e0af68" +theme[temp_end]="#f7768e" + +# CPU graph colors +theme[cpu_start]="#9ece6a" +theme[cpu_mid]="#e0af68" +theme[cpu_end]="#f7768e" + +# Mem/Disk free meter +theme[free_start]="#9ece6a" +theme[free_mid]="#e0af68" +theme[free_end]="#f7768e" + +# Mem/Disk cached meter +theme[cached_start]="#9ece6a" +theme[cached_mid]="#e0af68" +theme[cached_end]="#f7768e" + +# Mem/Disk available meter +theme[available_start]="#9ece6a" +theme[available_mid]="#e0af68" +theme[available_end]="#f7768e" + +# Mem/Disk used meter +theme[used_start]="#9ece6a" +theme[used_mid]="#e0af68" +theme[used_end]="#f7768e" + +# Download graph colors +theme[download_start]="#9ece6a" +theme[download_mid]="#e0af68" +theme[download_end]="#f7768e" + +# Upload graph colors +theme[upload_start]="#9ece6a" +theme[upload_mid]="#e0af68" +theme[upload_end]="#f7768e" diff --git a/themes/tokyo-storm.theme b/themes/tokyo-storm.theme new file mode 100644 index 0000000..a4edfcf --- /dev/null +++ b/themes/tokyo-storm.theme @@ -0,0 +1,81 @@ +# Theme: tokyo-storm +# By: Pascal Jaeger + +# Main bg +theme[main_bg]="#24283b" + +# Main text color +theme[main_fg]="#cfc9c2" + +# Title color for boxes +theme[title]="#cfc9c2" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#7dcfff" + +# Background color of selected item in processes box +theme[selected_bg]="#414868" + +# Foreground color of selected item in processes box +theme[selected_fg]="#cfc9c2" + +# Color of inactive/disabled text +theme[inactive_fg]="#565f89" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#7dcfff" + +# Cpu box outline color +theme[cpu_box]="#565f89" + +# Memory/disks box outline color +theme[mem_box]="#565f89" + +# Net up/down box outline color +theme[net_box]="#565f89" + +# Processes box outline color +theme[proc_box]="#565f89" + +# Box divider line and small boxes line color +theme[div_line]="#565f89" + +# Temperature graph colors +theme[temp_start]="#9ece6a" +theme[temp_mid]="#e0af68" +theme[temp_end]="#f7768e" + +# CPU graph colors +theme[cpu_start]="#9ece6a" +theme[cpu_mid]="#e0af68" +theme[cpu_end]="#f7768e" + +# Mem/Disk free meter +theme[free_start]="#9ece6a" +theme[free_mid]="#e0af68" +theme[free_end]="#f7768e" + +# Mem/Disk cached meter +theme[cached_start]="#9ece6a" +theme[cached_mid]="#e0af68" +theme[cached_end]="#f7768e" + +# Mem/Disk available meter +theme[available_start]="#9ece6a" +theme[available_mid]="#e0af68" +theme[available_end]="#f7768e" + +# Mem/Disk used meter +theme[used_start]="#9ece6a" +theme[used_mid]="#e0af68" +theme[used_end]="#f7768e" + +# Download graph colors +theme[download_start]="#9ece6a" +theme[download_mid]="#e0af68" +theme[download_end]="#f7768e" + +# Upload graph colors +theme[upload_start]="#9ece6a" +theme[upload_mid]="#e0af68" +theme[upload_end]="#f7768e" From 8ed8d43f5a582deee6cfe2880b06cfdd71e8e7b1 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 24 May 2022 12:01:33 +0300 Subject: [PATCH 243/289] Added caching for kernel processes. --- src/linux/btop_collect.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index e2bfe92..95c4b92 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -16,6 +16,7 @@ indent = tab tab-size = 4 */ +#include "robin_hood.h" #include #include #include @@ -1258,8 +1259,21 @@ namespace Proc { int filter_found = 0; detail_container detailed; + static robin_hood::unordered_set kernels_procs{}; constexpr size_t KTHREADD = 2; + // Clearing the cache is used in the event of a pid wrap around. + // In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. + static void clear_kernel_cache() { + static size_t latest_clear_time = 0; + + if (latest_clear_time >= static_cast(Config::getI("update_ms") * 100)) { + kernels_procs.clear(); + latest_clear_time = 0; + } + + latest_clear_time++; + } //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { auto cur_pos = out_procs.size(); @@ -1453,6 +1467,8 @@ namespace Proc { //* ---------------------------------------------Collection start---------------------------------------------- else { should_filter = true; + // First make sure kernel proc cache is cleared. + clear_kernel_cache(); auto totalMem = Mem::get_totalMem(); int totalMem_len = to_string(totalMem >> 10).size(); @@ -1500,7 +1516,7 @@ namespace Proc { const size_t pid = stoul(pid_str); - if (should_filter_kernel && pid == KTHREADD) { + if (should_filter_kernel && (pid == KTHREADD || kernels_procs.contains(pid))) { continue; } found.push_back(pid); @@ -1637,8 +1653,10 @@ namespace Proc { pread.close(); if (should_filter_kernel && new_proc.ppid == KTHREADD) { + kernels_procs.emplace(new_proc.pid); current_procs.pop_back(); found.pop_back(); + continue; } if (x-offset < 24) continue; From 2b4000b8572694fac64d61b2e43a083d3bbe0846 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 24 May 2022 15:42:59 +0300 Subject: [PATCH 244/289] Added a check for filter kernel mode --- src/linux/btop_collect.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 95c4b92..7a0fe8b 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -16,7 +16,7 @@ indent = tab tab-size = 4 */ -#include "robin_hood.h" +#include #include #include #include @@ -1274,6 +1274,7 @@ namespace Proc { latest_clear_time++; } + //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { auto cur_pos = out_procs.size(); @@ -1467,8 +1468,11 @@ namespace Proc { //* ---------------------------------------------Collection start---------------------------------------------- else { should_filter = true; + // First make sure kernel proc cache is cleared. - clear_kernel_cache(); + if (should_filter_kernel) { + clear_kernel_cache(); + } auto totalMem = Mem::get_totalMem(); int totalMem_len = to_string(totalMem >> 10).size(); @@ -1519,6 +1523,7 @@ namespace Proc { if (should_filter_kernel && (pid == KTHREADD || kernels_procs.contains(pid))) { continue; } + found.push_back(pid); //? Check if pid already exists in current_procs From 7291c7dfdca7d27ee5f8413ff2782e000b60d514 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 28 May 2022 20:48:02 +0200 Subject: [PATCH 245/289] Fixed: Net sync scale bug --- src/btop_config.cpp | 2 +- src/linux/btop_collect.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 137b168..3b3af2f 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -243,7 +243,7 @@ namespace Config { {"base_10_sizes", false}, {"io_graph_combined", false}, {"net_auto", true}, - {"net_sync", false}, + {"net_sync", true}, {"show_battery", true}, {"vim_keys", false}, {"tty_mode", false}, diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 95028eb..bb3b764 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1153,6 +1153,7 @@ namespace Net { //? Set counters for auto scaling if (net_auto and selected_iface == iface) { + if (net_sync and saved_stat.speed < net.at(iface).stat.at(dir == "download" ? "upload" : "download").speed) continue; if (saved_stat.speed > graph_max[dir]) { ++max_count[dir][0]; if (max_count[dir][1] > 0) --max_count[dir][1]; From c3eb02f27f69f2cd03d5ec9ddc8ce7dc8eda3de8 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 28 May 2022 21:08:30 +0200 Subject: [PATCH 246/289] v1.2.7 Bug fixes & new features --- CHANGELOG.md | 14 ++++++++++++++ src/btop.cpp | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e9d63a..571b693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.2.7 + +* Fixed: Disk IO stats for individual partitions instead of whole disk (Linux) + +* Added: Case insensitive process filtering, by @abrasumente233 + +* Added: Include ZFS ARC in cached/available memory on Linux, by @mattico + +* Added: Desktop entry and icons, by @yonatan8070 + +* Fixed: Net sync scale bug + +* Added: tokyo-night & tokyo-storm themes, by @Schievel1 + ## v1.2.6 * Fixed: Wrong memory unit when shorten and size is less than 10, by @mohi001 diff --git a/src/btop.cpp b/src/btop.cpp index b94fe4b..ff59748 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.6"; + const string Version = "1.2.7"; int coreCount; string overlay; From 482734766a207195a9905c400578841b6f104ba4 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 29 May 2022 16:09:55 +0300 Subject: [PATCH 247/289] Finished kernel proc filtering. --- src/linux/btop_collect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 7a0fe8b..d55c8b8 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1267,7 +1267,7 @@ namespace Proc { static void clear_kernel_cache() { static size_t latest_clear_time = 0; - if (latest_clear_time >= static_cast(Config::getI("update_ms") * 100)) { + if (latest_clear_time >= 256) { kernels_procs.clear(); latest_clear_time = 0; } From d916e064d13c5d8826196652df5b379fd9047711 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 29 May 2022 16:11:27 +0300 Subject: [PATCH 248/289] Changed spaces to tabs --- src/linux/btop_collect.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index d55c8b8..7fcd3d0 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1259,21 +1259,21 @@ namespace Proc { int filter_found = 0; detail_container detailed; - static robin_hood::unordered_set kernels_procs{}; + static robin_hood::unordered_set kernels_procs{}; constexpr size_t KTHREADD = 2; - // Clearing the cache is used in the event of a pid wrap around. - // In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. - static void clear_kernel_cache() { - static size_t latest_clear_time = 0; - - if (latest_clear_time >= 256) { - kernels_procs.clear(); - latest_clear_time = 0; - } - - latest_clear_time++; - } + // Clearing the cache is used in the event of a pid wrap around. + // In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. + static void clear_kernel_cache() { + static size_t latest_clear_time = 0; + + if (latest_clear_time >= 256) { + kernels_procs.clear(); + latest_clear_time = 0; + } + + latest_clear_time++; + } //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1469,10 +1469,10 @@ namespace Proc { else { should_filter = true; - // First make sure kernel proc cache is cleared. - if (should_filter_kernel) { - clear_kernel_cache(); - } + // First make sure kernel proc cache is cleared. + if (should_filter_kernel) { + clear_kernel_cache(); + } auto totalMem = Mem::get_totalMem(); int totalMem_len = to_string(totalMem >> 10).size(); @@ -1658,10 +1658,10 @@ namespace Proc { pread.close(); if (should_filter_kernel && new_proc.ppid == KTHREADD) { - kernels_procs.emplace(new_proc.pid); + kernels_procs.emplace(new_proc.pid); current_procs.pop_back(); found.pop_back(); - continue; + continue; } if (x-offset < 24) continue; From fc8ac1590aa038097bbeddbd8f15eb98291d803b Mon Sep 17 00:00:00 2001 From: mapi68 <41143572+mapi68@users.noreply.github.com> Date: Mon, 30 May 2022 09:34:24 +0200 Subject: [PATCH 249/289] Update btop.desktop Hello, I propose these changes in btop.desktop: line 4: "Name" supports special character, so it's possible to write full name with "++" line 6: "Comment" no need dot (.) at the end added italian translation of "GenericName" and "Comment" Regards --- btop.desktop | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/btop.desktop b/btop.desktop index 489c436..3771b21 100644 --- a/btop.desktop +++ b/btop.desktop @@ -1,12 +1,13 @@ [Desktop Entry] Type=Application Version=1.0 -Name=btop +Name=btop++ GenericName=System Monitor -Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes. +GenericName[it]=Monitor di sistema +Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes +Comment[it]=Monitoraggio delle risorse: mostra utilizzo e statistiche per CPU, dischi, rete e processi Icon=btop Exec=btop Terminal=true Categories=System;Monitor;ConsoleOnly; Keywords=system;process;task - From e60a5123b9cd2fdc7d04512791fa507d826dbed9 Mon Sep 17 00:00:00 2001 From: 00davidr Date: Thu, 2 Jun 2022 11:39:57 +0200 Subject: [PATCH 250/289] Update README.md update on Color standards for terminal emulators --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f444f5d..3520962 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ Any support is greatly appreciated! For best experience, a terminal with support for: -* 24-bit truecolor ([See list of terminals with truecolor support](https://gist.github.com/XVilka/8346728)) +* 24-bit truecolor ([See list of terminals with truecolor support](https://github.com//termstandard/colors)) * 256-color terminals are supported through 24-bit to 256-color conversion when setting "truecolor" to False in the options or with "-lc/--low-color" arguments. * 16 color TTY mode will be activated if a real tty device is detected. Can be forced with "-t/--tty_on" arguments. * Wide characters (Are sometimes problematic in web-based terminals) From 40db134273b0056baaaacb419fabbe698b0e9979 Mon Sep 17 00:00:00 2001 From: iambeingtracked <94642304+iambeingtracked@users.noreply.github.com> Date: Tue, 7 Jun 2022 17:32:39 +0300 Subject: [PATCH 251/289] Add everforest-dark-hard.theme Add an everforest dark hard theme --- themes/everforest-dark-hard.theme | 93 +++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 themes/everforest-dark-hard.theme diff --git a/themes/everforest-dark-hard.theme b/themes/everforest-dark-hard.theme new file mode 100644 index 0000000..51a5a03 --- /dev/null +++ b/themes/everforest-dark-hard.theme @@ -0,0 +1,93 @@ +# Btop everforest dark hard theme by u/archontop. + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#2b3339" + +# Main text color +theme[main_fg]="#d3c6aa" + +# Title color for boxes +theme[title]="#d3c6aa" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#e67e80" + +# Background color of selected items +theme[selected_bg]="#4b565c" + +# Foreground color of selected items +theme[selected_fg]="#dbbc7f" + +# Color of inactive/disabled text +theme[inactive_fg]="#2b3339" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#d3c6aa" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#a7c080" + +# Cpu box outline color +theme[cpu_box]="#4b565c" + +# Memory/disks box outline color +theme[mem_box]="#4b565c" + +# Net up/down box outline color +theme[net_box]="#4b565c" + +# Processes box outline color +theme[proc_box]="#4b565c" + +# Box divider line and small boxes line color +theme[div_line]="#4b565c" + +# Temperature graph colors +theme[temp_start]="#a7c080" +theme[temp_mid]="#dbbc7f" +theme[temp_end]="#f85552" + +# CPU graph colors +theme[cpu_start]="#a7c080" +theme[cpu_mid]="#dbbc7f" +theme[cpu_end]="#f85552" + +# Mem/Disk free meter +theme[free_start]="#f85552" +theme[free_mid]="#dbbc7f" +theme[free_end]="#a7c080" + +# Mem/Disk cached meter +theme[cached_start]="#7fbbb3" +theme[cached_mid]="#83c092" +theme[cached_end]="#a7c080" + +# Mem/Disk available meter +theme[available_start]="#f85552" +theme[available_mid]="#dbbc7f" +theme[available_end]="#a7c080" + +# Mem/Disk used meter +theme[used_start]="#a7c080" +theme[used_mid]="#dbbc7f" +theme[used_end]="#f85552" + +# Download graph colors +theme[download_start]="#8da101" +theme[download_mid]="#83c092" +theme[download_end]="#a7c080" + +# Upload graph colors +theme[upload_start]="#f85552" +theme[upload_mid]="#dbbc7f" +theme[upload_end]="#a7c080" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#a7c080" +theme[process_mid]="#f85552" +theme[process_end]="#CC241D" From 7d86602ede5381805b8f16bed90f871a1199362f Mon Sep 17 00:00:00 2001 From: "Jakob P. Liljenberg" Date: Tue, 21 Jun 2022 14:42:06 +0200 Subject: [PATCH 252/289] Changed: Disable battery monitoring if it fails instead of exiting --- src/linux/btop_collect.cpp | 87 ++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index bb3b764..8f23ed4 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -513,52 +513,57 @@ namespace Cpu { //? Get paths to needed files and check for valid values on first run if (batteries.empty() and has_battery) { - if (fs::exists("/sys/class/power_supply")) { - for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { - //? Only consider online power supplies of type Battery or UPS - //? see kernel docs for details on the file structure and contents - //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power - battery new_bat; - fs::path bat_dir; - try { - if (not d.is_directory() - or not fs::exists(d.path() / "type") - or not fs::exists(d.path() / "present") - or stoi(readfile(d.path() / "present")) != 1) + try { + if (fs::exists("/sys/class/power_supply")) { + for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { + //? Only consider online power supplies of type Battery or UPS + //? see kernel docs for details on the file structure and contents + //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power + battery new_bat; + fs::path bat_dir; + try { + if (not d.is_directory() + or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "present") + or stoi(readfile(d.path() / "present")) != 1) + continue; + string dev_type = readfile(d.path() / "type"); + if (is_in(dev_type, "Battery", "UPS")) { + bat_dir = d.path(); + new_bat.base_dir = d.path(); + new_bat.device_type = dev_type; + } + } catch (...) { + //? skip power supplies not conforming to the kernel standard continue; - string dev_type = readfile(d.path() / "type"); - if (is_in(dev_type, "Battery", "UPS")) { - bat_dir = d.path(); - new_bat.base_dir = d.path(); - new_bat.device_type = dev_type; } - } catch (...) { - //? skip power supplies not conforming to the kernel standard - continue; + + if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; + else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; + else new_bat.use_energy = false; + + if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; + else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; + else new_bat.use_energy = false; + + if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { + continue; + } + + if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; + else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; + + if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; + else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; + + batteries[bat_dir.filename()] = new_bat; + Config::available_batteries.push_back(bat_dir.filename()); } - - if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; - else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; - else new_bat.use_energy = false; - - if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; - else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; - else new_bat.use_energy = false; - - if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { - continue; - } - - if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; - else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; - - if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; - else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; - - batteries[bat_dir.filename()] = new_bat; - Config::available_batteries.push_back(bat_dir.filename()); } } + catch (...) { + batteries.clear(); + } if (batteries.empty()) { has_battery = false; return {0, 0, ""}; From fbba6b69d38f1891e56cf329a3263750a3df9752 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Sat, 25 Jun 2022 18:12:35 +0300 Subject: [PATCH 253/289] Added support for ZFS pool io stats monitoring --- src/btop_shared.hpp | 1 + src/linux/btop_collect.cpp | 101 ++++++++++++++++++++++++++----------- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 22c6204..d6fd847 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -131,6 +131,7 @@ namespace Mem { struct disk_info { std::filesystem::path dev; string name; + string fstype; std::filesystem::path stat = ""; int64_t total = 0, used = 0, free = 0; int used_percent = 0, free_percent = 0; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 8f23ed4..89566bc 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -929,14 +929,15 @@ namespace Mem { found.push_back(mountpoint); if (not v_contains(last_found, mountpoint)) redraw = true; - //? Save mountpoint, name, dev path and path to /sys/block stat file + //? Save mountpoint, name, fstype, dev path and path to /sys/block stat file if (not disks.contains(mountpoint)) { - disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename()}; + disks[mountpoint] = disk_info{fs::canonical(dev, ec), fs::path(mountpoint).filename(), fstype}; if (disks.at(mountpoint).dev.empty()) disks.at(mountpoint).dev = dev; #ifdef SNAPPED if (mountpoint == "/mnt") disks.at(mountpoint).name = "root"; #endif if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); + disks.at(mountpoint).fstype = fstype; string devname = disks.at(mountpoint).dev.filename(); int c = 0; while (devname.size() >= 2) { @@ -946,6 +947,11 @@ namespace Mem { else disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat"; break; + //? Set ZFS stat filepath + } else if (fs::exists("/proc/spl/kstat/zfs/" + devname + "/io", ec) and access(string("/proc/spl/kstat/zfs/" + devname + "/io").c_str(), R_OK) == 0) { + Logger::warning("Adding ZFS stat path for " + (string)dev); + disks.at(mountpoint).stat = "/proc/spl/kstat/zfs/" + devname + "/io"; + break; } devname.resize(devname.size() - 1); c++; @@ -993,7 +999,7 @@ namespace Mem { #endif if (swap_disk and has_swap) { mem.disks_order.push_back("swap"); - if (not disks.contains("swap")) disks["swap"] = {"", "swap"}; + if (not disks.contains("swap")) disks["swap"] = {"", "swap", "swap"}; disks.at("swap").total = mem.stats.at("swap_total"); disks.at("swap").used = mem.stats.at("swap_used"); disks.at("swap").free = mem.stats.at("swap_free"); @@ -1008,39 +1014,76 @@ namespace Mem { #endif //? Get disks IO - int64_t sectors_read, sectors_write, io_ticks; + int64_t sectors_read, sectors_write, io_ticks, io_ticks_read, io_ticks_write; disk_ios = 0; for (auto& [ignored, disk] : disks) { if (disk.stat.empty() or access(disk.stat.c_str(), R_OK) != 0) continue; diskread.open(disk.stat); if (diskread.good()) { - disk_ios++; - for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } - diskread >> sectors_read; - if (disk.io_read.empty()) - disk.io_read.push_back(0); - else - disk.io_read.push_back(max((int64_t)0, (sectors_read - disk.old_io.at(0)) * 512)); - disk.old_io.at(0) = sectors_read; - while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + //? ZFS Pool Support + if (disk.fstype == "zfs") { + disk_ios++; + for (int i = 0; i < 18; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> sectors_read; // nbytes read + Logger::warning("ZFS device " + (string)disk.name + " read bytes: " + to_string(sectors_read)); + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (sectors_read - disk.old_io.at(0)))); + disk.old_io.at(0) = sectors_read; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); - for (int i = 0; i < 3; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } - diskread >> sectors_write; - if (disk.io_write.empty()) - disk.io_write.push_back(0); - else - disk.io_write.push_back(max((int64_t)0, (sectors_write - disk.old_io.at(1)) * 512)); - disk.old_io.at(1) = sectors_write; - while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + diskread >> sectors_write; // nbytes written + Logger::warning("ZFS device " + (string)disk.name + " write bytes: " + to_string(sectors_write)); + if (disk.io_write.empty()) + disk.io_write.push_back(0); + else + disk.io_write.push_back(max((int64_t)0, (sectors_write - disk.old_io.at(1)))); + disk.old_io.at(1) = sectors_write; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); - for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } - diskread >> io_ticks; - if (disk.io_activity.empty()) - disk.io_activity.push_back(0); - else - disk.io_activity.push_back(clamp((long)round((double)(io_ticks - disk.old_io.at(2)) / (uptime - old_uptime) / 10), 0l, 100l)); - disk.old_io.at(2) = io_ticks; - while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> io_ticks_write; + for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> io_ticks_read; + io_ticks = io_ticks_write + io_ticks_read; + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(clamp((long)round((double)(io_ticks - disk.old_io.at(2)) / (uptime - old_uptime) / 10), 0l, 100l)); + disk.old_io.at(2) = io_ticks; + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + } else { + disk_ios++; + for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> sectors_read; + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (sectors_read - disk.old_io.at(0)) * 512)); + disk.old_io.at(0) = sectors_read; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + + for (int i = 0; i < 3; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> sectors_write; + if (disk.io_write.empty()) + disk.io_write.push_back(0); + else + disk.io_write.push_back(max((int64_t)0, (sectors_write - disk.old_io.at(1)) * 512)); + disk.old_io.at(1) = sectors_write; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + + for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + diskread >> io_ticks; + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(clamp((long)round((double)(io_ticks - disk.old_io.at(2)) / (uptime - old_uptime) / 10), 0l, 100l)); + disk.old_io.at(2) = io_ticks; + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + } + } else { + Logger::warning("Error in Mem::collect() : when opening " + (string)disk.stat); } diskread.close(); } From a88671b68f7570dd6d6049d0467e86659bae6b7c Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Sat, 25 Jun 2022 20:02:01 +0300 Subject: [PATCH 254/289] Remove forgotten debug logger calls --- src/linux/btop_collect.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 89566bc..d7fa740 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -949,7 +949,6 @@ namespace Mem { break; //? Set ZFS stat filepath } else if (fs::exists("/proc/spl/kstat/zfs/" + devname + "/io", ec) and access(string("/proc/spl/kstat/zfs/" + devname + "/io").c_str(), R_OK) == 0) { - Logger::warning("Adding ZFS stat path for " + (string)dev); disks.at(mountpoint).stat = "/proc/spl/kstat/zfs/" + devname + "/io"; break; } @@ -1025,7 +1024,6 @@ namespace Mem { disk_ios++; for (int i = 0; i < 18; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } diskread >> sectors_read; // nbytes read - Logger::warning("ZFS device " + (string)disk.name + " read bytes: " + to_string(sectors_read)); if (disk.io_read.empty()) disk.io_read.push_back(0); else @@ -1034,7 +1032,6 @@ namespace Mem { while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); diskread >> sectors_write; // nbytes written - Logger::warning("ZFS device " + (string)disk.name + " write bytes: " + to_string(sectors_write)); if (disk.io_write.empty()) disk.io_write.push_back(0); else From d402f4cecea37a3674367de1af9cd6a50f7cd398 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Sat, 25 Jun 2022 20:07:13 +0300 Subject: [PATCH 255/289] Remove duplicate fstype setter --- src/linux/btop_collect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index d7fa740..890b3fa 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -937,7 +937,6 @@ namespace Mem { if (mountpoint == "/mnt") disks.at(mountpoint).name = "root"; #endif if (disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == "/" ? "root" : mountpoint); - disks.at(mountpoint).fstype = fstype; string devname = disks.at(mountpoint).dev.filename(); int c = 0; while (devname.size() >= 2) { From 126e89bf17d1494023d815ba9cc04c8f441913ea Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Mon, 27 Jun 2022 19:12:23 +0300 Subject: [PATCH 256/289] fix identation --- src/btop_shared.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index d6fd847..caef8bf 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -131,7 +131,7 @@ namespace Mem { struct disk_info { std::filesystem::path dev; string name; - string fstype; + string fstype; std::filesystem::path stat = ""; int64_t total = 0, used = 0, free = 0; int used_percent = 0, free_percent = 0; From f67365d493c0f45414f39eee222d89e111ab6cfb Mon Sep 17 00:00:00 2001 From: Appuchia <46938448+appuchias@users.noreply.github.com> Date: Tue, 28 Jun 2022 20:35:55 +0200 Subject: [PATCH 257/289] Add tomorrow night theme --- themes/tomorrow-night.theme | 89 +++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 themes/tomorrow-night.theme diff --git a/themes/tomorrow-night.theme b/themes/tomorrow-night.theme new file mode 100644 index 0000000..a745005 --- /dev/null +++ b/themes/tomorrow-night.theme @@ -0,0 +1,89 @@ +#Nord theme but using the Tomorrow Night palette +#by Appuchia + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#ffffff", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#1d1f21" + +# Main text color +theme[main_fg]="#c5c8c6" + +# Title color for boxes +theme[title]="#c5c8c6" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#81beb7" + +# Background color of selected item in processes box +theme[selected_bg]="#282a2e" + +# Foreground color of selected item in processes box +theme[selected_fg]="#c5c8c6" + +# Color of inactive/disabled text +theme[inactive_fg]="#373b41" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#969896" + +# Cpu box outline color +theme[cpu_box]="#81a2be" + +# Memory/disks box outline color +theme[mem_box]="#81a2be" + +# Net up/down box outline color +theme[net_box]="#81a2be" + +# Processes box outline color +theme[proc_box]="#81a2be" + +# Box divider line and small boxes line color +theme[div_line]="#81a2be" + +# Temperature graph colors +theme[temp_start]="#b5bd68" +theme[temp_mid]="#f0c674" +theme[temp_end]="#cc6666" + +# CPU graph colors +theme[cpu_start]="#b5bd68" +theme[cpu_mid]="#f0c674" +theme[cpu_end]="#cc6666" + +# Mem/Disk free meter +theme[free_start]="#b5bd68" +theme[free_mid]="#f0c674" +theme[free_end]="#cc6666" + +# Mem/Disk cached meter +theme[cached_start]="#b5bd68" +theme[cached_mid]="#f0c674" +theme[cached_end]="#cc6666" + +# Mem/Disk available meter +theme[available_start]="#b5bd68" +theme[available_mid]="#f0c674" +theme[available_end]="#cc6666" + +# Mem/Disk used meter +theme[used_start]="#b5bd68" +theme[used_mid]="#f0c674" +theme[used_end]="#cc6666" + +# Download graph colors +theme[download_start]="#b5bd68" +theme[download_mid]="#f0c674" +theme[download_end]="#cc6666" + +# Upload graph colors +theme[upload_start]="#b5bd68" +theme[upload_mid]="#f0c674" +theme[upload_end]="#cc6666" From b450293f7f479a8f4b66f1633208e6ce0481e50d Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Jun 2022 09:43:17 +0200 Subject: [PATCH 258/289] Optimize away clear_kernel_cache() function --- src/linux/btop_collect.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index f8ceb65..e438300 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1268,19 +1268,6 @@ namespace Proc { static robin_hood::unordered_set kernels_procs{}; constexpr size_t KTHREADD = 2; - // Clearing the cache is used in the event of a pid wrap around. - // In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. - static void clear_kernel_cache() { - static size_t latest_clear_time = 0; - - if (latest_clear_time >= 256) { - kernels_procs.clear(); - latest_clear_time = 0; - } - - latest_clear_time++; - } - //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { auto cur_pos = out_procs.size(); @@ -1467,6 +1454,8 @@ namespace Proc { const int cmult = (per_core) ? Shared::coreCount : 1; bool got_detailed = false; + static size_t proc_clear_count = 0; + //* Use pids from last update if only changing filter, sorting or tree options if (no_update and not current_procs.empty()) { if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, round(uptime), current_procs); @@ -1475,9 +1464,12 @@ namespace Proc { else { should_filter = true; - // First make sure kernel proc cache is cleared. - if (should_filter_kernel) { - clear_kernel_cache(); + //? First make sure kernel proc cache is cleared. + if (should_filter_kernel and ++proc_clear_count >= 256) { + //? Clearing the cache is used in the event of a pid wrap around. + //? In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. + kernels_procs.clear(); + proc_clear_count = 0; } auto totalMem = Mem::get_totalMem(); From f35d36ab6c29781a61b1c7b264bddbca149dae6d Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Jun 2022 09:54:28 +0200 Subject: [PATCH 259/289] Fixed kernel proc filter clearing issue + optimization --- src/linux/btop_collect.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index e438300..1d96491 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1265,8 +1265,8 @@ namespace Proc { int filter_found = 0; detail_container detailed; - static robin_hood::unordered_set kernels_procs{}; constexpr size_t KTHREADD = 2; + static robin_hood::unordered_set kernels_procs = {KTHREADD}; //* Generate process tree list void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { @@ -1468,7 +1468,8 @@ namespace Proc { if (should_filter_kernel and ++proc_clear_count >= 256) { //? Clearing the cache is used in the event of a pid wrap around. //? In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. - kernels_procs.clear(); + kernels_procs.clear(); + kernels_procs.emplace(KTHREADD); proc_clear_count = 0; } @@ -1518,7 +1519,7 @@ namespace Proc { const size_t pid = stoul(pid_str); - if (should_filter_kernel && (pid == KTHREADD || kernels_procs.contains(pid))) { + if (should_filter_kernel and kernels_procs.contains(pid)) { continue; } @@ -1655,11 +1656,9 @@ namespace Proc { pread.close(); - if (should_filter_kernel && new_proc.ppid == KTHREADD) { + if (should_filter_kernel and new_proc.ppid == KTHREADD) { kernels_procs.emplace(new_proc.pid); - current_procs.pop_back(); - found.pop_back(); - continue; + found.pop_back(); } if (x-offset < 24) continue; @@ -1688,7 +1687,7 @@ namespace Proc { } } - //? Clear dead processes from current_procs + //? Clear dead processes from current_procs and remove kernel processes if enabled auto eraser = rng::remove_if(current_procs, [&](const auto& element){ return not v_contains(found, element.pid); }); current_procs.erase(eraser.begin(), eraser.end()); From aeea53518b90dd99d771d23c77329ef8668fa26b Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:42:27 +0300 Subject: [PATCH 260/289] use Shared::procPath, fix Logger error type --- src/linux/btop_collect.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 890b3fa..ccb35d3 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -947,8 +947,8 @@ namespace Mem { disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat"; break; //? Set ZFS stat filepath - } else if (fs::exists("/proc/spl/kstat/zfs/" + devname + "/io", ec) and access(string("/proc/spl/kstat/zfs/" + devname + "/io").c_str(), R_OK) == 0) { - disks.at(mountpoint).stat = "/proc/spl/kstat/zfs/" + devname + "/io"; + } else if (fs::exists(Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io", ec) and access(string(Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io").c_str(), R_OK) == 0) { + disks.at(mountpoint).stat = Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io"; break; } devname.resize(devname.size() - 1); @@ -1079,7 +1079,7 @@ namespace Mem { while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); } } else { - Logger::warning("Error in Mem::collect() : when opening " + (string)disk.stat); + Logger::debug("Error in Mem::collect() : when opening " + (string)disk.stat); } diskread.close(); } From 102b6dbc9d33906319e7c710cf58ba2893d6ec49 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 29 Jun 2022 18:59:27 +0200 Subject: [PATCH 261/289] v1.2.8 New features & themes --- CHANGELOG.md | 12 ++++++++++++ src/btop.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 571b693..dacbb53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v1.2.8 + +* Added: Support for ZFS pool io stats monitoring, by @simplepad + +* Added: Filtering of kernel processes, by @0xJoeMama + +* Added: New theme everforest-dark-hard, by @iambeingtracked + +* Added: New theme tomorrow-night, by @appuchias + +* Changed: Disable battery monitoring if it fails instead of exiting + ## v1.2.7 * Fixed: Disk IO stats for individual partitions instead of whole disk (Linux) diff --git a/src/btop.cpp b/src/btop.cpp index ff59748..b114753 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -60,7 +60,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.2.7"; + const string Version = "1.2.8"; int coreCount; string overlay; From d8d7e408146e6d6525db9a9266f6f3d67e3155bd Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Fri, 1 Jul 2022 18:35:41 +0300 Subject: [PATCH 262/289] Add zfs_pools_only option --- src/btop_config.cpp | 3 +++ src/btop_menu.cpp | 7 +++++++ src/linux/btop_collect.cpp | 1 + 3 files changed, 11 insertions(+) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 6ffc483..6cc2a6c 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -155,6 +155,8 @@ namespace Config { {"use_fstab", "#* Read disks list from /etc/fstab. This also disables only_physical."}, + {"zfs_pools_only", "#* Only show ZFS pools. Setting this to True will hide all datasets, and only show ZFS pools."}, + {"disk_free_priv", "#* Set to true to show available disk space for privileged users."}, {"show_io_stat", "#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view."}, @@ -241,6 +243,7 @@ namespace Config { {"show_disks", true}, {"only_physical", true}, {"use_fstab", true}, + {"zfs_pools_only", false}, {"show_io_stat", true}, {"io_mode", false}, {"base_10_sizes", false}, diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 6dd420c..99972ef 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -469,6 +469,13 @@ namespace Menu { "This also disables only_physical.", "", "True or False."}, + {"zfs_pools_only", + "(Linux) Only show ZFS pools.", + "", + "Setting this to True will hide all datasets,", + "and only show ZFS pools.", + "", + "True or False."}, {"disk_free_priv", "(Linux) Type of available disk space.", "", diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 0c71397..8350dc2 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -851,6 +851,7 @@ namespace Mem { bool filter_exclude = false; auto& use_fstab = Config::getB("use_fstab"); auto& only_physical = Config::getB("only_physical"); + auto& zfs_pools_only = Config::getB("zfs_pools_only"); auto& disks = mem.disks; ifstream diskread; From 6b1b9f8142561c180dc224b277e7418696960cf6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 3 Jul 2022 12:37:54 +0200 Subject: [PATCH 263/289] Changed: Rewrite of process sorting and tree generation including fixes for tree sorting and mouse support --- src/btop_config.cpp | 2 + src/btop_draw.cpp | 3 +- src/btop_input.cpp | 12 ++- src/btop_shared.cpp | 174 ++++++++++++++++++++++++++++++ src/btop_shared.hpp | 18 +++- src/freebsd/btop_collect.cpp | 201 ++++++++++++----------------------- src/linux/btop_collect.cpp | 154 +++++++-------------------- src/osx/btop_collect.cpp | 152 ++++++++------------------ 8 files changed, 356 insertions(+), 360 deletions(-) create mode 100644 src/btop_shared.cpp diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 6ffc483..1e20a0e 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -264,6 +264,7 @@ namespace Config { {"net_upload", 100}, {"detailed_pid", 0}, {"selected_pid", 0}, + {"selected_depth", 0}, {"proc_start", 0}, {"proc_selected", 0}, {"proc_last_selected", 0}, @@ -472,6 +473,7 @@ namespace Config { strings.at("selected_name") = Proc::selected_name; ints.at("proc_start") = Proc::start; ints.at("proc_selected") = Proc::selected; + ints.at("selected_depth") = Proc::selected_depth; } for (auto& item : stringsTmp) { diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 5bea6cb..2af3d61 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1022,7 +1022,7 @@ namespace Proc { int x, y, width = 20, height; int start, selected, select_max; bool shown = true, redraw = true; - int selected_pid = 0; + int selected_pid = 0, selected_depth = 0; string selected_name; unordered_flat_map p_graphs; unordered_flat_map p_wide_cmd; @@ -1345,6 +1345,7 @@ namespace Proc { if (is_selected) { selected_pid = (int)p.pid; selected_name = p.name; + selected_depth = p.depth; } //? Update graphs for processes with above 0.0% cpu usage, delete if below 0.1% 10x times diff --git a/src/btop_input.cpp b/src/btop_input.cpp index d21feec..13ed1e2 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -354,7 +354,16 @@ namespace Input { const auto& current_selection = Config::getI("proc_selected"); if (current_selection == line - y - 1) { redraw = true; - goto proc_mouse_enter; + if (Config::getB("proc_tree")) { + const int x_pos = col - Proc::x; + const int offset = Config::getI("selected_depth") * 3; + if (x_pos > offset and x_pos < 4 + offset) { + process("space"); + return; + } + } + process("enter"); + return; } else if (current_selection == 0 or line - y - 1 == 0) redraw = true; @@ -380,7 +389,6 @@ namespace Input { keep_going = true; } else if (key == "enter") { - proc_mouse_enter: if (Config::getI("proc_selected") == 0 and not Config::getB("show_detailed")) { return; } diff --git a/src/btop_shared.cpp b/src/btop_shared.cpp new file mode 100644 index 0000000..0cafdfb --- /dev/null +++ b/src/btop_shared.cpp @@ -0,0 +1,174 @@ +/* Copyright 2021 Aristocratos (jakob@qvantnet.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +indent = tab +tab-size = 4 +*/ + +#include + +#include +#include + +using std::string_literals::operator""s; +namespace rng = std::ranges; +using namespace Tools; + + +namespace Proc { + void proc_sorter(vector& proc_vec, string sorting, const bool reverse, const bool tree) { + if (reverse) { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(proc_vec, rng::less{}, &proc_info::pid); break; + case 1: rng::stable_sort(proc_vec, rng::less{}, &proc_info::name); break; + case 2: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cmd); break; + case 3: rng::stable_sort(proc_vec, rng::less{}, &proc_info::threads); break; + case 4: rng::stable_sort(proc_vec, rng::less{}, &proc_info::user); break; + case 5: rng::stable_sort(proc_vec, rng::less{}, &proc_info::mem); break; + case 6: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_c); break; + } + } + else { + switch (v_index(sort_vector, sorting)) { + case 0: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::pid); break; + case 1: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::name); break; + case 2: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cmd); break; + case 3: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::threads); break; + case 4: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::user); break; + case 5: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::mem); break; + case 6: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_p); break; + case 7: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_c); break; + } + } + + //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage + if (not tree and not reverse and sorting == "cpu lazy") { + double max = 10.0, target = 30.0; + for (size_t i = 0, x = 0, offset = 0; i < proc_vec.size(); i++) { + if (i <= 5 and proc_vec.at(i).cpu_p > max) + max = proc_vec.at(i).cpu_p; + else if (i == 6) + target = (max > 30.0) ? max : 10.0; + if (i == offset and proc_vec.at(i).cpu_p > 30.0) + offset++; + else if (proc_vec.at(i).cpu_p > target) { + rotate(proc_vec.begin() + offset, proc_vec.begin() + i, proc_vec.begin() + i + 1); + if (++x > 10) break; + } + } + } + } + + void tree_sort(vector& proc_vec, const string& sorting, const bool reverse, int& c_index, const int index_max, const bool collapsed) { + if (proc_vec.size() > 1) { + if (reverse) { + switch (v_index(sort_vector, sorting)) { + case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads < b.entry.get().threads; }); break; + case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem < b.entry.get().mem; }); break; + case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p < b.entry.get().cpu_p; }); break; + case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c < b.entry.get().cpu_c; }); break; + } + } + else { + switch (v_index(sort_vector, sorting)) { + case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads > b.entry.get().threads; }); break; + case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem > b.entry.get().mem; }); break; + case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p > b.entry.get().cpu_p; }); break; + case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c > b.entry.get().cpu_c; }); break; + } + } + } + + for (auto& r : proc_vec) { + r.entry.get().tree_index = (collapsed or r.entry.get().filtered ? index_max : c_index++); + if (not r.children.empty()) { + tree_sort(r.children, sorting, reverse, c_index, (collapsed or r.entry.get().collapsed or r.entry.get().tree_index == (size_t)index_max)); + } + } + } + + void _tree_gen(proc_info& cur_proc, vector& in_procs, vector& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found, const bool no_update, const bool should_filter) { + auto cur_pos = out_procs.size(); + bool filtering = false; + + //? If filtering, include children of matching processes + if (not found and (should_filter or not filter.empty())) { + if (not s_contains(std::to_string(cur_proc.pid), filter) + and not s_contains(cur_proc.name, filter) + and not s_contains(cur_proc.cmd, filter) + and not s_contains(cur_proc.user, filter)) { + filtering = true; + cur_proc.filtered = true; + filter_found++; + } + else { + found = true; + cur_depth = 0; + } + } + else if (cur_proc.filtered) cur_proc.filtered = false; + + cur_proc.depth = cur_depth; + + //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree + out_procs.push_back({ cur_proc, {} }); + if (not collapsed and not filtering) { + cur_proc.tree_index = out_procs.size() - 1; + + //? Try to find name of the binary file and append to program name if not the same + if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { + std::string_view cmd_view = cur_proc.cmd; + cmd_view = cmd_view.substr((size_t)0, std::min(cmd_view.find(' '), cmd_view.size())); + cmd_view = cmd_view.substr(std::min(cmd_view.find_last_of('/') + 1, cmd_view.size())); + cur_proc.short_cmd = (string)cmd_view; + } + } + else { + cur_proc.tree_index = in_procs.size(); + } + + //? Recursive iteration over all children + int children = 0; + for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { + if (collapsed and not filtering) { + cur_proc.filtered = true; + } + children++; + + _tree_gen(p, in_procs, out_procs.back().children, cur_depth + 1, (collapsed or cur_proc.collapsed), filter, found, no_update, should_filter); + + if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { + //auto& parent = cur_proc; + cur_proc.cpu_p += p.cpu_p; + cur_proc.cpu_c += p.cpu_c; + cur_proc.mem += p.mem; + cur_proc.threads += p.threads; + filter_found++; + p.filtered = true; + } + } + if (collapsed or filtering) { + return; + } + + //? Add tree terminator symbol if it's the last child in a sub-tree + if (children > 0 and out_procs.back().children.back().entry.get().prefix.size() >= 8 and not out_procs.back().children.back().entry.get().prefix.ends_with("]─")) + out_procs.back().children.back().entry.get().prefix.replace(out_procs.back().children.back().entry.get().prefix.size() - 8, 8, " └─ "); + + //? Add collapse/expand symbols if process have any children + out_procs.at(cur_pos).entry.get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); + } + +} \ No newline at end of file diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index caef8bf..f61cdbb 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -131,7 +131,7 @@ namespace Mem { struct disk_info { std::filesystem::path dev; string name; - string fstype; + string fstype = ""; std::filesystem::path stat = ""; int64_t total = 0, used = 0, free = 0; int used_percent = 0, free_percent = 0; @@ -199,7 +199,7 @@ namespace Proc { extern bool shown, redraw; extern int select_max; extern atomic detailed_pid; - extern int selected_pid, start, selected, collapse, expand; + extern int selected_pid, start, selected, collapse, expand, filter_found, selected_depth; extern string selected_name; //? Contains the valid sorting options for processes @@ -268,4 +268,18 @@ namespace Proc { //* Draw contents of proc box using as data source string draw(const vector& plist, const bool force_redraw=false, const bool data_same=false); + + struct tree_proc { + std::reference_wrapper entry; + vector children; + }; + + //* Sort vector of proc_info's + void proc_sorter(vector& proc_vec, string sorting, const bool reverse, const bool tree = false); + + //* Recursive sort of process tree + void tree_sort(vector& proc_vec, const string& sorting, const bool reverse, int& c_index, const int index_max, const bool collapsed = false); + + //* Generate process tree list + void _tree_gen(proc_info& cur_proc, vector& in_procs, vector& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false); } diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 7c6c07c..9e5be73 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -1007,65 +1007,6 @@ namespace Proc { detail_container detailed; - //* Generate process tree list - void _tree_gen(proc_info &cur_proc, vector &in_procs, vector> &out_procs, int cur_depth, const bool collapsed, const string &filter, bool found = false, const bool no_update = false, const bool should_filter = false) { - auto cur_pos = out_procs.size(); - bool filtering = false; - - //? If filtering, include children of matching processes - if (not found and (should_filter or not filter.empty())) { - if (not s_contains(std::to_string(cur_proc.pid), filter) and not s_contains(cur_proc.name, filter) and not s_contains(cur_proc.cmd, filter) and not s_contains(cur_proc.user, filter)) { - filtering = true; - cur_proc.filtered = true; - filter_found++; - } else { - found = true; - cur_depth = 0; - } - } else if (cur_proc.filtered) - cur_proc.filtered = false; - - //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree - if (not collapsed and not filtering) { - out_procs.push_back(std::ref(cur_proc)); - cur_proc.tree_index = out_procs.size() - 1; - //? Try to find name of the binary file and append to program name if not the same - if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { - std::string_view cmd_view = cur_proc.cmd; - cmd_view = cmd_view.substr((size_t)0, min(cmd_view.find(' '), cmd_view.size())); - cmd_view = cmd_view.substr(min(cmd_view.find_last_of('/') + 1, cmd_view.size())); - cur_proc.short_cmd = (string)cmd_view; - } - } else { - cur_proc.tree_index = in_procs.size(); - } - - //? Recursive iteration over all children - int children = 0; - for (auto &p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { - if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { - out_procs.back().get().cpu_p += p.cpu_p; - out_procs.back().get().mem += p.mem; - out_procs.back().get().threads += p.threads; - filter_found++; - } - if (collapsed and not filtering) { - cur_proc.filtered = true; - } else - children++; - _tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cur_proc.collapsed), filter, found, no_update, should_filter); - } - if (collapsed or filtering) - return; - - //? Add tree terminator symbol if it's the last child in a sub-tree - if (out_procs.size() > cur_pos + 1 and not out_procs.back().get().prefix.ends_with("]─")) - out_procs.back().get().prefix.replace(out_procs.back().get().prefix.size() - 8, 8, " └─ "); - - //? Add collapse/expand symbols if process have any children - out_procs.at(cur_pos).get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); - } - string get_status(char s) { if (s & SRUN) return "Running"; if (s & SSLEEP) return "Sleeping"; @@ -1156,6 +1097,8 @@ namespace Proc { const int cmult = (per_core) ? Shared::coreCount : 1; bool got_detailed = false; + static vector found; + vector> cpu_time(Shared::coreCount); size_t size = sizeof(long) * CPUSTATES * Shared::coreCount; if (sysctlbyname("kern.cp_times", &cpu_time[0], &size, NULL, 0) == -1) { @@ -1175,7 +1118,7 @@ namespace Proc { //* ---------------------------------------------Collection start---------------------------------------------- should_filter = true; - vector found; + found.clear(); struct timeval currentTime; gettimeofday(¤tTime, NULL); const double timeNow = currentTime.tv_sec + (currentTime.tv_usec / 1'000'000); @@ -1206,6 +1149,7 @@ namespace Proc { if (no_cache) { if (kproc->ki_comm == NULL or kproc->ki_comm == "idle"s) { current_procs.pop_back(); + found.pop_back(); continue; } new_proc.name = kproc->ki_comm; @@ -1249,116 +1193,111 @@ namespace Proc { if (show_detailed and not got_detailed and new_proc.pid == detailed_pid) { got_detailed = true; } - - // //? Clear dead processes from current_procs - auto eraser = rng::remove_if(current_procs, [&](const auto &element) { return not v_contains(found, element.pid); }); - current_procs.erase(eraser.begin(), eraser.end()); - - //? Update the details info box for process if active - if (show_detailed and got_detailed) { - _collect_details(detailed_pid, current_procs); - } else if (show_detailed and not got_detailed and detailed.status != "Dead") { - detailed.status = "Dead"; - redraw = true; - } - - old_cputimes = cputimes; } + + //? Clear dead processes from current_procs + auto eraser = rng::remove_if(current_procs, [&](const auto &element) { return not v_contains(found, element.pid); }); + current_procs.erase(eraser.begin(), eraser.end()); + + //? Update the details info box for process if active + if (show_detailed and got_detailed) { + _collect_details(detailed_pid, current_procs); + } else if (show_detailed and not got_detailed and detailed.status != "Dead") { + detailed.status = "Dead"; + redraw = true; + } + + old_cputimes = cputimes; + } //* ---------------------------------------------Collection done----------------------------------------------- - //* Sort processes - if (sorted_change or not no_update) { - if (reverse) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; - } - } else { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; - } - } - - //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage - if (not tree and not reverse and sorting == "cpu lazy") { - double max = 10.0, target = 30.0; - for (size_t i = 0, x = 0, offset = 0; i < current_procs.size(); i++) { - if (i <= 5 and current_procs.at(i).cpu_p > max) - max = current_procs.at(i).cpu_p; - else if (i == 6) - target = (max > 30.0) ? max : 10.0; - if (i == offset and current_procs.at(i).cpu_p > 30.0) - offset++; - else if (current_procs.at(i).cpu_p > target) { - rotate(current_procs.begin() + offset, current_procs.begin() + i, current_procs.begin() + i + 1); - if (++x > 10) break; - } - } - } - } - //* Match filter if defined if (should_filter) { filter_found = 0; - for (auto &p : current_procs) { + for (auto& p : current_procs) { if (not tree and not filter.empty()) { - if (not s_contains_ic(to_string(p.pid), filter) and not s_contains_ic(p.name, filter) and not s_contains_ic(p.cmd, filter) and not s_contains_ic(p.user, filter)) { - p.filtered = true; - filter_found++; - } else { - p.filtered = false; + if (not s_contains_ic(to_string(p.pid), filter) + and not s_contains_ic(p.name, filter) + and not s_contains_ic(p.cmd, filter) + and not s_contains_ic(p.user, filter)) { + p.filtered = true; + filter_found++; + } + else { + p.filtered = false; + } } - } else { + else { p.filtered = false; } } } + //* Sort processes + if (sorted_change or not no_update) { + proc_sorter(current_procs, sorting, reverse, tree); + } + //* Generate tree view if enabled if (tree and (not no_update or should_filter or sorted_change)) { + bool locate_selection = false; if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); if (collapser != current_procs.end()) { if (collapse == expand) { collapser->collapsed = not collapser->collapsed; - } else if (collapse > -1) { + } + else if (collapse > -1) { collapser->collapsed = true; - } else if (expand > -1) { + } + else if (expand > -1) { collapser->collapsed = false; } + if (Config::ints.at("proc_selected") > 0) locate_selection = true; } collapse = expand = -1; } if (should_filter or not filter.empty()) filter_found = 0; - vector> tree_procs; + vector tree_procs; tree_procs.reserve(current_procs.size()); + for (auto& p : current_procs) { + if (not v_contains(found, p.ppid)) p.ppid = 0; + } + //? Stable sort to retain selected sorting among processes with the same parent - rng::stable_sort(current_procs, rng::less{}, &proc_info::ppid); + rng::stable_sort(current_procs, rng::less{}, & proc_info::ppid); //? Start recursive iteration over processes with the lowest shared parent pids - for (auto &p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { + for (auto& p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { _tree_gen(p, current_procs, tree_procs, 0, false, filter, false, no_update, should_filter); } + //? Recursive sort over tree structure to account for collapsed processes in the tree + int index = 0; + tree_sort(tree_procs, sorting, reverse, index, current_procs.size()); + + //? Add tree begin symbol to first item if childless + if (tree_procs.front().children.empty()) + tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size() - 8, 8, " ┌─ "); + + //? Add tree terminator symbol to last item if childless + if (tree_procs.back().children.empty()) + tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size() - 8, 8, " └─ "); + //? Final sort based on tree index - rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); + rng::sort(current_procs, rng::less{}, & proc_info::tree_index); + + //? Move current selection/view to the selected process when collapsing/expanding in the tree + if (locate_selection) { + int loc = rng::find(current_procs, Proc::selected_pid, &proc_info::pid)->tree_index; + if (Config::ints.at("proc_start") >= loc or Config::ints.at("proc_start") <= loc - Proc::select_max) + Config::ints.at("proc_start") = max(0, loc - 1); + Config::ints.at("proc_selected") = loc - Config::ints.at("proc_start") + 1; + } } numpids = (int)current_procs.size() - filter_found; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 0c71397..5d63508 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1307,69 +1307,6 @@ namespace Proc { constexpr size_t KTHREADD = 2; static robin_hood::unordered_set kernels_procs = {KTHREADD}; - //* Generate process tree list - void _tree_gen(proc_info& cur_proc, vector& in_procs, vector>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false) { - auto cur_pos = out_procs.size(); - bool filtering = false; - - //? If filtering, include children of matching processes - if (not found and (should_filter or not filter.empty())) { - if (not s_contains(std::to_string(cur_proc.pid), filter) - and not s_contains(cur_proc.name, filter) - and not s_contains(cur_proc.cmd, filter) - and not s_contains(cur_proc.user, filter)) { - filtering = true; - cur_proc.filtered = true; - filter_found++; - } - else { - found = true; - cur_depth = 0; - } - } - else if (cur_proc.filtered) cur_proc.filtered = false; - - //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree - if (not collapsed and not filtering) { - out_procs.push_back(std::ref(cur_proc)); - cur_proc.tree_index = out_procs.size() - 1; - //? Try to find name of the binary file and append to program name if not the same - if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { - std::string_view cmd_view = cur_proc.cmd; - cmd_view = cmd_view.substr((size_t)0, min(cmd_view.find(' '), cmd_view.size())); - cmd_view = cmd_view.substr(min(cmd_view.find_last_of('/') + 1, cmd_view.size())); - cur_proc.short_cmd = (string)cmd_view; - } - } - else { - cur_proc.tree_index = in_procs.size(); - } - - //? Recursive iteration over all children - int children = 0; - for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { - if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { - out_procs.back().get().cpu_p += p.cpu_p; - out_procs.back().get().mem += p.mem; - out_procs.back().get().threads += p.threads; - filter_found++; - } - if (collapsed and not filtering) { - cur_proc.filtered = true; - } - else children++; - _tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cur_proc.collapsed), filter, found, no_update, should_filter); - } - if (collapsed or filtering) return; - - //? Add tree terminator symbol if it's the last child in a sub-tree - if (out_procs.size() > cur_pos + 1 and not out_procs.back().get().prefix.ends_with("]─")) - out_procs.back().get().prefix.replace(out_procs.back().get().prefix.size() - 8, 8, " └─ "); - - //? Add collapse/expand symbols if process have any children - out_procs.at(cur_pos).get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); - } - //* Get detailed info for selected process void _collect_details(const size_t pid, const uint64_t uptime, vector& procs) { fs::path pid_path = Shared::procPath / std::to_string(pid); @@ -1488,6 +1425,8 @@ namespace Proc { string long_string; string short_str; + static vector found; + const double uptime = system_uptime(); const int cmult = (per_core) ? Shared::coreCount : 1; @@ -1502,10 +1441,11 @@ namespace Proc { //* ---------------------------------------------Collection start---------------------------------------------- else { should_filter = true; + found.clear(); //? First make sure kernel proc cache is cleared. if (should_filter_kernel and ++proc_clear_count >= 256) { - //? Clearing the cache is used in the event of a pid wrap around. + //? Clearing the cache is used in the event of a pid wrap around. //? In that event processes that acquire old kernel pids would also be filtered out so we need to manually clean the cache every now and then. kernels_procs.clear(); kernels_procs.emplace(KTHREADD); @@ -1547,7 +1487,6 @@ namespace Proc { pread.close(); //? Iterate over all pids in /proc - vector found; for (const auto& d: fs::directory_iterator(Shared::procPath)) { if (Runner::stopping) return current_procs; @@ -1557,7 +1496,7 @@ namespace Proc { if (not isdigit(pid_str[0])) continue; const size_t pid = stoul(pid_str); - + if (should_filter_kernel and kernels_procs.contains(pid)) { continue; } @@ -1694,7 +1633,7 @@ namespace Proc { catch (const std::out_of_range&) { continue; } pread.close(); - + if (should_filter_kernel and new_proc.ppid == KTHREADD) { kernels_procs.emplace(new_proc.pid); found.pop_back(); @@ -1743,50 +1682,6 @@ namespace Proc { } //* ---------------------------------------------Collection done----------------------------------------------- - //* Sort processes - if (sorted_change or not no_update) { - if (reverse) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; - } - } else { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; - } - } - - //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage - if (not tree and not reverse and sorting == "cpu lazy") { - double max = 10.0, target = 30.0; - for (size_t i = 0, x = 0, offset = 0; i < current_procs.size(); i++) { - if (i <= 5 and current_procs.at(i).cpu_p > max) - max = current_procs.at(i).cpu_p; - else if (i == 6) - target = (max > 30.0) ? max : 10.0; - if (i == offset and current_procs.at(i).cpu_p > 30.0) - offset++; - else if (current_procs.at(i).cpu_p > target) { - rotate(current_procs.begin() + offset, current_procs.begin() + i, current_procs.begin() + i + 1); - if (++x > 10) break; - } - } - } - } - //* Match filter if defined if (should_filter) { filter_found = 0; @@ -1809,8 +1704,14 @@ namespace Proc { } } + //* Sort processes + if (sorted_change or not no_update) { + proc_sorter(current_procs, sorting, reverse, tree); + } + //* Generate tree view if enabled if (tree and (not no_update or should_filter or sorted_change)) { + bool locate_selection = false; if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); if (collapser != current_procs.end()) { @@ -1823,24 +1724,49 @@ namespace Proc { else if (expand > -1) { collapser->collapsed = false; } + if (Config::ints.at("proc_selected") > 0) locate_selection = true; } collapse = expand = -1; } if (should_filter or not filter.empty()) filter_found = 0; - vector> tree_procs; + vector tree_procs; tree_procs.reserve(current_procs.size()); + for (auto& p : current_procs) { + if (not v_contains(found, p.ppid)) p.ppid = 0; + } + //? Stable sort to retain selected sorting among processes with the same parent - rng::stable_sort(current_procs, rng::less{}, &proc_info::ppid); + rng::stable_sort(current_procs, rng::less{}, & proc_info::ppid); //? Start recursive iteration over processes with the lowest shared parent pids for (auto& p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { _tree_gen(p, current_procs, tree_procs, 0, false, filter, false, no_update, should_filter); } + //? Recursive sort over tree structure to account for collapsed processes in the tree + int index = 0; + tree_sort(tree_procs, sorting, reverse, index, current_procs.size()); + + //? Add tree begin symbol to first item if childless + if (tree_procs.front().children.empty()) + tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size() - 8, 8, " ┌─ "); + + //? Add tree terminator symbol to last item if childless + if (tree_procs.back().children.empty()) + tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size() - 8, 8, " └─ "); + //? Final sort based on tree index - rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); + rng::sort(current_procs, rng::less{}, & proc_info::tree_index); + + //? Move current selection/view to the selected process when collapsing/expanding in the tree + if (locate_selection) { + int loc = rng::find(current_procs, Proc::selected_pid, &proc_info::pid)->tree_index; + if (Config::ints.at("proc_start") >= loc or Config::ints.at("proc_start") <= loc - Proc::select_max) + Config::ints.at("proc_start") = max(0, loc - 1); + Config::ints.at("proc_selected") = loc - Config::ints.at("proc_start") + 1; + } } numpids = (int)current_procs.size() - filter_found; diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index c9dbcfe..d7877a1 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -1046,65 +1046,6 @@ namespace Proc { detail_container detailed; - //* Generate process tree list - void _tree_gen(proc_info &cur_proc, vector &in_procs, vector> &out_procs, int cur_depth, const bool collapsed, const string &filter, bool found = false, const bool no_update = false, const bool should_filter = false) { - auto cur_pos = out_procs.size(); - bool filtering = false; - - //? If filtering, include children of matching processes - if (not found and (should_filter or not filter.empty())) { - if (not s_contains(std::to_string(cur_proc.pid), filter) and not s_contains(cur_proc.name, filter) and not s_contains(cur_proc.cmd, filter) and not s_contains(cur_proc.user, filter)) { - filtering = true; - cur_proc.filtered = true; - filter_found++; - } else { - found = true; - cur_depth = 0; - } - } else if (cur_proc.filtered) - cur_proc.filtered = false; - - //? Set tree index position for process if not filtered out or currently in a collapsed sub-tree - if (not collapsed and not filtering) { - out_procs.push_back(std::ref(cur_proc)); - cur_proc.tree_index = out_procs.size() - 1; - //? Try to find name of the binary file and append to program name if not the same - if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) { - std::string_view cmd_view = cur_proc.cmd; - cmd_view = cmd_view.substr((size_t)0, min(cmd_view.find(' '), cmd_view.size())); - cmd_view = cmd_view.substr(min(cmd_view.find_last_of('/') + 1, cmd_view.size())); - cur_proc.short_cmd = (string)cmd_view; - } - } else { - cur_proc.tree_index = in_procs.size(); - } - - //? Recursive iteration over all children - int children = 0; - for (auto &p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) { - if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) { - out_procs.back().get().cpu_p += p.cpu_p; - out_procs.back().get().mem += p.mem; - out_procs.back().get().threads += p.threads; - filter_found++; - } - if (collapsed and not filtering) { - cur_proc.filtered = true; - } else - children++; - _tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cur_proc.collapsed), filter, found, no_update, should_filter); - } - if (collapsed or filtering) - return; - - //? Add tree terminator symbol if it's the last child in a sub-tree - if (out_procs.size() > cur_pos + 1 and not out_procs.back().get().prefix.ends_with("]─")) - out_procs.back().get().prefix.replace(out_procs.back().get().prefix.size() - 8, 8, " └─ "); - - //? Add collapse/expand symbols if process have any children - out_procs.at(cur_pos).get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ "); - } - string get_status(char s) { if (s & SRUN) return "Running"; if (s & SSLEEP) return "Sleeping"; @@ -1184,6 +1125,8 @@ namespace Proc { const int cmult = (per_core) ? Shared::coreCount : 1; bool got_detailed = false; + static vector found; + //* Use pids from last update if only changing filter, sorting or tree options if (no_update and not current_procs.empty()) { if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, current_procs); @@ -1211,7 +1154,7 @@ namespace Proc { should_filter = true; int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; - vector found; + found.clear(); size_t size = 0; const auto timeNow = time_micros(); @@ -1323,50 +1266,6 @@ namespace Proc { //* ---------------------------------------------Collection done----------------------------------------------- - //* Sort processes - if (sorted_change or not no_update) { - if (reverse) { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::less{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::less{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::less{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::less{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::less{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::less{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::less{}, &proc_info::cpu_c); break; - } - } else { - switch (v_index(sort_vector, sorting)) { - case 0: rng::stable_sort(current_procs, rng::greater{}, &proc_info::pid); break; - case 1: rng::stable_sort(current_procs, rng::greater{}, &proc_info::name); break; - case 2: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cmd); break; - case 3: rng::stable_sort(current_procs, rng::greater{}, &proc_info::threads); break; - case 4: rng::stable_sort(current_procs, rng::greater{}, &proc_info::user); break; - case 5: rng::stable_sort(current_procs, rng::greater{}, &proc_info::mem); break; - case 6: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_p); break; - case 7: rng::stable_sort(current_procs, rng::greater{}, &proc_info::cpu_c); break; - } - } - - //* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage - if (not tree and not reverse and sorting == "cpu lazy") { - double max = 10.0, target = 30.0; - for (size_t i = 0, x = 0, offset = 0; i < current_procs.size(); i++) { - if (i <= 5 and current_procs.at(i).cpu_p > max) - max = current_procs.at(i).cpu_p; - else if (i == 6) - target = (max > 30.0) ? max : 10.0; - if (i == offset and current_procs.at(i).cpu_p > 30.0) - offset++; - else if (current_procs.at(i).cpu_p > target) { - rotate(current_procs.begin() + offset, current_procs.begin() + i, current_procs.begin() + i + 1); - if (++x > 10) break; - } - } - } - } - //* Match filter if defined if (should_filter) { filter_found = 0; @@ -1384,36 +1283,69 @@ namespace Proc { } } + //* Sort processes + if (sorted_change or not no_update) { + proc_sorter(current_procs, sorting, reverse, tree); + } + //* Generate tree view if enabled if (tree and (not no_update or should_filter or sorted_change)) { + bool locate_selection = false; if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); if (collapser != current_procs.end()) { if (collapse == expand) { collapser->collapsed = not collapser->collapsed; - } else if (collapse > -1) { + } + else if (collapse > -1) { collapser->collapsed = true; - } else if (expand > -1) { + } + else if (expand > -1) { collapser->collapsed = false; } + if (Config::ints.at("proc_selected") > 0) locate_selection = true; } collapse = expand = -1; } if (should_filter or not filter.empty()) filter_found = 0; - vector> tree_procs; + vector tree_procs; tree_procs.reserve(current_procs.size()); + for (auto& p : current_procs) { + if (not v_contains(found, p.ppid)) p.ppid = 0; + } + //? Stable sort to retain selected sorting among processes with the same parent - rng::stable_sort(current_procs, rng::less{}, &proc_info::ppid); + rng::stable_sort(current_procs, rng::less{}, & proc_info::ppid); //? Start recursive iteration over processes with the lowest shared parent pids - for (auto &p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { + for (auto& p : rng::equal_range(current_procs, current_procs.at(0).ppid, rng::less{}, &proc_info::ppid)) { _tree_gen(p, current_procs, tree_procs, 0, false, filter, false, no_update, should_filter); } + //? Recursive sort over tree structure to account for collapsed processes in the tree + int index = 0; + tree_sort(tree_procs, sorting, reverse, index, current_procs.size()); + + //? Add tree begin symbol to first item if childless + if (tree_procs.front().children.empty()) + tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size() - 8, 8, " ┌─ "); + + //? Add tree terminator symbol to last item if childless + if (tree_procs.back().children.empty()) + tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size() - 8, 8, " └─ "); + //? Final sort based on tree index - rng::stable_sort(current_procs, rng::less{}, &proc_info::tree_index); + rng::sort(current_procs, rng::less{}, & proc_info::tree_index); + + //? Move current selection/view to the selected process when collapsing/expanding in the tree + if (locate_selection) { + int loc = rng::find(current_procs, Proc::selected_pid, &proc_info::pid)->tree_index; + if (Config::ints.at("proc_start") >= loc or Config::ints.at("proc_start") <= loc - Proc::select_max) + Config::ints.at("proc_start") = max(0, loc - 1); + Config::ints.at("proc_selected") = loc - Config::ints.at("proc_start") + 1; + } } numpids = (int)current_procs.size() - filter_found; From 48184418170f0cb07023584dce68bc8d0d8dfb7e Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 3 Jul 2022 12:56:04 +0200 Subject: [PATCH 264/289] Pass const string ref --- src/btop_shared.cpp | 2 +- src/btop_shared.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_shared.cpp b/src/btop_shared.cpp index 0cafdfb..606c082 100644 --- a/src/btop_shared.cpp +++ b/src/btop_shared.cpp @@ -27,7 +27,7 @@ using namespace Tools; namespace Proc { - void proc_sorter(vector& proc_vec, string sorting, const bool reverse, const bool tree) { + void proc_sorter(vector& proc_vec, const string& sorting, const bool reverse, const bool tree) { if (reverse) { switch (v_index(sort_vector, sorting)) { case 0: rng::stable_sort(proc_vec, rng::less{}, &proc_info::pid); break; diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index f61cdbb..bfec417 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -275,7 +275,7 @@ namespace Proc { }; //* Sort vector of proc_info's - void proc_sorter(vector& proc_vec, string sorting, const bool reverse, const bool tree = false); + void proc_sorter(vector& proc_vec, const string& sorting, const bool reverse, const bool tree = false); //* Recursive sort of process tree void tree_sort(vector& proc_vec, const string& sorting, const bool reverse, int& c_index, const int index_max, const bool collapsed = false); From ed20cb9e0702659a90af3e2b5a4efd6ddf8aa217 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Sun, 3 Jul 2022 21:04:05 +0300 Subject: [PATCH 265/289] Re-implemented ZFS stat collection to be compatible with new ZFS versions, now it uses files "/proc/spl/kstat/zfs/*pool_name*/objset*". Needs additional work to be compatible with the option "zfs_pools_only". --- src/btop_shared.hpp | 3 ++ src/linux/btop_collect.cpp | 93 ++++++++++++++++++++++++++++++++------ 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index caef8bf..3704c15 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -160,6 +160,9 @@ namespace Mem { //* Draw contents of mem box using as source string draw(const mem_info& mem, const bool force_redraw=false, const bool data_same=false); + + //? * Find the filepath to the specified ZFS object's stat file + string get_zfs_stat_file(const string& device_name, size_t dataset_name_start); } namespace Net { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 8350dc2..dac7c6d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -26,6 +26,7 @@ tab-size = 4 #include #include #include +#include #if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #include @@ -925,6 +926,10 @@ namespace Mem { continue; } + //? Skip ZFS datasets if zfs_pools_only option is enabled + size_t zfs_dataset_name_start = 0; + if (fstype == "zfs" && (zfs_dataset_name_start = dev.find('/')) != std::string::npos && zfs_pools_only) continue; + if ((not use_fstab and not only_physical) or (use_fstab and v_contains(fstab, mountpoint)) or (not use_fstab and only_physical and v_contains(fstypes, fstype))) { @@ -949,8 +954,11 @@ namespace Mem { disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat"; break; //? Set ZFS stat filepath - } else if (fs::exists(Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io", ec) and access(string(Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io").c_str(), R_OK) == 0) { - disks.at(mountpoint).stat = Shared::procPath.string() + "/spl/kstat/zfs/" + devname + "/io"; + } else if (fstype == "zfs") { + disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start); + if (disks.at(mountpoint).stat.empty()) { + Logger::warning("Failed to get ZFS stat file for device " + dev); + } break; } devname.resize(devname.size() - 1); @@ -1020,18 +1028,17 @@ namespace Mem { if (disk.stat.empty() or access(disk.stat.c_str(), R_OK) != 0) continue; diskread.open(disk.stat); if (diskread.good()) { + disk_ios++; //? ZFS Pool Support if (disk.fstype == "zfs") { - disk_ios++; - for (int i = 0; i < 18; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } - diskread >> sectors_read; // nbytes read - if (disk.io_read.empty()) - disk.io_read.push_back(0); - else - disk.io_read.push_back(max((int64_t)0, (sectors_read - disk.old_io.at(0)))); - disk.old_io.at(0) = sectors_read; - while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + // skip first three lines + for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> io_ticks_write; + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); diskread >> sectors_write; // nbytes written if (disk.io_write.empty()) disk.io_write.push_back(0); @@ -1040,10 +1047,20 @@ namespace Mem { disk.old_io.at(1) = sectors_write; while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); - for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } - diskread >> io_ticks_write; - for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); diskread >> io_ticks_read; + + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> sectors_read; // nbytes read + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (sectors_read - disk.old_io.at(0)))); + disk.old_io.at(0) = sectors_read; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + io_ticks = io_ticks_write + io_ticks_read; if (disk.io_activity.empty()) disk.io_activity.push_back(0); @@ -1052,7 +1069,6 @@ namespace Mem { disk.old_io.at(2) = io_ticks; while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); } else { - disk_ios++; for (int i = 0; i < 2; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); } diskread >> sectors_read; if (disk.io_read.empty()) @@ -1095,6 +1111,53 @@ namespace Mem { return mem; } + string get_zfs_stat_file(const string& device_name, size_t dataset_name_start) { + ifstream filestream; + DIR *directory; + struct dirent *entity; + string filename; + string filepath; + string zfs_pool_stat_path; + string pool_name; + if (dataset_name_start != std::string::npos) { // device is a dataset + pool_name = device_name.substr(0, dataset_name_start); + zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + pool_name + "/"; + } else { // device is a pool + zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + device_name + "/"; + } + string name_compare; + + if ((directory = opendir(zfs_pool_stat_path.c_str())) == nullptr) { + return ""; + } + // looking through all files that start with 'objset' to find the one containing `device_name` object stats + while ((entity = readdir(directory)) != nullptr) { + filename = entity->d_name; + if (filename.find("objset") != std::string::npos) { + filepath = zfs_pool_stat_path + filename; + filestream.open(filepath); + if (filestream.good()) { + // skip first two lines + for (int i = 0; i < 2; i++) filestream.ignore(numeric_limits::max(), '\n'); + // skip characters until '7' is reached, indicating data type 7, next value will be object name + filestream.ignore(numeric_limits::max(), '7'); + filestream >> name_compare; + if (name_compare == device_name) { + filestream.close(); + if (access((filepath).c_str(), R_OK) == 0) { + return filepath; + } else { + return ""; + } + } + } + filestream.close(); + } + } + + return ""; + } + } namespace Net { From 7feff854fd457453b798d3290f94d6e9ae534fb4 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Mon, 4 Jul 2022 01:28:25 +0300 Subject: [PATCH 266/289] Made ZFS stats collection compatible with zfs_pools_only option. ZFS pool's stat filepath points to the objset-* file when the option is disabled, otherwise it points to the pool's stats directory. Made ZFS total pool stat collection into a separate function for clean code. Also removed an unnecessary variable in the default ZFS stat collection, and changed io_ticks to track the number of reads/writes, reducing unnecessary calculations. --- src/btop_shared.hpp | 7 ++- src/linux/btop_collect.cpp | 115 ++++++++++++++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 3704c15..d08eb4c 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -161,8 +161,11 @@ namespace Mem { //* Draw contents of mem box using as source string draw(const mem_info& mem, const bool force_redraw=false, const bool data_same=false); - //? * Find the filepath to the specified ZFS object's stat file - string get_zfs_stat_file(const string& device_name, size_t dataset_name_start); + //?* Find the filepath to the specified ZFS object's stat file + string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); + + //?* Collect total ZFS pool io stats + bool zfs_collect_pool_total_stats(struct disk_info &disk); } namespace Net { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index dac7c6d..113d418 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -955,7 +955,7 @@ namespace Mem { break; //? Set ZFS stat filepath } else if (fstype == "zfs") { - disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start); + disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_pools_only); if (disks.at(mountpoint).stat.empty()) { Logger::warning("Failed to get ZFS stat file for device " + dev); } @@ -966,6 +966,14 @@ namespace Mem { } } + //? If zfs_pools_only option was switched, refresh stat filepath + if (fstype == "zfs" && ((zfs_pools_only && !is_directory(disks.at(mountpoint).stat)) + || (!zfs_pools_only && is_directory(disks.at(mountpoint).stat)))) { + disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_pools_only); + if (disks.at(mountpoint).stat.empty()) { + Logger::warning("Failed to get ZFS stat file for device " + dev); + } + } } } //? Remove disks no longer mounted or filtered out @@ -1022,10 +1030,14 @@ namespace Mem { #endif //? Get disks IO - int64_t sectors_read, sectors_write, io_ticks, io_ticks_read, io_ticks_write; + int64_t sectors_read, sectors_write, io_ticks, io_ticks_temp; disk_ios = 0; for (auto& [ignored, disk] : disks) { if (disk.stat.empty() or access(disk.stat.c_str(), R_OK) != 0) continue; + if (disk.fstype == "zfs" && zfs_pools_only && zfs_collect_pool_total_stats(disk)) { + disk_ios++; + continue; + } diskread.open(disk.stat); if (diskread.good()) { disk_ios++; @@ -1035,7 +1047,7 @@ namespace Mem { for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); // skip characters until '4' is reached, indicating data type 4, next value will be out target diskread.ignore(numeric_limits::max(), '4'); - diskread >> io_ticks_write; + diskread >> io_ticks; // skip characters until '4' is reached, indicating data type 4, next value will be out target diskread.ignore(numeric_limits::max(), '4'); @@ -1049,7 +1061,8 @@ namespace Mem { // skip characters until '4' is reached, indicating data type 4, next value will be out target diskread.ignore(numeric_limits::max(), '4'); - diskread >> io_ticks_read; + diskread >> io_ticks_temp; + io_ticks += io_ticks_temp; // skip characters until '4' is reached, indicating data type 4, next value will be out target diskread.ignore(numeric_limits::max(), '4'); @@ -1061,11 +1074,10 @@ namespace Mem { disk.old_io.at(0) = sectors_read; while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); - io_ticks = io_ticks_write + io_ticks_read; if (disk.io_activity.empty()) disk.io_activity.push_back(0); else - disk.io_activity.push_back(clamp((long)round((double)(io_ticks - disk.old_io.at(2)) / (uptime - old_uptime) / 10), 0l, 100l)); + disk.io_activity.push_back(max((int64_t)0, (io_ticks - disk.old_io.at(2)))); disk.old_io.at(2) = io_ticks; while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); } else { @@ -1111,23 +1123,35 @@ namespace Mem { return mem; } - string get_zfs_stat_file(const string& device_name, size_t dataset_name_start) { + string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only) { + string zfs_pool_stat_path; + if (zfs_pools_only) { + zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + device_name; + if (access((zfs_pool_stat_path).c_str(), R_OK) == 0) { + return zfs_pool_stat_path; + } else { + Logger::warning("Cant access folder: " + zfs_pool_stat_path); + return ""; + } + } + ifstream filestream; DIR *directory; struct dirent *entity; string filename; string filepath; - string zfs_pool_stat_path; string pool_name; + string name_compare; + if (dataset_name_start != std::string::npos) { // device is a dataset pool_name = device_name.substr(0, dataset_name_start); zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + pool_name + "/"; } else { // device is a pool zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + device_name + "/"; } - string name_compare; if ((directory = opendir(zfs_pool_stat_path.c_str())) == nullptr) { + Logger::warning("Cant access folder: " + zfs_pool_stat_path); return ""; } // looking through all files that start with 'objset' to find the one containing `device_name` object stats @@ -1147,6 +1171,7 @@ namespace Mem { if (access((filepath).c_str(), R_OK) == 0) { return filepath; } else { + Logger::warning("Cant access file: " + filepath); return ""; } } @@ -1155,9 +1180,81 @@ namespace Mem { } } + Logger::warning("Could not read directory: " + zfs_pool_stat_path); return ""; } + bool zfs_collect_pool_total_stats(struct disk_info &disk) { + ifstream diskread; + DIR *directory; + struct dirent *entity; + string filename; + + int64_t bytes_read, bytes_write, io_ticks, bytes_read_total = 0, bytes_write_total = 0, io_ticks_total = 0; + + if ((directory = opendir(disk.stat.c_str())) == nullptr) { + Logger::warning("Cant access folder: " + disk.stat.string()); + return false; + } + + // looking through all files that start with 'objset' + while ((entity = readdir(directory)) != nullptr) { + filename = entity->d_name; + if (filename.find("objset") != std::string::npos) { + diskread.open(disk.stat / filename); + if (diskread.good()) { + // skip first three lines + for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> io_ticks; + io_ticks_total += io_ticks; + + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> bytes_write; + bytes_write_total += bytes_write; + + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> io_ticks; + io_ticks_total += io_ticks; + + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> bytes_read; + bytes_read_total += bytes_read; + } else { + Logger::warning("Could not read file: " + (disk.stat / filename).string()); + } + diskread.close(); + } + } + + if (disk.io_write.empty()) + disk.io_write.push_back(0); + else + disk.io_write.push_back(max((int64_t)0, (bytes_write_total - disk.old_io.at(1)))); + disk.old_io.at(1) = bytes_write_total; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (bytes_read_total - disk.old_io.at(0)))); + disk.old_io.at(0) = bytes_read_total; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(max((int64_t)0, (io_ticks_total - disk.old_io.at(2)))); + disk.old_io.at(2) = io_ticks_total; + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + + return true; + } + } namespace Net { From 30cc42fcd92891336e4df6734282aba3213d0c17 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Tue, 5 Jul 2022 00:20:33 +0300 Subject: [PATCH 267/289] Move get_zfs_stat_file() and zfs_collect_pool_total_stats() functions declarations to btop_collect.cpp so they aren't included when compiling for macos and freebsd --- src/btop_shared.hpp | 5 ----- src/linux/btop_collect.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index d08eb4c..07c042e 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -161,11 +161,6 @@ namespace Mem { //* Draw contents of mem box using as source string draw(const mem_info& mem, const bool force_redraw=false, const bool data_same=false); - //?* Find the filepath to the specified ZFS object's stat file - string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); - - //?* Collect total ZFS pool io stats - bool zfs_collect_pool_total_stats(struct disk_info &disk); } namespace Net { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 113d418..7598d50 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -741,6 +741,12 @@ namespace Mem { vector last_found; const std::regex zfs_size_regex("^size\\s+\\d\\s+(\\d+)"); + //?* Find the filepath to the specified ZFS object's stat file + string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); + + //?* Collect total ZFS pool io stats + bool zfs_collect_pool_total_stats(struct disk_info &disk); + mem_info current_mem {}; uint64_t get_totalMem() { From 4969dd8dc63d2acb81babf20b73554ab2f529039 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Tue, 5 Jul 2022 01:11:17 +0300 Subject: [PATCH 268/289] Use fs::directory_iterator() instead of readdir() in ZFS functions, use fs::path instead of strings. --- src/linux/btop_collect.cpp | 60 +++++++++++++------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 7598d50..d82ef61 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -26,7 +26,6 @@ tab-size = 4 #include #include #include -#include #if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #include @@ -742,7 +741,7 @@ namespace Mem { const std::regex zfs_size_regex("^size\\s+\\d\\s+(\\d+)"); //?* Find the filepath to the specified ZFS object's stat file - string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); + fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); //?* Collect total ZFS pool io stats bool zfs_collect_pool_total_stats(struct disk_info &disk); @@ -1129,43 +1128,33 @@ namespace Mem { return mem; } - string get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only) { - string zfs_pool_stat_path; + fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only) { + fs::path zfs_pool_stat_path; if (zfs_pools_only) { - zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + device_name; - if (access((zfs_pool_stat_path).c_str(), R_OK) == 0) { + zfs_pool_stat_path = Shared::procPath / "spl/kstat/zfs" / device_name; + if (access(zfs_pool_stat_path.c_str(), R_OK) == 0) { return zfs_pool_stat_path; } else { - Logger::warning("Cant access folder: " + zfs_pool_stat_path); + Logger::warning("Cant access folder: " + zfs_pool_stat_path.string()); return ""; } } ifstream filestream; - DIR *directory; - struct dirent *entity; string filename; - string filepath; - string pool_name; string name_compare; if (dataset_name_start != std::string::npos) { // device is a dataset - pool_name = device_name.substr(0, dataset_name_start); - zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + pool_name + "/"; + zfs_pool_stat_path = Shared::procPath / "spl/kstat/zfs" / device_name.substr(0, dataset_name_start); } else { // device is a pool - zfs_pool_stat_path = Shared::procPath.string() + "/spl/kstat/zfs/" + device_name + "/"; + zfs_pool_stat_path = Shared::procPath / "spl/kstat/zfs" / device_name; } - if ((directory = opendir(zfs_pool_stat_path.c_str())) == nullptr) { - Logger::warning("Cant access folder: " + zfs_pool_stat_path); - return ""; - } // looking through all files that start with 'objset' to find the one containing `device_name` object stats - while ((entity = readdir(directory)) != nullptr) { - filename = entity->d_name; - if (filename.find("objset") != std::string::npos) { - filepath = zfs_pool_stat_path + filename; - filestream.open(filepath); + for (const auto& file: fs::directory_iterator(zfs_pool_stat_path)) { + filename = file.path().filename(); + if (filename.starts_with("objset")) { + filestream.open(file.path()); if (filestream.good()) { // skip first two lines for (int i = 0; i < 2; i++) filestream.ignore(numeric_limits::max(), '\n'); @@ -1174,10 +1163,10 @@ namespace Mem { filestream >> name_compare; if (name_compare == device_name) { filestream.close(); - if (access((filepath).c_str(), R_OK) == 0) { - return filepath; + if (access(file.path().c_str(), R_OK) == 0) { + return file.path(); } else { - Logger::warning("Cant access file: " + filepath); + Logger::warning("Can't access file: " + file.path().string()); return ""; } } @@ -1186,28 +1175,19 @@ namespace Mem { } } - Logger::warning("Could not read directory: " + zfs_pool_stat_path); + Logger::warning("Could not read directory: " + zfs_pool_stat_path.string()); return ""; } bool zfs_collect_pool_total_stats(struct disk_info &disk) { ifstream diskread; - DIR *directory; - struct dirent *entity; - string filename; int64_t bytes_read, bytes_write, io_ticks, bytes_read_total = 0, bytes_write_total = 0, io_ticks_total = 0; - if ((directory = opendir(disk.stat.c_str())) == nullptr) { - Logger::warning("Cant access folder: " + disk.stat.string()); - return false; - } - // looking through all files that start with 'objset' - while ((entity = readdir(directory)) != nullptr) { - filename = entity->d_name; - if (filename.find("objset") != std::string::npos) { - diskread.open(disk.stat / filename); + for (const auto& file: fs::directory_iterator(disk.stat)) { + if ((file.path().filename()).string().starts_with("objset")) { + diskread.open(file.path()); if (diskread.good()) { // skip first three lines for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); @@ -1231,7 +1211,7 @@ namespace Mem { diskread >> bytes_read; bytes_read_total += bytes_read; } else { - Logger::warning("Could not read file: " + (disk.stat / filename).string()); + Logger::warning("Could not read file: " + file.path().string()); } diskread.close(); } From ab92ed1257e840851136998f0878ecd3212dddce Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 5 Jul 2022 11:52:12 +0200 Subject: [PATCH 269/289] Fixed: Logo transparency --- src/btop_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 2af3d61..4edf8db 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -111,7 +111,7 @@ namespace Draw { } for (size_t i = 0; i < line[1].size(); i += 3) { if (line[1][i] == ' ') { - letter = ' '; + letter = Mv::r(1); i -= 2; } else From 3e049046f758182f39c32b8f56a76c2cccab797d Mon Sep 17 00:00:00 2001 From: mohammad hashemy Date: Thu, 7 Jul 2022 17:56:05 +0430 Subject: [PATCH 270/289] add "?" to see help Signed-off-by: mohammad hashemy --- src/btop_input.cpp | 2 +- src/btop_menu.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 13ed1e2..586dea9 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -249,7 +249,7 @@ namespace Input { Menu::show(Menu::Menus::Main); return; } - else if (is_in(key, "F1", help_key)) { + else if (is_in(key, "F1", "?", help_key)) { Menu::show(Menu::Menus::Help); return; } diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 6dd420c..c9f5c64 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -111,7 +111,7 @@ namespace Menu { {"4", "Toggle PROC box."}, {"d", "Toggle disks view in MEM box."}, {"F2, o", "Shows options."}, - {"F1, h", "Shows this window."}, + {"F1, ?, h", "Shows this window."}, {"ctrl + z", "Sleep program and put in background."}, {"q, ctrl + c", "Quits program."}, {"+, -", "Add/Subtract 100ms to/from update timer."}, From 189cba73e40b3c43381076e038da8929a58dece9 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Sat, 9 Jul 2022 03:46:15 +0300 Subject: [PATCH 271/289] check if at least one object was read before updating ZFS pool io in zfs_collect_pool_total_stats(), use try-catch to prevent possible crashes from int_64t conversions --- src/linux/btop_collect.cpp | 48 +++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index d82ef61..1ec2a13 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1182,34 +1182,41 @@ namespace Mem { bool zfs_collect_pool_total_stats(struct disk_info &disk) { ifstream diskread; - int64_t bytes_read, bytes_write, io_ticks, bytes_read_total = 0, bytes_write_total = 0, io_ticks_total = 0; + int64_t bytes_read, bytes_write, io_ticks, bytes_read_total = 0, bytes_write_total = 0, io_ticks_total = 0, objects_read = 0; // looking through all files that start with 'objset' for (const auto& file: fs::directory_iterator(disk.stat)) { if ((file.path().filename()).string().starts_with("objset")) { diskread.open(file.path()); if (diskread.good()) { - // skip first three lines - for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); - // skip characters until '4' is reached, indicating data type 4, next value will be out target - diskread.ignore(numeric_limits::max(), '4'); - diskread >> io_ticks; - io_ticks_total += io_ticks; + try { + // skip first three lines + for (int i = 0; i < 3; i++) diskread.ignore(numeric_limits::max(), '\n'); + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> io_ticks; + io_ticks_total += io_ticks; - // skip characters until '4' is reached, indicating data type 4, next value will be out target - diskread.ignore(numeric_limits::max(), '4'); - diskread >> bytes_write; - bytes_write_total += bytes_write; + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> bytes_write; + bytes_write_total += bytes_write; - // skip characters until '4' is reached, indicating data type 4, next value will be out target - diskread.ignore(numeric_limits::max(), '4'); - diskread >> io_ticks; - io_ticks_total += io_ticks; + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> io_ticks; + io_ticks_total += io_ticks; - // skip characters until '4' is reached, indicating data type 4, next value will be out target - diskread.ignore(numeric_limits::max(), '4'); - diskread >> bytes_read; - bytes_read_total += bytes_read; + // skip characters until '4' is reached, indicating data type 4, next value will be out target + diskread.ignore(numeric_limits::max(), '4'); + diskread >> bytes_read; + bytes_read_total += bytes_read; + } catch (const std::exception& e) { + continue; + } + + // increment read objects counter if no errors were encountered + objects_read++; } else { Logger::warning("Could not read file: " + file.path().string()); } @@ -1217,6 +1224,9 @@ namespace Mem { } } + // if for some reason no objects were read + if (objects_read == 0) return false; + if (disk.io_write.empty()) disk.io_write.push_back(0); else From bc608e862ead1e4ae1816736e20952616c7c61c7 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Mon, 11 Jul 2022 19:08:25 +0300 Subject: [PATCH 272/289] rename zfs_pools_only option to zfs_hide_datasets, make its description clearer --- src/btop_config.cpp | 4 ++-- src/btop_menu.cpp | 6 ++++-- src/linux/btop_collect.cpp | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 6cc2a6c..01e66d7 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -155,7 +155,7 @@ namespace Config { {"use_fstab", "#* Read disks list from /etc/fstab. This also disables only_physical."}, - {"zfs_pools_only", "#* Only show ZFS pools. Setting this to True will hide all datasets, and only show ZFS pools."}, + {"zfs_hide_datasets", "#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)"}, {"disk_free_priv", "#* Set to true to show available disk space for privileged users."}, @@ -243,7 +243,7 @@ namespace Config { {"show_disks", true}, {"only_physical", true}, {"use_fstab", true}, - {"zfs_pools_only", false}, + {"zfs_hide_datasets", false}, {"show_io_stat", true}, {"io_mode", false}, {"base_10_sizes", false}, diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 99972ef..cb83770 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -469,12 +469,14 @@ namespace Menu { "This also disables only_physical.", "", "True or False."}, - {"zfs_pools_only", - "(Linux) Only show ZFS pools.", + {"zfs_hide_datasets", + "(Linux) Hide ZFS datasets in disks list.", "", "Setting this to True will hide all datasets,", "and only show ZFS pools.", "", + "(IO stats will be calculated per-pool)", + "", "True or False."}, {"disk_free_priv", "(Linux) Type of available disk space.", diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 1ec2a13..3f4ff6e 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -741,7 +741,7 @@ namespace Mem { const std::regex zfs_size_regex("^size\\s+\\d\\s+(\\d+)"); //?* Find the filepath to the specified ZFS object's stat file - fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only); + fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_hide_datasets); //?* Collect total ZFS pool io stats bool zfs_collect_pool_total_stats(struct disk_info &disk); @@ -857,7 +857,7 @@ namespace Mem { bool filter_exclude = false; auto& use_fstab = Config::getB("use_fstab"); auto& only_physical = Config::getB("only_physical"); - auto& zfs_pools_only = Config::getB("zfs_pools_only"); + auto& zfs_hide_datasets = Config::getB("zfs_hide_datasets"); auto& disks = mem.disks; ifstream diskread; @@ -931,9 +931,9 @@ namespace Mem { continue; } - //? Skip ZFS datasets if zfs_pools_only option is enabled + //? Skip ZFS datasets if zfs_hide_datasets option is enabled size_t zfs_dataset_name_start = 0; - if (fstype == "zfs" && (zfs_dataset_name_start = dev.find('/')) != std::string::npos && zfs_pools_only) continue; + if (fstype == "zfs" && (zfs_dataset_name_start = dev.find('/')) != std::string::npos && zfs_hide_datasets) continue; if ((not use_fstab and not only_physical) or (use_fstab and v_contains(fstab, mountpoint)) @@ -960,7 +960,7 @@ namespace Mem { break; //? Set ZFS stat filepath } else if (fstype == "zfs") { - disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_pools_only); + disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_hide_datasets); if (disks.at(mountpoint).stat.empty()) { Logger::warning("Failed to get ZFS stat file for device " + dev); } @@ -971,10 +971,10 @@ namespace Mem { } } - //? If zfs_pools_only option was switched, refresh stat filepath - if (fstype == "zfs" && ((zfs_pools_only && !is_directory(disks.at(mountpoint).stat)) - || (!zfs_pools_only && is_directory(disks.at(mountpoint).stat)))) { - disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_pools_only); + //? If zfs_hide_datasets option was switched, refresh stat filepath + if (fstype == "zfs" && ((zfs_hide_datasets && !is_directory(disks.at(mountpoint).stat)) + || (!zfs_hide_datasets && is_directory(disks.at(mountpoint).stat)))) { + disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_hide_datasets); if (disks.at(mountpoint).stat.empty()) { Logger::warning("Failed to get ZFS stat file for device " + dev); } @@ -1039,7 +1039,7 @@ namespace Mem { disk_ios = 0; for (auto& [ignored, disk] : disks) { if (disk.stat.empty() or access(disk.stat.c_str(), R_OK) != 0) continue; - if (disk.fstype == "zfs" && zfs_pools_only && zfs_collect_pool_total_stats(disk)) { + if (disk.fstype == "zfs" && zfs_hide_datasets && zfs_collect_pool_total_stats(disk)) { disk_ios++; continue; } @@ -1128,9 +1128,9 @@ namespace Mem { return mem; } - fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_pools_only) { + fs::path get_zfs_stat_file(const string& device_name, size_t dataset_name_start, bool zfs_hide_datasets) { fs::path zfs_pool_stat_path; - if (zfs_pools_only) { + if (zfs_hide_datasets) { zfs_pool_stat_path = Shared::procPath / "spl/kstat/zfs" / device_name; if (access(zfs_pool_stat_path.c_str(), R_OK) == 0) { return zfs_pool_stat_path; From a33bab3000ea3fbc7b4179976960862d4653f168 Mon Sep 17 00:00:00 2001 From: simplepad <35456194+simplepad@users.noreply.github.com> Date: Mon, 11 Jul 2022 19:16:19 +0300 Subject: [PATCH 273/289] switch Logger calls to debug() to avoid filling up the logfile --- src/linux/btop_collect.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 3f4ff6e..068a7e2 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -962,7 +962,7 @@ namespace Mem { } else if (fstype == "zfs") { disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_hide_datasets); if (disks.at(mountpoint).stat.empty()) { - Logger::warning("Failed to get ZFS stat file for device " + dev); + Logger::debug("Failed to get ZFS stat file for device " + dev); } break; } @@ -976,7 +976,7 @@ namespace Mem { || (!zfs_hide_datasets && is_directory(disks.at(mountpoint).stat)))) { disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, zfs_hide_datasets); if (disks.at(mountpoint).stat.empty()) { - Logger::warning("Failed to get ZFS stat file for device " + dev); + Logger::debug("Failed to get ZFS stat file for device " + dev); } } } @@ -1135,7 +1135,7 @@ namespace Mem { if (access(zfs_pool_stat_path.c_str(), R_OK) == 0) { return zfs_pool_stat_path; } else { - Logger::warning("Cant access folder: " + zfs_pool_stat_path.string()); + Logger::debug("Cant access folder: " + zfs_pool_stat_path.string()); return ""; } } @@ -1166,7 +1166,7 @@ namespace Mem { if (access(file.path().c_str(), R_OK) == 0) { return file.path(); } else { - Logger::warning("Can't access file: " + file.path().string()); + Logger::debug("Can't access file: " + file.path().string()); return ""; } } @@ -1175,7 +1175,7 @@ namespace Mem { } } - Logger::warning("Could not read directory: " + zfs_pool_stat_path.string()); + Logger::debug("Could not read directory: " + zfs_pool_stat_path.string()); return ""; } @@ -1218,7 +1218,7 @@ namespace Mem { // increment read objects counter if no errors were encountered objects_read++; } else { - Logger::warning("Could not read file: " + file.path().string()); + Logger::debug("Could not read file: " + file.path().string()); } diskread.close(); } From a84a7e6a5c3fe16b5e1d1a9824422638aca2f975 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 Jul 2022 17:24:34 +0200 Subject: [PATCH 274/289] Fixed: Getting selfpath on macos (fix for finding theme folder) --- src/btop.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/btop.cpp b/src/btop.cpp index b114753..484a0df 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -34,6 +34,8 @@ tab-size = 4 #include #ifdef __APPLE__ #include + #include + #include #endif #include @@ -699,10 +701,17 @@ int main(int argc, char **argv) { } } //? Try to find global btop theme path relative to binary path -#if defined(__linux__) +#ifdef __linux__ { std::error_code ec; Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename(); } +#elif __APPLE__ + { + char buf [PATH_MAX]; + uint32_t bufsize = PATH_MAX; + if(!_NSGetExecutablePath(buf, &bufsize)) + Global::self_path = fs::path(buf).remove_filename(); + } #endif if (std::error_code ec; not Global::self_path.empty()) { Theme::theme_dir = fs::canonical(Global::self_path / "../share/btop/themes", ec); From edbafa906027b39d6d69134f141217039202ceae Mon Sep 17 00:00:00 2001 From: Aristocratos Date: Tue, 26 Jul 2022 21:34:14 +0200 Subject: [PATCH 275/289] Changed: Small graphs now show colors for each character --- src/btop_draw.cpp | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 4edf8db..6c3ffcf 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -388,15 +388,22 @@ namespace Draw { } } //? Generate graph symbol from 5x5 2D vector - graphs.at(current).at(horizon) += (height == 1 and result.at(0) + result.at(1) == 0) ? Mv::r(1) : graph_symbol.at((result.at(0) * 5 + result.at(1))); + if (height == 1) { + if (result.at(0) + result.at(1) == 0) graphs.at(current).at(horizon) += Mv::r(1); + else { + if (not color_gradient.empty()) graphs.at(current).at(horizon) += Theme::g(color_gradient).at(clamp(max(last, data_value), 0ll, 100ll)); + graphs.at(current).at(horizon) += graph_symbol.at((result.at(0) * 5 + result.at(1))); + } + } + else graphs.at(current).at(horizon) += graph_symbol.at((result.at(0) * 5 + result.at(1))); } if (mult and i >= 0) last = data_value; } last = data_value; out.clear(); if (height == 1) { - if (not color_gradient.empty()) - out += (last < 1 and not color_gradient.empty() ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(clamp(last, 0ll, 100ll))); + //if (not color_gradient.empty()) + // out += (last < 1 ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(clamp(last, 0ll, 100ll))); out += graphs.at(current).at(0); } else { @@ -443,7 +450,10 @@ namespace Draw { //? Make room for new characters on graph if (not tty_mode) current = not current; for (const int& i : iota(0, height)) { - if (graphs.at(current).at(i).at(1) == '[') graphs.at(current).at(i).erase(0, 4); + if (height == 1 and graphs.at(current).at(i).at(1) == '[') { + if (graphs.at(current).at(i).at(3) == 'C') graphs.at(current).at(i).erase(0, 4); + else graphs.at(current).at(i).erase(0, graphs.at(current).at(i).find_first_of('m') + 4); + } else if (graphs.at(current).at(i).at(0) == ' ') graphs.at(current).at(i).erase(0, 1); else graphs.at(current).at(i).erase(0, 3); } @@ -528,15 +538,15 @@ namespace Cpu { if (b_column_size > 0 or extra_width > 0) { core_graphs.clear(); for (const auto& core_data : cpu.core_percent) { - core_graphs.emplace_back(5 * b_column_size + extra_width, 1, "", core_data, graph_symbol); + core_graphs.emplace_back(5 * b_column_size + extra_width, 1, "cpu", core_data, graph_symbol); } } if (show_temps) { temp_graphs.clear(); - temp_graphs.emplace_back(5, 1, "", cpu.temp.at(0), graph_symbol, false, false, cpu.temp_max, -23); + temp_graphs.emplace_back(5, 1, "temp", cpu.temp.at(0), graph_symbol, false, false, cpu.temp_max, -23); if (not hide_cores and b_column_size > 1) { for (const auto& i : iota((size_t)1, cpu.temp.size())) { - temp_graphs.emplace_back(5, 1, "", cpu.temp.at(i), graph_symbol, false, false, cpu.temp_max, -23); + temp_graphs.emplace_back(5, 1, "temp", cpu.temp.at(i), graph_symbol, false, false, cpu.temp_max, -23); } } } @@ -626,16 +636,16 @@ namespace Cpu { + ljust(to_string(n), core_width); if (b_column_size > 0 or extra_width > 0) out += Theme::c("inactive_fg") + graph_bg * (5 * b_column_size + extra_width) + Mv::l(5 * b_column_size + extra_width) - + Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll)) + core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw); - else - out += Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll)); + + core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw); + + out += Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll)); out += rjust(to_string(cpu.core_percent.at(n).back()), (b_column_size < 2 ? 3 : 4)) + Theme::c("main_fg") + '%'; if (show_temps and not hide_cores) { const auto [temp, unit] = celsius_to(cpu.temp.at(n+1).back(), temp_scale); const auto& temp_color = Theme::g("temp").at(clamp(cpu.temp.at(n+1).back() * 100 / cpu.temp_max, 0ll, 100ll)); if (b_column_size > 1) - out += ' ' + Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5) + temp_color + out += ' ' + Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5) + temp_graphs.at(n+1)(cpu.temp.at(n+1), data_same or redraw); out += temp_color + rjust(to_string(temp), 4) + Theme::c("main_fg") + unit; } @@ -753,7 +763,7 @@ namespace Mem { for (const auto& [name, disk] : mem.disks) { if (disk.io_read.empty()) continue; - io_graphs[name + "_activity"] = Draw::Graph{disks_width - 6, 1, "", disk.io_activity, graph_symbol}; + io_graphs[name + "_activity"] = Draw::Graph{disks_width - 6, 1, "available", disk.io_activity, graph_symbol}; if (io_mode) { //? Create one combined graph for IO read/write if enabled @@ -850,7 +860,7 @@ namespace Mem { const string used_percent = to_string(disk.used_percent); out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2) - 1) + hu_div + used_percent + '%' + hu_div; } - out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll)) + out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg"); if (++cy > height - 3) break; if (io_graph_combined) { From 2d6bf1f4aaee3a83f5518406f7854de47e36e9fa Mon Sep 17 00:00:00 2001 From: Aristocratos Date: Fri, 29 Jul 2022 16:18:06 +0200 Subject: [PATCH 276/289] Added: Option to hide the small cpu graphs for processes --- src/btop_config.cpp | 3 +++ src/btop_draw.cpp | 13 +++++++++---- src/btop_menu.cpp | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 7d2dec8..479101a 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -92,6 +92,8 @@ namespace Config { {"proc_mem_bytes", "#* Show process memory as bytes instead of percent."}, + {"proc_cpu_graphs", "#* Show cpu graph for each process."}, + {"proc_info_smaps", "#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)"}, {"proc_left", "#* Show proc box on left side of screen instead of right."}, @@ -224,6 +226,7 @@ namespace Config { {"proc_gradient", true}, {"proc_per_core", false}, {"proc_mem_bytes", true}, + {"proc_cpu_graphs", true}, {"proc_info_smaps", false}, {"proc_left", false}, {"proc_filter_kernel", false}, diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 6c3ffcf..3603406 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1117,6 +1117,7 @@ namespace Proc { auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6); auto& mem_bytes = Config::getB("proc_mem_bytes"); auto& vim_keys = Config::getB("vim_keys"); + auto& show_graphs = Config::getB("proc_cpu_graphs"); start = Config::getI("proc_start"); selected = Config::getI("proc_selected"); const int y = show_detailed ? Proc::y + 8 : Proc::y; @@ -1144,6 +1145,10 @@ namespace Proc { prog_size = (width > 70 ? 16 : ( width > 55 ? 8 : width - user_size - thread_size - 33)); cmd_size = (width > 55 ? width - prog_size - user_size - thread_size - 33 : -1); tree_size = width - user_size - thread_size - 23; + if (not show_graphs) { + cmd_size += 5; + tree_size += 5; + } //? Detailed box if (show_detailed) { @@ -1294,7 +1299,7 @@ namespace Proc { out += (thread_size > 0 ? Mv::l(4) + "Threads: " : "") + ljust("User:", user_size) + ' ' + rjust((mem_bytes ? "MemB" : "Mem%"), 5) + ' ' - + rjust("Cpu%", 10) + Fx::ub; + + rjust("Cpu%", (show_graphs ? 10 : 5)) + Fx::ub; } //* End of redraw block @@ -1359,8 +1364,8 @@ namespace Proc { } //? Update graphs for processes with above 0.0% cpu usage, delete if below 0.1% 10x times - const bool has_graph = p_counters.contains(p.pid); - if ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph)) { + const bool has_graph = show_graphs ? p_counters.contains(p.pid) : false; + if (show_graphs and ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph))) { if (not has_graph) { p_graphs[p.pid] = Draw::Graph{5, 1, "", {}, graph_symbol}; p_counters[p.pid] = 0; @@ -1452,7 +1457,7 @@ namespace Proc { out += (thread_size > 0 ? t_color + rjust(to_string(min(p.threads, (size_t)9999)), thread_size) + ' ' + end : "" ) + g_color + ljust((cmp_greater(p.user.size(), user_size) ? p.user.substr(0, user_size - 1) + '+' : p.user), user_size) + ' ' + m_color + rjust(mem_str, 5) + end + ' ' - + (is_selected ? "" : Theme::c("inactive_fg")) + graph_bg * 5 + + (is_selected ? "" : Theme::c("inactive_fg")) + (show_graphs ? graph_bg * 5: "") + (p_graphs.contains(p.pid) ? Mv::l(5) + c_color + p_graphs.at(p.pid)({(p.cpu_p >= 0.1 and p.cpu_p < 5 ? 5ll : (long long)round(p.cpu_p))}, data_same) : "") + end + ' ' + c_color + rjust(cpu_str, 4) + " " + end; if (lc++ > height - 5) break; diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 0adee0d..8037e0f 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -607,6 +607,10 @@ namespace Menu { " ", "Will show percentage of total memory", "if False."}, + {"proc_cpu_graphs", + "Show cpu graph for each process.", + "", + "True or False"}, {"proc_filter_kernel", "(Linux) Filter kernel processes from output.", "", From 4e6f0c2843255ba857a6c07771c3ddaab01e43b3 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 14:47:18 -0500 Subject: [PATCH 277/289] Maybe --- snap/snapcraft.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 860b103..2cfbdc2 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -4,7 +4,6 @@ summary: Resource monitor that shows usage and stats description: | Resource monitor that shows usage and stats for processor, memory, disks, network and processes. C++ version and continuation of bashtop and bpytop. - license: Apache-2.0 base: core20 @@ -14,10 +13,7 @@ compression: lzo architectures: - build-on: amd64 - - build-on: arm64 - - build-on: armhf - - build-on: ppc64el - - build-on: s390x + run-on: [all] package-repositories: - type: apt @@ -26,6 +22,8 @@ package-repositories: apps: btop: command: usr/local/bin/btop + extensions: + - gnome-3-38 environment: LC_ALL: C.UTF-8 LANG: C.UTF-8 From 40bb998edfa513fbf3e3be9ae795013654dcd7d9 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 14:56:21 -0500 Subject: [PATCH 278/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 2cfbdc2..c77e06a 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -13,7 +13,10 @@ compression: lzo architectures: - build-on: amd64 - run-on: [all] + - build-on: arm64 + - build-on: armhf + - build-on: ppc64el + - build-on: s390x package-repositories: - type: apt @@ -21,7 +24,8 @@ package-repositories: apps: btop: - command: usr/local/bin/btop + command: desktop-launch usr/local/bin/btop + desktop: usr/local/bin/btop.desktop extensions: - gnome-3-38 environment: From e199fdd4b20d3a2830e9df1994d7aa867754b4c4 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 14:58:13 -0500 Subject: [PATCH 279/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c77e06a..f21863f 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -40,6 +40,11 @@ apps: - network-observe - home - removable-media + - desktop + - desktop-legacy + - x11 + - wayland + - unity7 parts: btop: From aabfc82c44f99ec3a2efe4a34418c0979cbde042 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:02:48 -0500 Subject: [PATCH 280/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f21863f..2fa4331 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -24,7 +24,7 @@ package-repositories: apps: btop: - command: desktop-launch usr/local/bin/btop + command: usr/local/bin/btop desktop: usr/local/bin/btop.desktop extensions: - gnome-3-38 From 4535e04fc51ca7dfc605135cbf87f5825973a714 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:06:55 -0500 Subject: [PATCH 281/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 2fa4331..79e8849 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,7 @@ package-repositories: apps: btop: command: usr/local/bin/btop - desktop: usr/local/bin/btop.desktop + desktop: btop.desktop extensions: - gnome-3-38 environment: From 4c029eed07068a7325596052416fc551cb6897e2 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:13:45 -0500 Subject: [PATCH 282/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 79e8849..2760171 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,7 @@ package-repositories: apps: btop: command: usr/local/bin/btop - desktop: btop.desktop + desktop: usr/local/bin/share/applications/btop.desktop extensions: - gnome-3-38 environment: From b80ef50131822367460d327f207e3da8d1cf15a4 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:19:58 -0500 Subject: [PATCH 283/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 2760171..4b6d767 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,7 @@ package-repositories: apps: btop: command: usr/local/bin/btop - desktop: usr/local/bin/share/applications/btop.desktop + desktop: usr/local/share/applications/btop.desktop extensions: - gnome-3-38 environment: From e700334c354806ef8b12aef5a8e54f9324dedf54 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:29:22 -0500 Subject: [PATCH 284/289] Create btop.desktop --- snap/gui/btop.desktop | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 snap/gui/btop.desktop diff --git a/snap/gui/btop.desktop b/snap/gui/btop.desktop new file mode 100644 index 0000000..c613d67 --- /dev/null +++ b/snap/gui/btop.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=btop++ +GenericName=System Monitor +GenericName[it]=Monitor di sistema +Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes +Comment[it]=Monitoraggio delle risorse: mostra utilizzo e statistiche per CPU, dischi, rete e processi +Icon=${SNAP}/meta/gui/btop.svg +Exec=btop +Terminal=true +Categories=System;Monitor;ConsoleOnly; +Keywords=system;process;task From aa9b750bc556149bff0b30fe13ff688214b7baac Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:31:02 -0500 Subject: [PATCH 285/289] Add files via upload --- snap/gui/icon.svg | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 snap/gui/icon.svg diff --git a/snap/gui/icon.svg b/snap/gui/icon.svg new file mode 100644 index 0000000..402b842 --- /dev/null +++ b/snap/gui/icon.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From 00417c28d961f29b997c19b29a6c6704e1aa16fa Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:31:20 -0500 Subject: [PATCH 286/289] Update btop.desktop --- snap/gui/btop.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/gui/btop.desktop b/snap/gui/btop.desktop index c613d67..410d198 100644 --- a/snap/gui/btop.desktop +++ b/snap/gui/btop.desktop @@ -6,7 +6,7 @@ GenericName=System Monitor GenericName[it]=Monitor di sistema Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes Comment[it]=Monitoraggio delle risorse: mostra utilizzo e statistiche per CPU, dischi, rete e processi -Icon=${SNAP}/meta/gui/btop.svg +Icon=${SNAP}/meta/gui/icon.svg Exec=btop Terminal=true Categories=System;Monitor;ConsoleOnly; From 3b3b44e20b956f049acd5b32e40358cadd2cf6ee Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:32:12 -0500 Subject: [PATCH 287/289] Update btop.desktop --- snap/gui/btop.desktop | 2 -- 1 file changed, 2 deletions(-) diff --git a/snap/gui/btop.desktop b/snap/gui/btop.desktop index 410d198..0135a93 100644 --- a/snap/gui/btop.desktop +++ b/snap/gui/btop.desktop @@ -3,9 +3,7 @@ Type=Application Version=1.0 Name=btop++ GenericName=System Monitor -GenericName[it]=Monitor di sistema Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes -Comment[it]=Monitoraggio delle risorse: mostra utilizzo e statistiche per CPU, dischi, rete e processi Icon=${SNAP}/meta/gui/icon.svg Exec=btop Terminal=true From 46de9a595d116b02cd4d38505c32ab8ae8067a20 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:41:27 -0500 Subject: [PATCH 288/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 4b6d767..79e8849 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,7 @@ package-repositories: apps: btop: command: usr/local/bin/btop - desktop: usr/local/share/applications/btop.desktop + desktop: btop.desktop extensions: - gnome-3-38 environment: From 238f23a0cfdeb9c48d62bdfb1f0482db4ff8fae7 Mon Sep 17 00:00:00 2001 From: kz6fittycent Date: Sun, 21 Aug 2022 15:45:24 -0500 Subject: [PATCH 289/289] Update snapcraft.yaml --- snap/snapcraft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 79e8849..e000e9a 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,6 @@ package-repositories: apps: btop: command: usr/local/bin/btop - desktop: btop.desktop extensions: - gnome-3-38 environment: