Merge branch 'more-procpos' into 'master'

Fix and port more apps for uutils-procps

See merge request redox-os/redox!2165
This commit is contained in:
Jeremy Soller 2026-05-25 06:51:37 -06:00
commit 858a689d3f
2 changed files with 354 additions and 5 deletions

View File

@ -1,22 +1,41 @@
#TODO: common libc functions such as getsid
#TODO: only watch is working
#TODO: common libc functions such as getsid and utmpx in rustix
[source]
git = "https://github.com/uutils/procps"
rev = "ee98c0a78fe2abe72589f80eb05b455fa228e757"
patches = [ "redox.patch" ]
shallow_clone = true
[build]
template = "custom"
script = """
DYNAMIC_INIT
# TODO: more features support?
CARGO_PROFILE_RELEASE_LTO=thin cookbook_cargo --no-default-features --features pmap,slabtop,sysctl,tload,vmstat,watch
BINS=(
#free
hugetop
pgrep
pidof
pidwait
pkill
pmap
ps
pwdx
skill
snice
sysctl
tload
#top
vmstat
#w
watch
)
(IFS=,; CARGO_PROFILE_RELEASE_LTO=thin cookbook_cargo --no-default-features --features "${BINS[*]}")
for bin in "${BINS[@]}"
do
ln -sv procps "${COOKBOOK_STAGE}/usr/bin/$bin"
done
"""
# conflict with coreutils
rm "${COOKBOOK_STAGE}/usr/bin/ps"
"""

View File

@ -0,0 +1,330 @@
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<Vec<usize>>,
}
+#[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<Self, io::Error> {
+ 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::<usize>()
+ .map_err(|_| io::ErrorKind::InvalidData)?;
+ let euid = parts[1]
+ .parse::<u32>()
+ .map_err(|_| io::ErrorKind::InvalidData)?;
+ let egid = parts[2]
+ .parse::<u32>()
+ .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<Self, io::Error> {
+ 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<ProcessInformation, io::Error> {
+ 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<String, io::Error> {
+ Ok(self.name.clone())
+ }
+
+ pub fn start_time(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+
+ pub fn ppid(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+ pub fn pgid(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+ pub fn sid(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+
+ pub fn uid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.euid)
+ }
+ pub fn euid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.euid)
+ }
+ pub fn gid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.egid)
+ }
+ pub fn egid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.egid)
+ }
+ pub fn suid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.euid)
+ }
+ pub fn sgid(&mut self) -> Result<u32, io::Error> {
+ Ok(self.egid)
+ }
+
+ pub fn signals_caught_mask(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+ pub fn signals_pending_mask(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+ pub fn signals_blocked_mask(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+ pub fn signals_ignored_mask(&mut self) -> Result<u64, io::Error> {
+ Ok(0)
+ }
+
+ pub fn root(&mut self) -> Result<PathBuf, io::Error> {
+ Ok(PathBuf::from("/"))
+ }
+
+ pub fn cgroups(&mut self) -> Result<Vec<CgroupMembership>, io::Error> {
+ Ok(vec![])
+ }
+ pub fn cgroup_v2_path(&mut self) -> Result<String, io::Error> {
+ Err(io::Error::new(io::ErrorKind::Unsupported, "no cgroups"))
+ }
+
+ pub fn run_state(&mut self) -> Result<RunState, io::Error> {
+ 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<HashMap<String, String>, io::Error> {
+ Ok(HashMap::new())
+ }
+
+ pub fn namespaces(&self) -> Result<Namespace, io::Error> {
+ 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, Self::Error> {
+ Self::try_new(value)
+ }
+}
+
+#[cfg(target_os = "linux")]
impl TryFrom<DirEntry> 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<String> {
let stat = String::from(stat);
@@ -767,6 +944,7 @@ fn stat_split(stat: &str) -> Vec<String> {
}
}
+#[cfg(target_os = "linux")]
/// Iterating pid in current system
pub fn walk_process() -> impl Iterator<Item = ProcessInformation> {
WalkDir::new("/proc/")
@@ -778,10 +956,12 @@ pub fn walk_process() -> impl Iterator<Item = ProcessInformation> {
.flat_map(ProcessInformation::try_from)
}
+#[cfg(target_os = "linux")]
static THREAD_REGEX: LazyLock<Regex> = 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<Item = ProcessInformation> {
WalkDir::new("/proc/")
.min_depth(1)
@@ -794,6 +974,38 @@ pub fn walk_threads() -> impl Iterator<Item = ProcessInformation> {
.flat_map(ProcessInformation::try_from)
}
+#[cfg(target_os = "redox")]
+pub fn walk_process() -> impl Iterator<Item = ProcessInformation> {
+ 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<Item = ProcessInformation> {
+ 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<ProcessInformation>) -> 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::<i64>().unwrap();
let stime = proc_info.borrow_mut().stat()[14].parse::<i64>().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<i32> {
}
}
+#[cfg(target_os = "redox")]
+fn getsid(_pid: i32) -> Option<i32> {
+ None
+}
+
// TODO: Temporary add to this file, this function will add to uucore.
#[cfg(target_family = "windows")]
fn getsid(_pid: i32) -> Option<i32> {