summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/app')
-rw-r--r--src/app/data_harvester/processes.rs67
-rw-r--r--src/app/query.rs27
-rw-r--r--src/app/states.rs56
3 files changed, 126 insertions, 24 deletions
diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs
index c9233337..56bf09d4 100644
--- a/src/app/data_harvester/processes.rs
+++ b/src/app/data_harvester/processes.rs
@@ -2,8 +2,11 @@ use crate::Pid;
use std::path::PathBuf;
use sysinfo::ProcessStatus;
+#[cfg(target_family = "unix")]
+use crate::utils::error;
+
#[cfg(target_os = "linux")]
-use crate::utils::error::{self, BottomError};
+use crate::utils::error::BottomError;
#[cfg(target_os = "linux")]
use fnv::{FnvHashMap, FnvHashSet};
@@ -29,28 +32,29 @@ pub enum ProcessSorting {
TotalRead,
TotalWrite,
State,
+ User,
Count,
}
impl std::fmt::Display for ProcessSorting {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use ProcessSorting::*;
write!(
f,
"{}",
match &self {
- CpuPercent => "CPU%",
- MemPercent => "Mem%",
- Mem => "Mem",
- ReadPerSecond => "R/s",
- WritePerSecond => "W/s",
- TotalRead => "T.Read",
- TotalWrite => "T.Write",
- State => "State",
- ProcessName => "Name",
- Command => "Command",
- Pid => "PID",
- Count => "Count",
+ ProcessSorting::CpuPercent => "CPU%",
+ ProcessSorting::MemPercent => "Mem%",
+ ProcessSorting::Mem => "Mem",
+ ProcessSorting::ReadPerSecond => "R/s",
+ ProcessSorting::WritePerSecond => "W/s",
+ ProcessSorting::TotalRead => "T.Read",
+ ProcessSorting::TotalWrite => "T.Write",
+ ProcessSorting::State => "State",
+ ProcessSorting::ProcessName => "Name",
+ ProcessSorting::Command => "Command",
+ ProcessSorting::Pid => "PID",
+ ProcessSorting::Count => "Count",
+ ProcessSorting::User => "User",
}
)
}
@@ -81,9 +85,13 @@ pub struct ProcessHarvest {
pub process_state_char: char,
/// This is the *effective* user ID.
- pub uid: Option<u32>,
- // pub real_uid: Option<u32>, // TODO: Add real user ID
- pub gid: Option<u32>,
+ #[cfg(target_family = "unix")]
+ pub uid: Option<libc::uid_t>,
+
+ // TODO: Add real user ID
+ // pub real_uid: Option<u32>,
+ #[cfg(target_family = "unix")]
+ pub gid: Option<libc::gid_t>,
}
#[derive(Debug, Default, Clone)]
@@ -114,6 +122,29 @@ impl PrevProcDetails {
}
}
+#[cfg(target_family = "unix")]
+#[derive(Debug, Default)]
+pub struct UserTable {
+ pub uid_user_mapping: std::collections::HashMap<libc::uid_t, String>,
+}
+
+#[cfg(target_family = "unix")]
+impl UserTable {
+ pub fn get_uid_to_username_mapping(&mut self, uid: libc::uid_t) -> error::Result<String> {
+ if let Some(user) = self.uid_user_mapping.get(&uid) {
+ Ok(user.clone())
+ } else {
+ let passwd = unsafe { libc::getpwuid(uid) };
+ let username = unsafe { std::ffi::CStr::from_ptr((*passwd).pw_name) }
+ .to_str()?
+ .to_string();
+ self.uid_user_mapping.insert(uid, username.clone());
+
+ Ok(username)
+ }
+ }
+}
+
#[cfg(target_os = "linux")]
fn cpu_usage_calculation(
prev_idle: &mut f64, prev_non_idle: &mut f64,
@@ -591,8 +622,6 @@ pub fn get_process_data(
total_write_bytes: disk_usage.total_written_bytes,
process_state: process_val.status().to_string().to_string(),
process_state_char: convert_process_status_to_char(process_val.status()),
- uid: None,
- gid: None,
});
}
}
diff --git a/src/app/query.rs b/src/app/query.rs
index 79f61e73..5a827aec 100644
--- a/src/app/query.rs
+++ b/src/app/query.rs
@@ -26,7 +26,8 @@ pub trait ProcessQuery {
/// - PIDs: Use prefix `pid`, can use regex or match word (case is irrelevant).
/// - CPU: Use prefix `cpu`, cannot use r/m/c (regex, match word, case). Can compare.
/// - MEM: Use prefix `mem`, cannot use r/m/c. Can compare.
- /// - STATE: Use prefix `state`, TODO when we update how state looks in 0.5 probably.
+ /// - STATE: Use prefix `state`, can use regex, match word, or case.
+ /// - USER: Use prefix `user`, can use regex, match word, or case.
/// - Read/s: Use prefix `r`. Can compare.
/// - Write/s: Use prefix `w`. Can compare.
/// - Total read: Use prefix `read`. Can compare.
@@ -128,8 +129,6 @@ impl ProcessQuery for ProcWidgetState {
fn process_prefix(query: &mut VecDeque<String>, inside_quotation: bool) -> Result<Prefix> {
if let Some(queue_top) = query.pop_front() {
- // debug!("Prefix QT: {:?}", queue_top);
-
if inside_quotation {
if queue_top == "\"" {
// This means we hit something like "". Return an empty prefix, and to deal with
@@ -264,11 +263,20 @@ impl ProcessQuery for ProcWidgetState {
compare_prefix: None,
})
}
- PrefixType::Pid | PrefixType::State => {
+ PrefixType::Pid | PrefixType::State | PrefixType::User => {
// We have to check if someone put an "="...
if content == "=" {
// Check next string if possible
if let Some(queue_next) = query.pop_front() {
+ // TODO: Need to consider the following cases:
+ // - (test)
+ // - (test
+ // - test)
+ // These are split into 2 to 3 different strings due to parentheses being
+ // delimiters in our query system.
+ //
+ // Do we want these to be valid? They should, as a string, right?
+
return Ok(Prefix {
or: None,
regex_prefix: Some((
@@ -580,6 +588,7 @@ pub enum PrefixType {
TWrite,
Name,
State,
+ User,
__Nonexhaustive,
}
@@ -602,6 +611,7 @@ impl std::str::FromStr for PrefixType {
"twrite" | "t.write" => Ok(TWrite),
"pid" => Ok(Pid),
"state" => Ok(State),
+ "user" => Ok(User),
_ => Ok(Name),
}
}
@@ -628,7 +638,7 @@ impl Prefix {
} else if let Some((prefix_type, StringQuery::Value(regex_string))) = &mut self.regex_prefix
{
match prefix_type {
- PrefixType::Pid | PrefixType::Name | PrefixType::State => {
+ PrefixType::Pid | PrefixType::Name | PrefixType::State | PrefixType::User => {
let escaped_regex: String;
let final_regex_string = &format!(
"{}{}{}{}",
@@ -681,6 +691,13 @@ impl Prefix {
}),
PrefixType::Pid => r.is_match(process.pid.to_string().as_str()),
PrefixType::State => r.is_match(process.process_state.as_str()),
+ PrefixType::User => {
+ if let Some(user) = &process.user {
+ r.is_match(user.as_str())
+ } else {
+ false
+ }
+ }
_ => true,
}
} else {
diff --git a/src/app/states.rs b/src/app/states.rs
index c2853337..39dd0222 100644
--- a/src/app/states.rs
+++ b/src/app/states.rs
@@ -174,6 +174,9 @@ impl ProcessSearchState {
pub struct ColumnInfo {
pub enabled: bool,
pub shortcut: Option<&'static str>,
+ // FIXME: Move column width logic here!
+ // pub hard_width: Option<u16>,
+ // pub max_soft_width: Option<f64>,
}
pub struct ProcColumn {
@@ -205,6 +208,7 @@ impl Default for ProcColumn {
WritePerSecond,
TotalRead,
TotalWrite,
+ User,
State,
];
@@ -219,6 +223,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: true,
shortcut: Some("c"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -228,6 +234,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: true,
shortcut: Some("m"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -237,6 +245,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: false,
shortcut: Some("m"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -246,6 +256,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: true,
shortcut: Some("n"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -255,6 +267,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: false,
shortcut: Some("n"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -264,6 +278,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: true,
shortcut: Some("p"),
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -273,6 +289,17 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: false,
shortcut: None,
+ // hard_width: None,
+ // max_soft_width: None,
+ },
+ );
+ }
+ User => {
+ column_mapping.insert(
+ column,
+ ColumnInfo {
+ enabled: cfg!(target_family = "unix"),
+ shortcut: None,
},
);
}
@@ -282,6 +309,8 @@ impl Default for ProcColumn {
ColumnInfo {
enabled: true,
shortcut: None,
+ // hard_width: None,
+ // max_soft_width: None,
},
);
}
@@ -316,6 +345,33 @@ impl ProcColumn {
}
}
+ pub fn try_set(&mut self, column: &ProcessSorting, setting: bool) -> Option<bool> {
+ if let Some(mapping) = self.column_mapping.get_mut(column) {
+ mapping.enabled = setting;
+ Some(mapping.enabled)
+ } else {
+ None
+ }
+ }
+
+ pub fn try_enable(&mut self, column: &ProcessSorting) -> Option<bool> {
+ if let Some(mapping) = self.column_mapping.get_mut(column) {
+ mapping.enabled = true;
+ Some(mapping.enabled)
+ } else {
+ None
+ }
+ }
+
+ pub fn try_disable(&mut self, column: &ProcessSorting) -> Option<bool> {
+ if let Some(mapping) = self.column_mapping.get_mut(column) {
+ mapping.enabled = false;
+ Some(mapping.enabled)
+ } else {
+ None
+ }
+ }
+
pub fn is_enabled(&self, column: &ProcessSorting) -> bool {
if let Some(mapping) = self.column_mapping.get(column) {
mapping.enabled