diff --git a/src/uu/pgrep/src/process.rs b/src/uu/pgrep/src/process.rs index 6dce047..a1721ac 100644 --- a/src/uu/pgrep/src/process.rs +++ b/src/uu/pgrep/src/process.rs @@ -422,6 +422,7 @@ impl Namespace { } /// Process ID and its information +#[cfg(target_os = "linux")] #[derive(Debug, Clone, Default)] pub struct ProcessInformation { pub pid: usize, @@ -440,6 +441,21 @@ pub struct ProcessInformation { thread_ids: OnceLock>, } +#[cfg(target_os = "redox")] +#[derive(Debug, Clone, Default)] +pub struct ProcessInformation { + pub pid: usize, + pub cmdline: String, + pub name: String, + pub euid: u32, + pub egid: u32, + pub time_str: String, + pub run_state_str: String, + pub inner_status: String, + pub inner_stat: String, +} + +#[cfg(target_os = "linux")] impl ProcessInformation { /// Try new with pid path such as `/proc/self` /// @@ -729,6 +745,166 @@ impl ProcessInformation { Namespace::from_pid(self.pid) } } + +#[cfg(target_os = "redox")] +impl ProcessInformation { + pub fn try_new(line: &str) -> Result { + let parts: Vec<&str> = line.split_whitespace().collect(); + // PID EUID EGID STAT CPU AFFINITY TIME PRIVATE PRIVATE_UNIT SHARED SHARED_UNIT NAME + if parts.len() < 12 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "parts incomplete", + )); + } + + let pid = parts[0] + .parse::() + .map_err(|_| io::ErrorKind::InvalidData)?; + let euid = parts[1] + .parse::() + .map_err(|_| io::ErrorKind::InvalidData)?; + let egid = parts[2] + .parse::() + .map_err(|_| io::ErrorKind::InvalidData)?; + let run_state_str = parts[3].to_string(); + let time_str = parts[6].to_string(); + + let name = parts.last().unwrap_or(&"").to_string(); + let cmdline = name.clone(); + + Ok(Self { + pid, + cmdline, + name, + euid, + egid, + run_state_str, + time_str, + inner_status: String::new(), + inner_stat: String::new(), + }) + } + + pub fn from_pid(pid: usize) -> Result { + let content = fs::read_to_string("/scheme/sys/context")?; + for line in content.lines() { + if let Ok(proc_info) = Self::try_new(line) { + if proc_info.pid == pid { + return Ok(proc_info); + } + } + } + Err(io::Error::new(io::ErrorKind::NotFound, "no process found")) + } + + pub fn current_process_info() -> Result { + let pid = rustix::process::getpid(); + Self::from_pid(pid.as_raw_pid() as usize) + } + + pub fn proc_status(&self) -> &str { + "" + } + pub fn proc_stat(&self) -> &str { + "" + } + + pub fn name(&mut self) -> Result { + Ok(self.name.clone()) + } + + pub fn start_time(&mut self) -> Result { + Ok(0) + } + + pub fn ppid(&mut self) -> Result { + Ok(0) + } + pub fn pgid(&mut self) -> Result { + Ok(0) + } + pub fn sid(&mut self) -> Result { + Ok(0) + } + + pub fn uid(&mut self) -> Result { + Ok(self.euid) + } + pub fn euid(&mut self) -> Result { + Ok(self.euid) + } + pub fn gid(&mut self) -> Result { + Ok(self.egid) + } + pub fn egid(&mut self) -> Result { + Ok(self.egid) + } + pub fn suid(&mut self) -> Result { + Ok(self.euid) + } + pub fn sgid(&mut self) -> Result { + Ok(self.egid) + } + + pub fn signals_caught_mask(&mut self) -> Result { + Ok(0) + } + pub fn signals_pending_mask(&mut self) -> Result { + Ok(0) + } + pub fn signals_blocked_mask(&mut self) -> Result { + Ok(0) + } + pub fn signals_ignored_mask(&mut self) -> Result { + Ok(0) + } + + pub fn root(&mut self) -> Result { + Ok(PathBuf::from("/")) + } + + pub fn cgroups(&mut self) -> Result, io::Error> { + Ok(vec![]) + } + pub fn cgroup_v2_path(&mut self) -> Result { + Err(io::Error::new(io::ErrorKind::Unsupported, "no cgroups")) + } + + pub fn run_state(&mut self) -> Result { + match self.run_state_str.as_str() { + "RR" | "UR" => RunState::try_from("R"), + "UB" => RunState::try_from("S"), + _ => RunState::try_from("S"), + } + } + + pub fn tty(&mut self) -> Teletype { + Teletype::Unknown + } + + pub fn thread_ids(&mut self) -> &[usize] { + &[] + } + + pub fn env_vars(&self) -> Result, io::Error> { + Ok(HashMap::new()) + } + + pub fn namespaces(&self) -> Result { + Err(io::Error::new(io::ErrorKind::Unsupported, "no namespaces")) + } +} +#[cfg(target_os = "redox")] +impl TryFrom<&str> for ProcessInformation { + type Error = io::Error; + + fn try_from(value: &str) -> Result { + Self::try_new(value) + } +} + +#[cfg(target_os = "linux")] impl TryFrom for ProcessInformation { type Error = io::Error; @@ -751,6 +927,7 @@ impl Hash for ProcessInformation { /// Parsing `/proc/self/stat` file. /// /// TODO: If possible, test and use regex to replace this algorithm. +#[cfg(target_os = "linux")] fn stat_split(stat: &str) -> Vec { let stat = String::from(stat); @@ -767,6 +944,7 @@ fn stat_split(stat: &str) -> Vec { } } +#[cfg(target_os = "linux")] /// Iterating pid in current system pub fn walk_process() -> impl Iterator { WalkDir::new("/proc/") @@ -778,10 +956,12 @@ pub fn walk_process() -> impl Iterator { .flat_map(ProcessInformation::try_from) } +#[cfg(target_os = "linux")] static THREAD_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"^/proc/[0-9]+$|^/proc/[0-9]+/task$|^/proc/[0-9]+/task/[0-9]+$").unwrap() }); +#[cfg(target_os = "linux")] pub fn walk_threads() -> impl Iterator { WalkDir::new("/proc/") .min_depth(1) @@ -794,6 +974,38 @@ pub fn walk_threads() -> impl Iterator { .flat_map(ProcessInformation::try_from) } +#[cfg(target_os = "redox")] +pub fn walk_process() -> impl Iterator { + use std::collections::HashSet; + + let content = fs::read_to_string("/scheme/sys/context").unwrap(); + + let mut processes = Vec::new(); + let mut seen_pids = HashSet::new(); + + for line in content.lines() { + if let Ok(proc_info) = ProcessInformation::try_new(line) { + if seen_pids.insert(proc_info.pid) { + processes.push(proc_info); + } + } + } + processes.into_iter() +} + +#[cfg(target_os = "redox")] +pub fn walk_threads() -> impl Iterator { + let content = fs::read_to_string("/scheme/sys/context").unwrap(); + + let mut threads = Vec::new(); + for line in content.lines() { + if let Ok(proc_info) = ProcessInformation::try_new(line) { + threads.push(proc_info); + } + } + threads.into_iter() +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/uu/pgrep/src/process_matcher.rs b/src/uu/pgrep/src/process_matcher.rs index c991092..33adcff 100644 --- a/src/uu/pgrep/src/process_matcher.rs +++ b/src/uu/pgrep/src/process_matcher.rs @@ -452,14 +452,14 @@ pub fn getpgrp() -> u64 { /// Dummy implementation for unsupported platforms. pub fn getsid(_pid: u32) -> u64 { - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "redox")))] { rustix::process::getsid(None) .ok() .map(|pid: rustix::process::Pid| pid.as_raw_nonzero().get() as u64) .unwrap_or(0) } - #[cfg(not(unix))] + #[cfg(not(all(unix, not(target_os = "redox"))))] { 0 } diff --git a/src/uu/ps/src/picker.rs b/src/uu/ps/src/picker.rs index be0a1c4..496bf2d 100644 --- a/src/uu/ps/src/picker.rs +++ b/src/uu/ps/src/picker.rs @@ -148,13 +148,17 @@ fn time(proc_info: RefCell) -> String { // https://docs.kernel.org/filesystems/proc.html#id10 // Index of 13 14 + #[cfg(target_os = "linux")] let cumulative_cpu_time = { let utime = proc_info.borrow_mut().stat()[13].parse::().unwrap(); let stime = proc_info.borrow_mut().stat()[14].parse::().unwrap(); - (utime + stime) / 100 + format_time((utime + stime) / 100) }; - format_time(cumulative_cpu_time) + #[cfg(target_os = "redox")] + let cumulative_cpu_time = { proc_info.borrow_mut().time_str.clone() }; + + cumulative_cpu_time } fn format_time(seconds: i64) -> String { diff --git a/src/uu/ps/src/process_selection.rs b/src/uu/ps/src/process_selection.rs index c2a0a5a..65c33a2 100644 --- a/src/uu/ps/src/process_selection.rs +++ b/src/uu/ps/src/process_selection.rs @@ -20,6 +20,11 @@ fn getsid(pid: i32) -> Option { } } +#[cfg(target_os = "redox")] +fn getsid(_pid: i32) -> Option { + None +} + // TODO: Temporary add to this file, this function will add to uucore. #[cfg(target_family = "windows")] fn getsid(_pid: i32) -> Option {