Changes from main + fixes

This commit is contained in:
aristocratos 2021-11-13 23:15:53 +01:00
parent bd5d867089
commit c2c4fe47db
13 changed files with 247 additions and 114 deletions

View file

@ -1,3 +1,47 @@
## 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
* 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
## 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
* 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
## v1.0.18 ## v1.0.18
* Fixed: Makefile g++ -dumpmachine failure to get platform on some distros * Fixed: Makefile g++ -dumpmachine failure to get platform on some distros

View file

@ -57,7 +57,6 @@ else ifeq ($(shell command -v g++11 >/dev/null; echo $$?),0)
else ifeq ($(shell command -v g++ >/dev/null; echo $$?),0) else ifeq ($(shell command -v g++ >/dev/null; echo $$?),0)
CXX := g++ CXX := g++
endif endif
override CXX_VERSION := $(shell $(CXX) -dumpfullversion -dumpversion || echo 0) 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 #? Try to make sure we are using GCC/G++ version 11 or later if not instructed to use g++-10
@ -116,17 +115,13 @@ override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main
#? Flags, Libraries and Includes #? Flags, Libraries and Includes
override REQFLAGS := -std=c++20 override REQFLAGS := -std=c++20
WARNFLAGS := -Wall -Wextra -pedantic WARNFLAGS := -Wall -Wextra -pedantic
OPTFLAGS ?= -O2 -ftree-loop-vectorize -flto=$(THREADS) OPTFLAGS := -O2 -ftree-loop-vectorize -flto=$(THREADS)
LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS $(GOODFLAGS) $(ADDFLAGS) LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS $(GOODFLAGS) $(ADDFLAGS)
override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
INC := -I$(INCDIR) -I$(SRCDIR) INC := -I$(INCDIR) -I$(SRCDIR)
SU_USER := root SU_USER := root
ifdef DEBUG
override OPTFLAGS := -O0 -g
endif
SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)) SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT))
SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)) SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT))
@ -192,7 +187,6 @@ install:
@printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n" @printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n"
@cp -pr themes $(DESTDIR)$(PREFIX)/share/btop @cp -pr themes $(DESTDIR)$(PREFIX)/share/btop
#? Set SUID bit for btop as $SU_USER in $SU_GROUP #? Set SUID bit for btop as $SU_USER in $SU_GROUP
setuid: setuid:
@printf "\033[1;97mFile: $(DESTDIR)$(PREFIX)/bin/btop\n" @printf "\033[1;97mFile: $(DESTDIR)$(PREFIX)/bin/btop\n"

View file

@ -12,7 +12,7 @@
[![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/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) [![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) [![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop)
[![Continuous Build Linux](https://github.com/aristocratos/btop/actions/workflows/continuous-build.yml/badge.svg)](https://github.com/aristocratos/btop/actions) [![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) [![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)
@ -39,9 +39,38 @@
### Under development ### 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 ##### 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. See branch [OSX](https://github.com/aristocratos/btop/tree/OSX) for current progress.
##### 18 September 2021 ##### 18 September 2021
@ -180,6 +209,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** 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)** 2. **Install (from created folder)**
* **Run install.sh or:** * **Run install.sh or:**

View file

@ -53,7 +53,7 @@ namespace Global {
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
}; };
const string Version = "1.0.18"; const string Version = "1.0.24";
int coreCount; int coreCount;
string overlay; string overlay;
@ -64,6 +64,7 @@ namespace Global {
string fg_green = "\x1b[1;92m"; string fg_green = "\x1b[1;92m";
string fg_red = "\x1b[0;91m"; string fg_red = "\x1b[0;91m";
uid_t real_uid, set_uid;
fs::path self_path; fs::path self_path;
@ -78,6 +79,8 @@ namespace Global {
atomic<bool> resized (false); atomic<bool> resized (false);
atomic<bool> quitting (false); atomic<bool> quitting (false);
atomic<bool> should_quit (false);
atomic<bool> should_sleep (false);
atomic<bool> _runner_started (false); atomic<bool> _runner_started (false);
bool arg_tty = false; bool arg_tty = false;
@ -85,7 +88,6 @@ namespace Global {
int arg_preset = -1; int arg_preset = -1;
} }
//* A simple argument parser //* A simple argument parser
void argumentParser(const int& argc, char **argv) { void argumentParser(const int& argc, char **argv) {
for(int i = 1; i < argc; i++) { for(int i = 1; i < argc; i++) {
@ -214,7 +216,6 @@ void clean_quit(int sig) {
} }
Config::write(); Config::write();
Input::clear();
//? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms //? 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++) { for (int i = 0; Tools::active_locks > 0 and i < 100; i++) {
@ -222,6 +223,7 @@ void clean_quit(int sig) {
} }
if (Term::initialized) { if (Term::initialized) {
Input::clear();
Term::restore(); Term::restore();
} }
@ -262,10 +264,24 @@ void _exit_handler() {
void _signal_handler(const int sig) { void _signal_handler(const int sig) {
switch (sig) { switch (sig) {
case SIGINT: case SIGINT:
clean_quit(0); if (Runner::active) {
Global::should_quit = true;
Runner::stopping = true;
Input::interrupt = true;
}
else {
clean_quit(0);
}
break; break;
case SIGTSTP: case SIGTSTP:
_sleep(); if (Runner::active) {
Global::should_sleep = true;
Runner::stopping = true;
Input::interrupt = true;
}
else {
_sleep();
}
break; break;
case SIGCONT: case SIGCONT:
_resume(); _resume();
@ -303,10 +319,22 @@ namespace Runner {
pthread_mutex_t& pt_mutex; pthread_mutex_t& pt_mutex;
public: public:
int status; 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); } ~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 output;
string empty_bg; string empty_bg;
bool pause_output = false; bool pause_output = false;
@ -359,10 +387,10 @@ namespace Runner {
//? ------------------------------- Secondary thread: async launcher and drawing ---------------------------------- //? ------------------------------- Secondary thread: async launcher and drawing ----------------------------------
void * _runner(void * _) { void * _runner(void * _) {
(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); sigemptyset(&mask);
sigaddset(&mask, SIGINT); // sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTSTP); // sigaddset(&mask, SIGTSTP);
sigaddset(&mask, SIGWINCH); sigaddset(&mask, SIGWINCH);
sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &mask, NULL); pthread_sigmask(SIG_BLOCK, &mask, NULL);
@ -394,6 +422,9 @@ namespace Runner {
//? Atomic lock used for blocking non thread-safe actions in main thread //? Atomic lock used for blocking non thread-safe actions in main thread
atomic_lock lck(active); atomic_lock lck(active);
//? Set effective user if SUID bit is set
gain_priv powers{};
auto& conf = current_conf; auto& conf = current_conf;
//! DEBUG stats //! DEBUG stats
@ -407,44 +438,23 @@ namespace Runner {
//* Run collection and draw functions for all boxes //* Run collection and draw functions for all boxes
try { try {
//? PROC //? CPU
if (v_contains(conf.boxes, "proc")) { if (v_contains(conf.boxes, "cpu")) {
try { try {
if (Global::debug) debug_timer("proc", collect_begin); if (Global::debug) debug_timer("cpu", collect_begin);
//? Start collect //? 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 //? 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) { catch (const std::exception& e) {
throw std::runtime_error("Proc:: -> " + (string)e.what()); throw std::runtime_error("Cpu:: -> " + (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());
} }
} }
@ -468,23 +478,43 @@ namespace Runner {
} }
} }
//? CPU //? NET
if (v_contains(conf.boxes, "cpu")) { if (v_contains(conf.boxes, "net")) {
try { try {
if (Global::debug) debug_timer("cpu", collect_begin); if (Global::debug) debug_timer("net", collect_begin);
//? Start collect //? 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 //? 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) { 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());
} }
} }
} }
@ -540,7 +570,6 @@ namespace Runner {
<< Term::sync_end << flush; << Term::sync_end << flush;
} }
//* ----------------------------------------------- THREAD LOOP ----------------------------------------------- //* ----------------------------------------------- THREAD LOOP -----------------------------------------------
pthread_exit(NULL); pthread_exit(NULL);
} }
//? ------------------------------------------ Secondary thread end ----------------------------------------------- //? ------------------------------------------ Secondary thread end -----------------------------------------------
@ -625,6 +654,17 @@ int main(int argc, char **argv) {
Global::start_time = time_s(); 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 //? Call argument parser if launched with arguments
if (argc > 1) argumentParser(argc, argv); if (argc > 1) argumentParser(argc, argv);
@ -827,6 +867,8 @@ int main(int argc, char **argv) {
while (not true not_eq not false) { while (not true not_eq not false) {
//? Check for exceptions in secondary thread and exit with fail signal if true //? Check for exceptions in secondary thread and exit with fail signal if true
if (Global::thread_exception) exit(1); 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) //? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly)
term_resize(); term_resize();

View file

@ -479,7 +479,7 @@ namespace Config {
} }
catch (const std::exception& e) { catch (const std::exception& e) {
Global::exit_error_msg = "Exception during Config::unlock() : " + (string)e.what(); Global::exit_error_msg = "Exception during Config::unlock() : " + (string)e.what();
exit(1); clean_quit(1);
} }
locked = false; locked = false;
@ -530,9 +530,8 @@ namespace Config {
vector<string> valid_names; vector<string> valid_names;
for (auto &n : descriptions) for (auto &n : descriptions)
valid_names.push_back(n[0]); valid_names.push_back(n[0]);
string v_string;
getline(cread, v_string, '\n'); if (string v_string; cread.peek() != '#' or (getline(cread, v_string, '\n') and not s_contains(v_string, Global::Version)))
if (not s_contains(v_string, Global::Version))
write_new = true; write_new = true;
while (not cread.eof()) { while (not cread.eof()) {
cread >> std::ws; cread >> std::ws;
@ -589,6 +588,7 @@ namespace Config {
void write() { void write() {
if (conf_file.empty() or not write_new) return; if (conf_file.empty() or not write_new) return;
Logger::debug("Writing new config file"); 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); std::ofstream cwrite(conf_file, std::ios::trunc);
if (cwrite.good()) { if (cwrite.good()) {
cwrite << "#? Config file for btop v. " << Global::Version; cwrite << "#? Config file for btop v. " << Global::Version;

View file

@ -32,8 +32,6 @@ using std::cin, std::vector, std::string_literals::operator""s;
using namespace Tools; using namespace Tools;
namespace rng = std::ranges; namespace rng = std::ranges;
extern void clean_quit(int sig);
namespace Input { namespace Input {
//* Map for translating key codes to readable values //* Map for translating key codes to readable values
@ -97,7 +95,7 @@ namespace Input {
string get() { string get() {
string key; string key;
while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get(); 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()) { if (not key.empty()) {
//? Remove escape code prefix if present //? Remove escape code prefix if present
if (key.substr(0, 2) == Fx::e) { if (key.substr(0, 2) == Fx::e) {
@ -177,7 +175,11 @@ namespace Input {
} }
void clear() { 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) { void process(const string& key) {
@ -268,7 +270,7 @@ namespace Input {
cur_i = 0; cur_i = 0;
Config::set("proc_sorting", Proc::sort_vector.at(cur_i)); Config::set("proc_sorting", Proc::sort_vector.at(cur_i));
} }
else if (key == "f") { else if (is_in(key, "f", "/")) {
Config::flip("proc_filtering"); Config::flip("proc_filtering");
Proc::filter = { Config::getS("proc_filter") }; Proc::filter = { Config::getS("proc_filter") };
old_filter = Proc::filter.text; old_filter = Proc::filter.text;

View file

@ -126,7 +126,7 @@ namespace Menu {
{"z", "Toggle totals reset for current network device"}, {"z", "Toggle totals reset for current network device"},
{"a", "Toggle auto scaling for the network graphs."}, {"a", "Toggle auto scaling for the network graphs."},
{"y", "Toggle synced scaling mode for 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."}, {"delete", "Clear any entered filter."},
{"c", "Toggle per-core cpu usage of processes."}, {"c", "Toggle per-core cpu usage of processes."},
{"r", "Reverse sorting order in processes box."}, {"r", "Reverse sorting order in processes box."},
@ -892,10 +892,7 @@ namespace Menu {
}; };
} }
} }
else if (key == "q") { else if (is_in(key, "escape", "q", "m", "mouse_click")) {
exit(0);
}
else if (is_in(key, "escape", "m", "mouse_click")) {
return Closed; return Closed;
} }
else if (key.starts_with("button_")) { else if (key.starts_with("button_")) {
@ -916,7 +913,7 @@ namespace Menu {
currentMenu = Menus::Help; currentMenu = Menus::Help;
return Switch; return Switch;
case Quit: case Quit:
exit(0); clean_quit(0);
} }
} }
else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) { else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) {
@ -1142,8 +1139,8 @@ namespace Menu {
auto& optList = optionsList.at(option).get(); auto& optList = optionsList.at(option).get();
int i = v_index(optList, Config::getS(option)); int i = v_index(optList, Config::getS(option));
if (key == "right" and ++i >= (int)optList.size()) i = 0; if ((key == "right" or (vim_keys and key == "l")) and ++i >= (int)optList.size()) i = 0;
else if (key == "left" and --i < 0) i = optList.size() - 1; else if ((key == "left" or (vim_keys and key == "h")) and --i < 0) i = optList.size() - 1;
Config::set(option, optList.at(i)); Config::set(option, optList.at(i));
if (option == "color_theme") if (option == "color_theme")

View file

@ -27,12 +27,15 @@ tab-size = 4
#include <array> #include <array>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <tuple> #include <tuple>
#include <unistd.h>
using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std::atomic, std::array, std::tuple; using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std::atomic, std::array, std::tuple;
void term_resize(bool force=false); void term_resize(bool force=false);
void banner_gen(); void banner_gen();
extern void clean_quit(int sig);
namespace Global { namespace Global {
extern const vector<array<string, 2>> Banner_src; extern const vector<array<string, 2>> Banner_src;
extern const string Version; extern const string Version;
@ -43,6 +46,7 @@ namespace Global {
extern atomic<bool> resized; extern atomic<bool> resized;
extern string overlay; extern string overlay;
extern string clock; extern string clock;
extern uid_t real_uid, set_uid;
} }
namespace Runner { namespace Runner {
@ -69,7 +73,7 @@ namespace Shared {
//* Initialize platform specific needed variables and check for errors //* Initialize platform specific needed variables and check for errors
void init(); void init();
extern long coreCount, page_size, clkTck; extern long coreCount, page_size, clk_tck;
} }

View file

@ -23,10 +23,10 @@ tab-size = 4
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <utility> #include <utility>
#include <ranges>
#include <robin_hood.h> #include <robin_hood.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#include <termios.h> #include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -46,7 +46,6 @@ namespace Term {
atomic<int> width = 0; atomic<int> width = 0;
atomic<int> height = 0; atomic<int> height = 0;
string current_tty; string current_tty;
char* custombuf;
namespace { namespace {
struct termios initial_settings; struct termios initial_settings;
@ -122,9 +121,6 @@ namespace Term {
linebuffered(false); linebuffered(false);
refresh(); refresh();
//? Set 1MB buffer for cout
std::cout.rdbuf()->pubsetbuf(custombuf, 1048576);
cout << alt_screen << hide_cursor << mouse_on << flush; cout << alt_screen << hide_cursor << mouse_on << flush;
Global::resized = false; Global::resized = false;
} }
@ -143,6 +139,25 @@ namespace Term {
//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- //? --------------------------------------------------- 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); not isdigit(out[end_pos - 1]) or end_pos - start_pos > next_pos - start_pos)
continue;
out.replace(start_pos, end_pos - start_pos, "");
next_pos = 0;
}
out.shrink_to_fit();
return out;
}
}
namespace Tools { namespace Tools {
atomic<int> active_locks (0); atomic<int> active_locks (0);
@ -391,6 +406,18 @@ namespace Logger {
size_t loglevel; size_t loglevel;
fs::path logfile; 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) { void set(const string& level) {
loglevel = v_index(log_levels, level); loglevel = v_index(log_levels, level);
} }
@ -398,6 +425,7 @@ namespace Logger {
void log_write(const size_t level, const string& msg) { void log_write(const size_t level, const string& msg) {
if (loglevel < level or logfile.empty()) return; if (loglevel < level or logfile.empty()) return;
atomic_lock lck(busy, true); atomic_lock lck(busy, true);
lose_priv neutered{};
std::error_code ec; std::error_code ec;
try { try {
if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) { if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) {

View file

@ -21,7 +21,6 @@ tab-size = 4
#include <string> #include <string>
#include <vector> #include <vector>
#include <array> #include <array>
#include <regex>
#include <atomic> #include <atomic>
#include <filesystem> #include <filesystem>
#include <ranges> #include <ranges>
@ -29,16 +28,17 @@ tab-size = 4
#include <thread> #include <thread>
#include <tuple> #include <tuple>
#include <pthread.h> #include <pthread.h>
#include <limits.h>
using std::string, std::vector, std::atomic, std::to_string, std::regex, std::tuple, std::array;
#ifndef HOST_NAME_MAX #ifndef HOST_NAME_MAX
#if defined(__APPLE__) #ifdef __APPLE__
#define HOST_NAME_MAX 255 #define HOST_NAME_MAX 255
#else #else
#define HOST_NAME_MAX 64 #define HOST_NAME_MAX 64
#endif /* __APPLE__ */ #endif
#endif /* HOST_NAME_MAX */ #endif
using std::string, std::vector, std::atomic, std::to_string, std::tuple, std::array;
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------ //? ------------------------------------------------- NAMESPACES ------------------------------------------------------
@ -64,14 +64,8 @@ namespace Fx {
//* Reset text effects and restore theme foregrund and background color //* Reset text effects and restore theme foregrund and background color
extern string reset; 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 //* 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);
} }
@ -114,7 +108,7 @@ namespace Term {
const string clear_end = Fx::e + "0J"; const string clear_end = Fx::e + "0J";
const string clear_begin = Fx::e + "1J"; 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_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_on = Fx::e + "?1003h"; //? Enable reporting of mouse position at any movement
const string mouse_direct_off = Fx::e + "?1003l"; const string mouse_direct_off = Fx::e + "?1003l";
const string sync_start = Fx::e + "?2026h"; //? Start of terminal synchronized output const string sync_start = Fx::e + "?2026h"; //? Start of terminal synchronized output

View file

@ -21,7 +21,6 @@ tab-size = 4
#include <cmath> #include <cmath>
#include <unistd.h> #include <unistd.h>
#include <numeric> #include <numeric>
#include <regex>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <netdb.h> #include <netdb.h>
#include <ifaddrs.h> #include <ifaddrs.h>
@ -217,9 +216,9 @@ namespace Cpu {
name += n + ' '; name += n + ' ';
} }
name.pop_back(); name.pop_back();
for (const auto& reg : {regex("Processor"), regex("CPU"), regex("\\(R\\)"), regex("\\(TM\\)"), regex("Intel"), for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) {
regex("AMD"), regex("Core"), regex("\\d?\\.?\\d+[mMgG][hH][zZ]")}) { name = s_replace(name, replace, "");
name = std::regex_replace(name, reg, ""); name = s_replace(name, " ", " ");
} }
name = trim(name); name = trim(name);
} }
@ -313,7 +312,7 @@ namespace Cpu {
if (not got_coretemp or core_sensors.empty()) cpu_temp_only = true; if (not got_coretemp or core_sensors.empty()) cpu_temp_only = true;
if (cpu_sensor.empty() and not found_sensors.empty()) { if (cpu_sensor.empty() and not found_sensors.empty()) {
for (const auto& [name, sensor] : found_sensors) { for (const auto& [name, sensor] : found_sensors) {
if (s_contains(str_to_lower(name), "cpu")) { if (s_contains(str_to_lower(name), "cpu") or s_contains(str_to_lower(name), "k10temp")) {
cpu_sensor = name; cpu_sensor = name;
break; break;
} }
@ -905,8 +904,8 @@ namespace Mem {
//? Get disk/partition stats //? Get disk/partition stats
for (auto& [mountpoint, disk] : disks) { for (auto& [mountpoint, disk] : disks) {
if (std::error_code ec; not fs::exists(mountpoint, ec)) continue; if (std::error_code ec; not fs::exists(mountpoint, ec)) continue;
struct statvfs vfs; struct statvfs64 vfs;
if (statvfs(mountpoint.c_str(), &vfs) < 0) { if (statvfs64(mountpoint.c_str(), &vfs) < 0) {
Logger::warning("Failed to get disk/partition stats with statvfs() for: " + mountpoint); Logger::warning("Failed to get disk/partition stats with statvfs() for: " + mountpoint);
continue; continue;
} }
@ -1066,7 +1065,7 @@ namespace Net {
auto& bandwidth = net.at(iface).bandwidth.at(dir); auto& bandwidth = net.at(iface).bandwidth.at(dir);
uint64_t val = saved_stat.last; 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::invalid_argument&) {}
catch (const std::out_of_range&) {} catch (const std::out_of_range&) {}

View file

@ -230,11 +230,11 @@ namespace Cpu {
name += n + ' '; name += n + ' ';
} }
name.pop_back(); name.pop_back();
for (const auto &reg : {regex("Processor"), regex("CPU"), regex("\\(R\\)"), regex("\\(TM\\)"), regex("Intel"), for (const auto& replace : {"Processor", "CPU", "(R)", "(TM)", "Intel", "AMD", "Core"}) {
regex("AMD"), regex("Core"), regex("\\d?\\.?\\d+[mMgG][hH][zZ]")}) { name = s_replace(name, replace, "");
name = std::regex_replace(name, reg, ""); name = s_replace(name, " ", " ");
} }
name = trim(name); name = trim(name);
} }
return name; return name;

View file

@ -3,11 +3,9 @@
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <IOKit/hidsystem/IOHIDEventSystemClient.h> #include <IOKit/hidsystem/IOHIDEventSystemClient.h>
#include <btop_tools.hpp>
#include <iostream>
#include <map>
#include <string> #include <string>
#include <numeric> #include <numeric>
#include <vector>
extern "C" { extern "C" {
typedef struct __IOHIDEvent *IOHIDEventRef; typedef struct __IOHIDEvent *IOHIDEventRef;
@ -62,7 +60,7 @@ long long Cpu::ThermalSensors::getSensors() {
IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault); IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
IOHIDEventSystemClientSetMatching(system, thermalSensors); IOHIDEventSystemClientSetMatching(system, thermalSensors);
CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system); CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system);
vector<double> temps; std::vector<double> temps;
if (matchingsrvs) { if (matchingsrvs) {
long count = CFArrayGetCount(matchingsrvs); long count = CFArrayGetCount(matchingsrvs);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {