use std::ffi::OsString; use std::io; use std::path::Path; use crate::{Child, Endpoint, Executable, MAX_DESCRIPTOR}; pub struct Launch<'a> { pub executable: Executable, pub program: &'a Path, pub args: &'a [String], pub env: Vec<(OsString, OsString)>, pub cwd: &'a Path, pub group: bool, pub join: Option<&'a crate::Group>, pub terminal: bool, pub endpoints: Vec<(u32, Endpoint)>, } pub fn spawn(launch: Launch<'_>) -> io::Result { let mut descriptors = std::collections::BTreeSet::new(); if launch .endpoints .iter() .any(|(fd, _)| *fd > MAX_DESCRIPTOR || !descriptors.insert(*fd)) { return Err(io::Error::new( io::ErrorKind::InvalidInput, "Invalid or duplicate subprocess descriptor", )); } if launch.args.iter().any(|arg| arg.contains('\0')) || launch.env.iter().any(|(name, value)| { name.is_empty() || name .as_encoded_bytes() .iter() .enumerate() .any(|(index, byte)| { *byte == 0 || (*byte == b'=' && !(cfg!(windows) && index == 0)) }) || value.as_encoded_bytes().contains(&0) }) || launch.program.as_os_str().as_encoded_bytes().contains(&0) || launch.cwd.as_os_str().as_encoded_bytes().contains(&0) { return Err(io::Error::new( io::ErrorKind::InvalidInput, "Invalid subprocess argument, environment, or path", )); } crate::sys::spawn(launch) }