use super::BWInfo;
use crate::{GlobalsFinal, LogCommand};
use anyhow::{Context, Result as AResult};
use command_fds::CommandFdExt;
use os_pipe::pipe;
use std::io::Write;
use std::os::fd::AsRawFd;
use std::process::{self, Command};
pub fn launch(args: Vec<String>, globals: &GlobalsFinal) -> AResult<()> {
let (mut rinfo, winfo) = pipe()?;
let fdinfo = winfo.as_raw_fd();
let (rblock, mut wblock) = pipe()?;
let fdblock = rblock.as_raw_fd();
let pipeargs: Vec<String> = format!("--info-fd {fdinfo} --userns-block-fd {fdblock}")
.split_whitespace()
.map(|x| x.to_string())
.collect();
let mut bwrap = Command::new("bwrap");
bwrap
.args(pipeargs)
.args(args)
.preserved_fds(vec![winfo.into(), rblock.into()]);
bwrap.log("Bubblewrap cmd");
if globals.dry_run() {
process::exit(0);
}
let mut child = bwrap.spawn().context("Failed to spawn bwrap")?;
log::debug!("Spawned bubblewrap. PID: {}", child.id());
let info = BWInfo::acquire(&mut rinfo)?;
log::debug!(
"Started command. PID: {}. Blocked for ID mapping",
info.child_pid
);
let (uidmaps, gidmaps) = globals.idmaps();
info.map_ids(uidmaps, gidmaps)?;
log::debug!("Successfully configured userns. Unlocking command");
wblock.write_all(b"1")?;
wblock.flush()?;
let code = child.wait()?.code().unwrap_or_default();
log::debug!("Bubblewrap exited with code {code}");
process::exit(code);
}