2023-01-21 20:55:59 -05:00
|
|
|
use super::Cmd;
|
|
|
|
use clap::{Arg, Command};
|
|
|
|
use std::{
|
|
|
|
env, io,
|
|
|
|
os::unix::{fs, process::CommandExt},
|
|
|
|
process,
|
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct Chroot;
|
|
|
|
|
|
|
|
impl Cmd for Chroot {
|
|
|
|
fn cli(&self) -> clap::Command {
|
|
|
|
Command::new("chroot")
|
|
|
|
.about("run command or interactive shell with special root directory")
|
|
|
|
.author("Nathan Fisher")
|
|
|
|
.version(env!("CARGO_PKG_VERSION"))
|
|
|
|
.args([
|
|
|
|
Arg::new("dir")
|
|
|
|
.short('d')
|
|
|
|
.long("directory")
|
|
|
|
.help("change to this directory after performing the chroot instead of '/'")
|
|
|
|
.value_name("DIRECTORY"),
|
|
|
|
Arg::new("newroot")
|
|
|
|
.value_name("NEWROOT")
|
|
|
|
.num_args(1)
|
|
|
|
.required(true),
|
|
|
|
Arg::new("command")
|
|
|
|
.value_name("COMMAND")
|
|
|
|
.num_args(1)
|
|
|
|
.required(false),
|
|
|
|
Arg::new("arg")
|
|
|
|
.value_name("ARG")
|
|
|
|
.num_args(1..)
|
|
|
|
.requires("command")
|
|
|
|
.allow_hyphen_values(true)
|
|
|
|
.required(false),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
2023-02-04 08:54:27 -05:00
|
|
|
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
|
2023-01-21 20:55:59 -05:00
|
|
|
let Some(newroot) = matches.get_one::<String>("newroot") else {
|
|
|
|
return Err(io::Error::new(io::ErrorKind::Other, "no new root given").into());
|
|
|
|
};
|
|
|
|
let mut command = if let Some(c) = matches.get_one::<String>("command") {
|
|
|
|
process::Command::new(c)
|
|
|
|
} else if let Ok(s) = env::var("SHELL") {
|
|
|
|
process::Command::new(s)
|
|
|
|
} else {
|
|
|
|
process::Command::new("/bin/sh")
|
|
|
|
};
|
|
|
|
let mut command = &mut command;
|
|
|
|
if let Some(mut args) = matches.get_many::<String>("arg") {
|
|
|
|
command = command.args(&mut args);
|
|
|
|
}
|
|
|
|
fs::chroot(newroot)?;
|
|
|
|
if let Some(d) = matches.get_one::<String>("dir") {
|
|
|
|
env::set_current_dir(d)?;
|
|
|
|
} else {
|
|
|
|
env::set_current_dir("/")?;
|
|
|
|
}
|
|
|
|
return Err(command.exec().into());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path(&self) -> Option<crate::Path> {
|
|
|
|
Some(crate::Path::UsrSbin)
|
|
|
|
}
|
|
|
|
}
|