char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somrearrange libs into lib and extensions into extsf4a0f5b

main
1.6 KiB52 linesraw
1use std::ffi::OsString;
2use std::io;
3use std::path::Path;
4
5use crate::{Child, Endpoint, Executable, MAX_DESCRIPTOR};
6
7pub struct Launch<'a> {
8    pub executable: Executable,
9    pub program: &'a Path,
10    pub args: &'a [String],
11    pub env: Vec<(OsString, OsString)>,
12    pub cwd: &'a Path,
13    pub group: bool,
14    pub join: Option<&'a crate::Group>,
15    pub terminal: bool,
16    pub endpoints: Vec<(u32, Endpoint)>,
17}
18
19pub fn spawn(launch: Launch<'_>) -> io::Result<Child> {
20    let mut descriptors = std::collections::BTreeSet::new();
21    if launch
22        .endpoints
23        .iter()
24        .any(|(fd, _)| *fd > MAX_DESCRIPTOR || !descriptors.insert(*fd))
25    {
26        return Err(io::Error::new(
27            io::ErrorKind::InvalidInput,
28            "Invalid or duplicate subprocess descriptor",
29        ));
30    }
31    if launch.args.iter().any(|arg| arg.contains('\0'))
32        || launch.env.iter().any(|(name, value)| {
33            name.is_empty()
34                || name
35                    .as_encoded_bytes()
36                    .iter()
37                    .enumerate()
38                    .any(|(index, byte)| {
39                        *byte == 0 || (*byte == b'=' && !(cfg!(windows) && index == 0))
40                    })
41                || value.as_encoded_bytes().contains(&0)
42        })
43        || launch.program.as_os_str().as_encoded_bytes().contains(&0)
44        || launch.cwd.as_os_str().as_encoded_bytes().contains(&0)
45    {
46        return Err(io::Error::new(
47            io::ErrorKind::InvalidInput,
48            "Invalid subprocess argument, environment, or path",
49        ));
50    }
51    crate::sys::spawn(launch)
52}