use getargv_sys as ffi;
use std::{
ffi::c_char,
io::{Error, Result},
mem,
};
#[derive(Debug)]
pub struct Argv(ffi::ArgvResult);
impl Argv {
pub fn print(&self) -> Result<()> {
if unsafe {
ffi::print_argv_of_pid(
self.0.start_pointer as *const c_char,
self.0.end_pointer as *const c_char,
)
} {
Ok(())
} else {
Err(Error::last_os_error())
}
}
pub fn len(&self) -> usize {
if self.0.start_pointer.is_null() || self.0.end_pointer.is_null() {
0
} else {
unsafe { self.0.end_pointer.offset_from(self.0.start_pointer).try_into().unwrap() }
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Default for Argv {
fn default() -> Self {
unsafe { mem::zeroed() }
}
}
unsafe impl Send for Argv {}
unsafe impl Sync for Argv {}
impl Drop for Argv {
fn drop(&mut self) {
unsafe { ffi::free_ArgvResult(&mut self.0) }
}
}
pub fn get_argv_of_pid(pid: ffi::pid_t, nuls: bool, skip: ffi::uint) -> Result<Argv> {
let options = ffi::GetArgvOptions { skip, pid, nuls };
let mut result: ffi::ArgvResult = Default::default();
let succeeded: bool = unsafe { ffi::get_argv_of_pid(&options, &mut result) };
if succeeded {
Ok(Argv(result))
} else {
Err(Error::last_os_error())
}
}
#[cfg(test)]
mod tests {
use super::*;
use libc::ESRCH;
use std::process;
use std::fmt::Write;
#[test]
fn get_argv_of_pid_sanity_check_ok() {
let result = get_argv_of_pid(process::id().try_into().unwrap(), false, 0);
assert!(result.is_ok());
}
#[test]
fn get_argv_of_pid_sanity_check_err() {
let result = get_argv_of_pid(-1, false, 0);
assert!(result.is_err());
assert_eq!(result.unwrap_err().raw_os_error().unwrap(), ESRCH);
}
#[test]
fn argv_print_sanity_check() {
let result = get_argv_of_pid(process::id().try_into().unwrap(), false, 0);
assert!(result.is_ok());
let result = result.unwrap();
assert!(result.print().is_ok());
}
#[test]
fn argv_default_trait_sanity_check() {
let argv: Argv = Default::default();
assert_eq!(argv.0.buffer, std::ptr::null_mut());
assert_eq!(argv.0.start_pointer, std::ptr::null_mut());
assert_eq!(argv.0.end_pointer, std::ptr::null_mut());
}
#[test]
fn argv_debug_trait_sanity_check() {
let argv: Argv = Default::default();
let mut output = String::new();
write!(&mut output, "{:?}",argv)
.expect("Error occurred while trying to write in String");
assert_eq!(output, "Argv(ArgvResult { buffer: 0x0, start_pointer: 0x0, end_pointer: 0x0 })");
}
}