use integrations::osx::ffi::*;
use libc::*;
use std;
use types::*;
pub struct ProcessInfoIterator {
pids: Vec<i32>,
index: isize,
}
impl ProcessInfoIterator {
#[inline]
pub fn new() -> ProcessInfoIterator {
ProcessInfoIterator {
pids: Vec::new(),
index: -1,
}
}
}
impl std::iter::Iterator for ProcessInfoIterator {
type Item = Result<ProcessInfo, Error>;
#[inline]
fn next(&mut self) -> Option<Result<ProcessInfo, Error>> {
unsafe {
self.index += 1;
if self.index == 0 {
self.pids = match get_pids() {
Result::Ok(pids) => pids,
Result::Err(err) => return Option::Some(Result::Err(err)),
};
}
if self.index as usize >= self.pids.len() {
return Option::None;
}
let pid = self.pids[self.index as usize];
let name = match get_name(pid) {
Result::Ok(name) => name,
Result::Err(err) => return Option::Some(Result::Err(err)),
};
let info = match get_info(pid) {
Result::Ok(info) => info,
Result::Err(err) => return Option::Some(Result::Err(err)),
};
Option::Some(Result::Ok(ProcessInfo {
name,
pid: info.pbi_pid,
parent_pid: info.pbi_ppid,
}))
}
}
}
#[inline]
unsafe fn get_pids() -> Result<Vec<i32>, Error> {
let buf_size = proc_listpids(PROC_ALL_PIDS, 0, std::ptr::null_mut(), 0);
if buf_size <= 0 {
return Result::Err(Error::foreign_with_errno("proc_listpids"));
}
let pids_count = buf_size as usize / 4;
let mut pids = Vec::<i32>::with_capacity(pids_count);
let buf_ptr = pids.as_mut_ptr() as *mut c_void;
if proc_listpids(PROC_ALL_PIDS, 0, buf_ptr, buf_size as u32) <= 0 {
return Result::Err(Error::foreign_with_errno("proc_listpids"));
}
pids.set_len(pids_count);
Result::Ok(pids)
}
#[inline]
unsafe fn get_name(pid: i32) -> Result<String, Error> {
let mut buf = Vec::<u8>::with_capacity(PROC_PIDPATHINFO_MAXSIZE);
let buf_ptr = buf.as_mut_ptr() as *mut c_void;
let buf_size = buf.capacity() as u32;
let name_len = proc_name(pid, buf_ptr, buf_size);
if name_len <= 0 {
return Result::Err(Error::foreign_with_errno("proc_name"));
}
buf.set_len(name_len as usize);
match String::from_utf8(buf) {
Result::Ok(name) => Result::Ok(name),
Result::Err(err) => {
let description = String::from("Can't parse process name");
Result::Err(Error::internal_with_cause(description, &err))
}
}
}
#[inline]
unsafe fn get_info(pid: i32) -> Result<proc_bsdinfo, Error> {
let mut info = std::mem::zeroed::<proc_bsdinfo>();
let buf_ptr = &mut info as *mut _ as *mut c_void;
let buf_size = std::mem::size_of::<proc_bsdinfo>() as i32;
if proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, buf_ptr, buf_size) <= 0 {
return Result::Err(Error::foreign_with_errno("proc_pidinfo"));
}
Result::Ok(info)
}