use super::*; use std::{ path::{Path,PathBuf,}, }; impl ProcessArgs { pub fn parse(string: &mut T, not_last: &mut bool) -> Result where T: Iterator, U: AsRef { let name = string.next().ok_or("No process name")?.as_ref().to_owned(); let mut args = Vec::new(); *not_last = false; while let Some(arg) = string.next() { let arg = arg.as_ref(); let mut chars = arg.chars(); if let Some(BROKEN_PIPE) = chars.next() { *not_last = true; break; } else { args.push(arg.to_owned()); } } Ok(Self{ name, args, name_real: None, }) } pub fn name_path(&self) -> Result<&Path, &'static str> { if let Some(buf) = &self.name_real { Ok(buf.as_ref()) } else { Err("No name_path specified, have you called `verify()`?") } } pub fn verify(&self) -> Result { if let Ok(spath) = std::env::var("LEAKY_PIPE_PATH") { if let Some(path) = find_somewhere(&self.name, spath.split(':')) { return Ok(path) } } if let Ok(spath) = std::env::var("PATH") { if let Some(path) = find_somewhere(&self.name, spath.split(':')) { Ok(path) } else { Err("File not found") } } else { match Path::new(&self.name) { path if path.exists() => Ok(Path::new(&self.name).to_owned()), _ => Err("File not found and $PATH not found.") } } } } fn find_somewhere(name: T, places: U) -> Option where T: AsRef, U: IntoIterator, V: AsRef { let name = name.as_ref(); for place in places.into_iter() { let place = place.as_ref(); let pbuf = Path::new(&place).join(&name); if pbuf.exists() { return Some(pbuf); } } None } fn escape(s: &T) -> String where T: AsRef + ?Sized { let s = s.as_ref(); let mut o = String::with_capacity(s.len()); for c in s.chars() { match c { '\\' => { o.push('\\'); o.push('\\'); }, '\'' => { o.push('\\'); o.push('\''); }, other => o.push(other), }; } o } use std::fmt; impl fmt::Display for ProcessArgs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} ", self.name)?; let len = self.args.len(); for (i,x) in (0..len).zip(self.args.iter()) { write!(f, "{}", &x)?; if i < len-1 { write!(f, " ")?; } } Ok(()) } }