Testing Processes class

This commit is contained in:
aristocratos 2021-05-10 23:46:41 +02:00
parent 73098b70f5
commit d1180d6b38
8 changed files with 198 additions and 60 deletions

View file

@ -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

View file

@ -25,10 +25,6 @@ tab-size = 4
#include <thread>
#include <future>
#include <atomic>
#include <ranges>
#include <fstream>
#include <filesystem>
#include <unistd.h>
@ -41,6 +37,7 @@ tab-size = 4
#if defined(__linux__)
#define SYSTEM "linux"
#include <sys/sysinfo.h>
#include <btop_linux.h>
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h>
#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<tuple<int, string, string>> 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<int, string, string>& a, tuple<int, string, string>& 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++;
}
}

View file

@ -25,7 +25,7 @@ tab-size = 4
#include <btop_tools.h>
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

View file

@ -24,7 +24,7 @@ tab-size = 4
#include <vector>
#include <atomic>
using std::string, std::vector, std::map, std::atomic;
using namespace std;
namespace Global {

View file

@ -26,7 +26,7 @@ tab-size = 4
#include <btop_globs.h>
#include <btop_tools.h>
using std::string, std::map, std::cin;
using namespace std;
//* Class for handling keyboard and mouse input

122
src/btop_linux.h Normal file
View file

@ -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 <string>
#include <vector>
#include <tuple>
#include <map>
#include <atomic>
#include <fstream>
#include <filesystem>
#include <ranges>
#include <unistd.h>
#include <pwd.h>
// #include <grp.h>
#include <sys/stat.h>
#include <btop_config.h>
#include <btop_globs.h>
#include <btop_tools.h>
namespace fs = std::filesystem;
using namespace std;
class Processes {
uint64_t timestamp;
map<int, tuple<string, string, string>> cache;
map<string, unsigned> 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<tuple<int, string, string, string>> 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<int, string, string, string>& a, tuple<int, string, string, string>& 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

View file

@ -28,7 +28,7 @@ tab-size = 4
#include <btop_tools.h>
#include <btop_config.h>
using std::string, std::to_string, std::round, std::vector, std::map;
using namespace std;
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------

View file

@ -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 <btop_globs.h>
#include <btop_config.h>
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<unsigned char>(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 <str> if <x> is greater than <str> length
string ljustify(string str, size_t x){
return str + string(max((int)(x - str.size()), 0), ' ');
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> 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 <str> if <x> is greater than <str> length
string rjustify(string str, size_t x){
return string(max((int)(x - str.size()), 0), ' ') + str;
//* Right justify string <str> if <x> is greater than <str> length, limit return size to <x> 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 <x>
string limit(string str, size_t x){
if (str.size() > x) str.resize(x);
//* Trim trailing characters if utf8 string length is greatear than <x>
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
#endif