diff --git a/Makefile b/Makefile index 7146d26..5159a1e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ PREFIX ?= /usr/local DOCDIR ?= $(PREFIX)/share/btop/doc CXX = g++ -CXXFLAGS = -std=c++20 -pthread +CXXFLAGS = -std=c++20 -pthread -Wall -Wextra INCLUDES = -I./src btop: btop.cpp diff --git a/btop.cpp b/btop.cpp index bbfd957..88412e6 100644 --- a/btop.cpp +++ b/btop.cpp @@ -25,10 +25,6 @@ tab-size = 4 #include #include #include -#include - -#include -#include #include @@ -41,6 +37,7 @@ tab-size = 4 #if defined(__linux__) #define SYSTEM "linux" #include + #include #elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__) #include #if defined(BSD) @@ -60,7 +57,6 @@ tab-size = 4 #endif using namespace std; -namespace fs = filesystem; //? ------------------------------------------------- GLOBALS --------------------------------------------------------- @@ -190,7 +186,7 @@ int main(int argc, char **argv){ if (debug < 2) cout << Term.alt_screen << Term.clear << Term.hide_cursor << flush; - cout << Theme("main_fg") << endl; + cout << Theme("main_fg") << Term.clear << endl; cout << Mv::r(Term.width / 2 - Banner.width / 2) << Banner() << endl; cout << string(Term.width - 1, '-') << endl; @@ -257,44 +253,37 @@ int main(int argc, char **argv){ - int count = 0; +//------>>>>>> + auto timestamp = time_ms(); - string item, name, cmd; - vector> plist; - for (auto& d: fs::directory_iterator("/proc")){ - item = fs::path(d.path()).filename(); - if (d.is_directory() && isdigit(item[0])) { - if (fs::is_regular_file((string)d.path() + "/comm")) { - ifstream pread((string)d.path() + "/comm"); - getline(pread, name); - pread.close(); - } - if (fs::is_regular_file((string)d.path() + "/cmdline")) { - ifstream pread((string)d.path() + "/cmdline"); - getline(pread, cmd); - pread.close(); - } - plist.push_back(make_tuple(stoi(item), name, cmd)); - } - } + + // insert Processes call here + timestamp = time_ms() - timestamp; auto timestamp2 = time_ms(); - ranges::sort(plist, [](tuple& a, tuple& b) {return get<1>(a) < get<1>(b);}); + + // insert Processes call here + timestamp2 = time_ms() - timestamp2; - int lc = 0; - cout << rjustify("Pid:", 8) << " " << ljustify("Program:", 16) << "Command:" << "\n"; - for (auto& [lpid, lname, lcmd] : plist){ //| views::reverse - cout << rjustify(to_string(lpid), 8) << " " << ljustify(limit(lname, 15), 16) << limit(lcmd, Term.width - 25) << "\n"; - if (lc++ > 30) break; - } + // int lc = 0; + // string ostring; + // cout << rjustify("Pid:", 8) << " " << ljustify("Program:", 16) << " " << ljustify("Command:", Term.width - 50) << " " << rjustify("User:", 10) << " " << rjustify("Group:", 10) << "\n"; + // for (auto& [lpid, lname, lcmd, luser, lgroup] : plist){ + // ostring += rjustify(to_string(lpid), 8) + " " + ljustify(lname, 16) + " " + ljustify(lcmd, Term.width - 50, true) + " " + rjustify(luser, 10) + " " + rjustify(lgroup, 10) + "\n"; + // if (lc++ > Term.height - 30) break; + // } - cout << endl; + // cout << ostring << endl; - cout << "List generated in " << timestamp << "ms and sorted in " << timestamp2 << "ms" << endl; - cout << "Found " << plist.size() << " pids\n" << endl; + // cout << "List generated in " << timestamp << "ms first call and in " << timestamp2 << "ms second call" << endl; + // cout << "Found " << plist.size() << " pids\n" << endl; + +//-----<<<<< + + //cout << pw->pw_name << "/" << gr->gr_name << endl; @@ -358,7 +347,7 @@ int main(int argc, char **argv){ if (debug == 0){ cout << Theme("main_fg"); cout << Mv::to(Term.height - 1, 0) << "Press q to exit! Timeout" << flush; - string full; + string full, key; int wt = 90; bool qp = false; while (!qp && wt >= 0){ @@ -368,10 +357,12 @@ int main(int argc, char **argv){ cout << Mv::to(Term.height - 1, 26) << "(" << wtm << ":" << wts << ") " << flush; //chr = Key(1000); if (Input(1000)) { - cout << Mv::to(Term.height - 2, 1) << "Last key: LEN=" << Input().size() << " ULEN=" << ulen(Input()) << " KEY=\"" << Input() << "\" CODE=" << (int)Input().at(0) << " " << flush; - full += Input(); + key = Input(); + cout << Mv::to(Term.height - 2, 1) << "Last key: LEN=" << key.size() << " ULEN=" << ulen(key) << " KEY=\"" << key << "\" CODE=" << (int)key.at(0) << " " << flush; + full += key; cout << Mv::to(Term.height - 5, 1) << full << flush; - if (Input() == "q") qp = true; + if (key == "q") qp = true; + key = ""; wt++; } } diff --git a/src/btop_config.h b/src/btop_config.h index 4cc9d91..5e7c3d2 100644 --- a/src/btop_config.h +++ b/src/btop_config.h @@ -25,7 +25,7 @@ tab-size = 4 #include -using std::string, std::to_string, std::vector, std::map; +using namespace std; //? Classes, functions and variables for reading and writing the btop config file diff --git a/src/btop_globs.h b/src/btop_globs.h index 2280f06..4c45d73 100644 --- a/src/btop_globs.h +++ b/src/btop_globs.h @@ -24,7 +24,7 @@ tab-size = 4 #include #include -using std::string, std::vector, std::map, std::atomic; +using namespace std; namespace Global { diff --git a/src/btop_input.h b/src/btop_input.h index 85c8ecf..06b9cfb 100644 --- a/src/btop_input.h +++ b/src/btop_input.h @@ -26,7 +26,7 @@ tab-size = 4 #include #include -using std::string, std::map, std::cin; +using namespace std; //* Class for handling keyboard and mouse input diff --git a/src/btop_linux.h b/src/btop_linux.h new file mode 100644 index 0000000..d158d6c --- /dev/null +++ b/src/btop_linux.h @@ -0,0 +1,122 @@ +/* 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 +*/ + +#ifndef _btop_linux_included_ +#define _btop_linux_included_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +// #include +#include + +#include +#include +#include + +namespace fs = std::filesystem; +using namespace std; + +class Processes { + uint64_t timestamp; + map> cache; + map sorts = { + {"pid", 0}, + {"name", 1}, + {"command", 2}, + {"user", 3} + }; + + + auto collect(string sorting="pid", bool reverse=false){ + int pid, count = 0; + auto timestamp = time_ms(); + string item, name, cmd, attr, user; + struct stat ug; + auto sortint = (sorts.contains(sorting)) ? sorts[sorting] : 0; + vector> procs; + for (auto& d: fs::directory_iterator("/proc")){ + item = fs::path(d.path()).filename(); + bool cached = false; + if (d.is_directory() && isdigit(item[0])) { + pid = stoi(item); + if (cache.contains(pid)) { + cached = true; + } else { + if (fs::is_regular_file((string)d.path() + "/comm")) { + ifstream pread((string)d.path() + "/comm"); + getline(pread, name); + pread.close(); + } + if (fs::is_regular_file((string)d.path() + "/cmdline")) { + ifstream pread((string)d.path() + "/cmdline"); + getline(pread, cmd); + // if (cmd.size() > 1) cmd.erase(cmd.size(), 1); + // cmd = to_string(ulen(cmd)) + ":" + to_string(cmd.size()) + cmd; + pread.close(); + } + if (fs::is_regular_file((string)d.path() + "/attr")) { + attr = (string)d.path() + "/attr"; + stat(attr.c_str(), &ug); // Error check omitted + struct passwd *pw = getpwuid(ug.st_uid); + user = pw->pw_name; + // struct group *gr = getgrgid(ug.st_gid); + } + cache[pid] = make_tuple(name, clean_nullbyte(cmd), user); + } + + procs.push_back(make_tuple(pid, get<0>(cache[pid]), get<1>(cache[pid]), get<2>(cache[pid]))); + } + } + + ranges::sort(procs, [sortint, reverse](tuple& a, tuple& b) { + if (reverse) { + switch (sortint) { + case 0: return get<0>(a) > get<0>(b); + case 1: return get<1>(a) > get<1>(b); + case 2: return get<2>(a) > get<2>(b); + case 3: return get<3>(a) > get<3>(b); + } + } else { + switch (sortint) { + case 0: return get<0>(a) < get<0>(b); + case 1: return get<1>(a) < get<1>(b); + case 2: return get<2>(a) < get<2>(b); + case 3: return get<3>(a) < get<3>(b); + } + } + }); + // if (reverse) views::reverse(procs); + + timestamp = time_ms() - timestamp; + + return procs; + } +}; + + + +#endif \ No newline at end of file diff --git a/src/btop_theme.h b/src/btop_theme.h index ec08f4f..9ec5ee1 100644 --- a/src/btop_theme.h +++ b/src/btop_theme.h @@ -28,7 +28,7 @@ tab-size = 4 #include #include -using std::string, std::to_string, std::round, std::vector, std::map; +using namespace std; //? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- diff --git a/src/btop_tools.h b/src/btop_tools.h index 4d8d957..60e9103 100644 --- a/src/btop_tools.h +++ b/src/btop_tools.h @@ -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, @@ -34,7 +34,7 @@ tab-size = 4 #include #include -using std::string, std::to_string, std::round, std::vector, std::map, std::cin, std::max; +using namespace std; //? ------------------------------------------------- NAMESPACES ------------------------------------------------------ @@ -95,10 +95,9 @@ namespace Mv { //? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- //* Return number of UTF8 characters in a string -inline size_t ulen(const string& str){ - size_t len = 0; - for (char c : str) if ((c & 0xC0) != 0x80) ++len; - return len; +size_t ulen(string s){ + return std::count_if(s.begin(), s.end(), + [](char c) { return (static_cast(c) & 0xC0) != 0x80; } ); } //* Return current time since epoch in milliseconds @@ -156,19 +155,39 @@ void sleep_ms(unsigned ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } -//* Left justify string if is greater than length -string ljustify(string str, size_t x){ - return str + string(max((int)(x - str.size()), 0), ' '); +//* Left justify string if is greater than length, limit return size to by default +string ljustify(string str, size_t x, bool utf=false, bool lim=true){ + if (!utf) { + if (lim && str.size() > x) str.resize(x); + return str + string(max((int)(x - str.size()), 0), ' '); + } else { + if (lim && ulen(str) > x) { + auto i = str.size(); + while (ulen(str) > x) str.resize(--i); + } + return str + string(max((int)(x - ulen(str)), 0), ' '); + } } -//* Right justify string if is greater than length -string rjustify(string str, size_t x){ - return string(max((int)(x - str.size()), 0), ' ') + str; +//* Right justify string if is greater than length, limit return size to by default +string rjustify(string str, size_t x, bool utf=false, bool lim=true){ + if (!utf) { + if (lim && str.size() > x) str.resize(x); + return string(max((int)(x - str.size()), 0), ' ') + str; + } else { + if (lim && ulen(str) > x) { + auto i = str.size(); + while (ulen(str) > x) str.resize(--i); + } + return string(max((int)(x - ulen(str)), 0), ' ') + str; + } } -//* Trim trailing characters if string length is greatear than -string limit(string str, size_t x){ - if (str.size() > x) str.resize(x); +//* Trim trailing characters if utf8 string length is greatear than +string uresize(string str, size_t x){ + auto i = str.size(); + if (i < 1 || x < 1) return str; + while (ulen(str) > x) str.resize(--i); return str; } @@ -187,6 +206,12 @@ string trans(string str){ return (newstr.empty()) ? str : newstr; } +//* Clean string by replacing null byte '\0' with whitespace ' ' +string clean_nullbyte(string str){ + while (str.find('\0') != string::npos) str.replace(str.find('\0'), 1, " "); + return str; +} + string sec_to_dhms(unsigned sec){ string out; unsigned d, h, m; @@ -307,4 +332,4 @@ public: //? --------------------------------------------------- STRUCTS ------------------------------------------------------- -#endif \ No newline at end of file +#endif