add environment variable configuration
This commit is contained in:
parent
f5273c1fd3
commit
795bdbe4d7
|
@ -1,3 +1,8 @@
|
||||||
|
use std::{
|
||||||
|
io::{BufRead, BufReader},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::platform::{self, Platform};
|
use crate::platform::{self, Platform};
|
||||||
use crate::result::{Context, Result};
|
use crate::result::{Context, Result};
|
||||||
|
|
||||||
|
@ -12,6 +17,31 @@ pub struct Config {
|
||||||
pub platform: Option<Box<dyn Platform>>,
|
pub platform: Option<Box<dyn Platform>>,
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub target: String,
|
pub target: String,
|
||||||
|
pub environment: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_environment() -> Result<Vec<String>> {
|
||||||
|
let mut environment = vec![];
|
||||||
|
let environment_file = PathBuf::from("/etc/environment");
|
||||||
|
|
||||||
|
// NOTE: We should never have to care about permissions. Therefore, we don't use .try_exists()
|
||||||
|
// As for TOCTOU... we're init, and this is the first code to run.
|
||||||
|
if environment_file.exists() {
|
||||||
|
let file = std::fs::File::open(&environment_file).context(format_args!(
|
||||||
|
"could not open: {environment_file}",
|
||||||
|
environment_file = environment_file.display(),
|
||||||
|
))?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
for line in reader.lines() {
|
||||||
|
let line = line.context(format_args!(
|
||||||
|
"could not read line from: {environment_file}",
|
||||||
|
environment_file = environment_file.display()
|
||||||
|
))?;
|
||||||
|
environment.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_config() -> Result<Config> {
|
pub fn get_config() -> Result<Config> {
|
||||||
|
@ -39,7 +69,16 @@ pub fn get_config() -> Result<Config> {
|
||||||
|
|
||||||
let platform = platform::get_current_platform(values.remove("platform").as_deref())?;
|
let platform = platform::get_current_platform(values.remove("platform").as_deref())?;
|
||||||
|
|
||||||
let target = values.remove("target").unwrap_or(String::from("/usr/bin/hello"));
|
let target = values
|
||||||
|
.remove("target")
|
||||||
|
.unwrap_or(String::from("/usr/bin/hello"));
|
||||||
|
|
||||||
Ok(Config { platform, mode, target })
|
let environment = get_environment()?;
|
||||||
|
|
||||||
|
Ok(Config {
|
||||||
|
platform,
|
||||||
|
mode,
|
||||||
|
target,
|
||||||
|
environment,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
extern "C" fn handle_sigchld(_sig: i32) {
|
extern "C" fn handle_sigchld(_sig: i32) {
|
||||||
// wait on all dead processes
|
// wait on all dead processes
|
||||||
while system::syscall::waitpid(-1, libc::WNOHANG).is_ok() {
|
while system::syscall::waitpid(-1, libc::WNOHANG).is_ok() {
|
||||||
|
@ -66,7 +67,8 @@ fn init() -> Result<()> {
|
||||||
}
|
}
|
||||||
config::Mode::Exec => {
|
config::Mode::Exec => {
|
||||||
dmesg(format!("pivoting to {command}"));
|
dmesg(format!("pivoting to {command}"));
|
||||||
system::syscall::execv(command, &[])?;
|
let envs = config.environment.iter().map(|e| &**e).collect::<Vec<_>>();
|
||||||
|
system::syscall::execve(command, &[], &envs)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ pub fn close(fd: RawFd) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execv(command: impl AsRef<Path>, args: &[&str]) -> Result<()> {
|
pub fn execve(command: impl AsRef<Path>, args: &[&str], envs: &[&str]) -> Result<()> {
|
||||||
let command = command.as_ref();
|
let command = command.as_ref();
|
||||||
|
|
||||||
let command_cstr = CString::new(command.as_os_str().as_encoded_bytes())
|
let command_cstr = CString::new(command.as_os_str().as_encoded_bytes())
|
||||||
|
@ -213,7 +213,21 @@ pub fn execv(command: impl AsRef<Path>, args: &[&str]) -> Result<()> {
|
||||||
.chain(std::iter::once(std::ptr::null()))
|
.chain(std::iter::once(std::ptr::null()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if unsafe { libc::execv(command_cstr.as_ptr().cast(), args_ptrs.as_ptr().cast()) } == -1 {
|
let mut envs_cstr = vec![command_cstr.clone()];
|
||||||
|
for env in envs {
|
||||||
|
let cur_env_cstr = CString::new(env.as_bytes()).context(format_args!("bad env: {env}"))?;
|
||||||
|
envs_cstr.push(cur_env_cstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: The last env must be a null pointer, but we can't construct a CString from nullptr, so
|
||||||
|
// we construct an array of pointers and use that
|
||||||
|
let envs_ptrs: Vec<_> = envs_cstr
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.as_ptr())
|
||||||
|
.chain(std::iter::once(std::ptr::null()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if unsafe { libc::execve(command_cstr.as_ptr().cast(), args_ptrs.as_ptr().cast(), envs_ptrs.as_ptr().cast()) } == -1 {
|
||||||
return ctx_os_error(format_args!(
|
return ctx_os_error(format_args!(
|
||||||
"error calling exec({command}, {args:?})",
|
"error calling exec({command}, {args:?})",
|
||||||
command = command.display()
|
command = command.display()
|
||||||
|
|
Loading…
Reference in New Issue