use std::os::raw::c_void;
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Timeval {
pub tv_sec: i64,
pub tv_usec: i32,
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Itimerval {
pub it_interval: Timeval,
pub it_value: Timeval,
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ExternProc {
pub p_un: Timeval,
pub p_vmspace: *mut c_void,
pub p_sigacts: usize,
pub p_flag: i32,
pub p_stat: i8,
pub p_pid: i32,
pub p_oppid: i32,
pub p_dupfd: i32,
pub user_stack: *mut c_void,
pub exit_thread: *mut c_void,
pub p_debugger: i32,
pub sigwait: i32,
pub p_estcpu: u32,
pub p_cpticks: i32,
pub p_pctcpu: u32,
pub p_wchan: *mut c_void,
pub p_wmesg: *mut c_void,
pub p_swtime: u32,
pub p_slptime: u32,
pub p_realtimer: Itimerval,
pub p_rtime: Timeval,
pub p_uticks: u64,
pub p_sticks: u64,
pub p_iticks: u64,
pub p_traceflag: i32,
pub p_tracep: *mut c_void,
pub p_siglist: i32,
pub p_textvp: *mut c_void,
pub p_holdcnt: i32,
pub p_sigmask: u32,
pub p_sigignore: u32,
pub p_sigcatch: u32,
pub p_priority: u8,
pub p_usrpri: u8,
pub p_nice: i8,
pub p_comm: [i8; 17],
pub p_pgrp: *mut c_void,
pub p_addr: *mut c_void,
pub p_xstat: u16,
pub p_acflag: u16,
pub p_ru: *mut c_void,
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Pcred {
pub pc_lock: [i8; 72],
pub pc_ucred: *mut c_void,
pub p_ruid: u32,
pub p_svuid: u32,
pub p_rgid: u32,
pub p_svgid: u32,
pub p_refcnt: i32,
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Ucred {
pub cr_ref: i32,
pub cr_uid: u32,
pub cr_ngroups: i16,
pub cr_groups: [u32; 16],
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Vmspace {
pub dummy: i32,
pub dummy2: *mut c_void,
pub dummy3: [i32; 5],
pub dummy4: [*mut c_void; 3],
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Eproc {
pub e_paddr: *mut c_void,
pub e_sess: *mut c_void,
pub e_pcred: Pcred,
pub e_ucred: Ucred,
pub e_vm: Vmspace,
pub e_ppid: i32,
pub e_pgid: i32,
pub e_jobc: i16,
pub e_tdev: i32,
pub e_tpgid: i32,
pub e_tsess: *mut c_void,
pub e_wmesg: [i8; 8],
pub e_xsize: i32,
pub e_xrssize: i16,
pub e_xccount: i16,
pub e_xswrss: i16,
pub e_flag: i32,
pub e_login: [i8; 12],
pub e_spare: [i32; 4],
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct KinfoProc {
pub kp_proc: ExternProc,
pub kp_eproc: Eproc,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct KProcInfo {
pub pid: i32,
pub ppid: i32,
pub pgid: i32,
pub ruid: u32,
pub nice: i32,
pub status: i32,
pub priority: i32,
pub comm: String,
pub flags: i32,
}
impl From<&KinfoProc> for KProcInfo {
fn from(k: &KinfoProc) -> Self {
KProcInfo {
pid: k.kp_proc.p_pid,
ppid: k.kp_eproc.e_ppid,
pgid: k.kp_eproc.e_pgid,
ruid: k.kp_eproc.e_pcred.p_ruid,
nice: i32::from(k.kp_proc.p_nice),
status: i32::from(k.kp_proc.p_stat),
priority: i32::from(k.kp_proc.p_priority),
comm: c_chars_to_string(&k.kp_proc.p_comm),
flags: k.kp_proc.p_flag,
}
}
}
fn c_chars_to_string(buf: &[i8]) -> String {
let bytes: Vec<u8> = buf
.iter()
.take_while(|&&c| c != 0)
.map(|&c| c.to_le_bytes()[0])
.collect();
String::from_utf8_lossy(&bytes).into_owned()
}
#[cfg(test)]
mod layout_tests {
use super::{Itimerval, Timeval};
use std::mem::{align_of, offset_of, size_of};
#[test]
fn timeval_matches_libc() {
assert_eq!(
size_of::<Timeval>(),
size_of::<libc::timeval>(),
"Timeval size must match libc::timeval"
);
assert_eq!(
align_of::<Timeval>(),
align_of::<libc::timeval>(),
"Timeval alignment must match libc::timeval"
);
assert_eq!(offset_of!(Timeval, tv_sec), 0);
assert_eq!(
offset_of!(Timeval, tv_usec),
size_of::<libc::time_t>(),
"tv_usec must follow the full-width tv_sec"
);
}
#[test]
fn itimerval_matches_libc() {
assert_eq!(
size_of::<Itimerval>(),
size_of::<libc::itimerval>(),
"Itimerval size must match libc::itimerval"
);
assert_eq!(align_of::<Itimerval>(), align_of::<libc::itimerval>());
assert_eq!(offset_of!(Itimerval, it_interval), 0);
assert_eq!(
offset_of!(Itimerval, it_value),
size_of::<Timeval>(),
"it_value must follow it_interval"
);
}
}