pub struct MemFdExecutable<'a> {
pub stdin: Option<Stdio>,
pub stdout: Option<Stdio>,
pub stderr: Option<Stdio>,
/* private fields */
}
Expand description
This is the main struct used to create an in-memory only executable. Wherever possible, it
is intended to be a drop-in replacement for the standard library’s process::Command
struct.
§Examples
This example is the “motivating case” for this library. It shows how to execute a binary entirely from memory, without writing it to disk. This is useful for executing binaries sneakily, or (the real reason) for bundling executables that are a pain to set up and compile, but whose static versions are very portable. Here’s a “sneaky” example:
use memfd_exec::{MemFdExecutable, Stdio};
// You can include the entirety of a binary (for example, nc)
let nc_binary= include_bytes!("/usr/bin/nc-static");
// The first argument is just the name for the program, you can pick anything but
// if the program expects a specific argv[0] value, use that.
// The second argument is the binary code to execute.
let mut cmd = MemFdExecutable::new("nc", nc_binary)
// We can pass arbitrary args just like with Command. Here, we'll execute nc
// to listen on a port and run a shell for connections, entirely from memory.
.arg("-l")
.arg("1234")
.arg("-e")
.arg("/bin/sh")
// And we can get piped stdin/stdout just like with Command
.stdout(Stdio::piped())
// Spawn starts the child process and gives us a handle back
.spawn()
.expect("failed to execute process");
// Then, we can wait for the program to exit.
cmd.wait();
Fields§
§stdin: Option<Stdio>
The program’s stdin handle
stdout: Option<Stdio>
The program’s stdout handle
stderr: Option<Stdio>
The program’s stderr handle
Implementations§
Source§impl<'a> MemFdExecutable<'a>
impl<'a> MemFdExecutable<'a>
Sourcepub fn new<S: AsRef<OsStr>>(name: S, code: &'a [u8]) -> Self
pub fn new<S: AsRef<OsStr>>(name: S, code: &'a [u8]) -> Self
Create a new MemFdExecutable with the given name and code. The name is the name of the program, and is used as the argv[0] argument to the program. The code is the binary code to execute (usually, the entire contents of an ELF file).
§Examples
You can run code that is included directly in your executable with include_bytes!()
:
use memfd_exec::MemFdExecutable;
let code = include_bytes!("/usr/bin/nc-static");
let mut cmd = MemFdExecutable::new("nc", code)
.arg("-l")
.arg("1234")
.arg("-e")
.arg("/bin/sh")
.status()
.expect("failed to execute process");
Sourcepub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self
Add an argument to the program. This is equivalent to Command::arg()
.
Sourcepub fn args<I, S>(&mut self, args: I) -> &mut Self
pub fn args<I, S>(&mut self, args: I) -> &mut Self
Add multiple arguments to the program. This is equivalent to Command::args()
.
Sourcepub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self
Add an environment variable to the program. This is equivalent to Command::env()
.
Sourcepub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
Add multiple environment variables to the program. This is equivalent to Command::envs()
.
Sourcepub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Self
pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Self
Remove an environment variable from the program. This is equivalent to Command::env_remove()
.
Sourcepub fn env_clear(&mut self) -> &mut Self
pub fn env_clear(&mut self) -> &mut Self
Clear all environment variables from the program. This is equivalent to Command::env_clear()
.
Sourcepub fn cwd<P: AsRef<Path>>(&mut self, dir: P) -> &mut Self
pub fn cwd<P: AsRef<Path>>(&mut self, dir: P) -> &mut Self
Set the current working directory for the program. This is equivalent to Command::current_dir()
.
Sourcepub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
Set the stdin handle for the program. This is equivalent to Command::stdin()
. The
default is to inherit the current process’s stdin. Note that this Stdio
is not the
same exactly as process::Stdio
, but it is feature-equivalent.
§Examples
This example creates a cat
process that will read in the contents passed to its
stdin handle and write them to a null stdout (i.e. it will be discarded). The same
methodology can be used to read from stderr/stdout.
use std::thread::spawn;
use std::io::Write;
use memfd_exec::{MemFdExecutable, Stdio};
let mut cat_cmd = MemFdExecutable::new("cat", include_bytes!("/bin/cat"))
.stdin(Stdio::piped())
.stdout(Stdio::null())
.spawn()
.expect("failed to spawn cat");
let mut cat_stdin = cat_cmd.stdin.take().expect("failed to open stdin");
spawn(move || {
cat_stdin.write_all(b"hello world").expect("failed to write to stdin");
});
Sourcepub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
Set the stdout handle for the program. This is equivalent to Command::stdout()
. The
§Arguments
cfg
- The configuration for the stdout handle. This will usually be one of the following:Stdio::inherit()
- Inherit the current process’s stdout handleStdio::piped()
- Create a pipe to the child process’s stdout. This can be readStdio::null()
- Discard all output to stdout
§Examples
This example creates a cat
process that will read in the contents passed to its stdin handle
and read them from its stdout handle. The same methodology can be used to read from stderr/stdout.
use std::thread::spawn;
use std::fs::read;
use std::io::{Read, Write};
use memfd_exec::{MemFdExecutable, Stdio};
let mut cat = MemFdExecutable::new("cat", &read("/bin/cat").unwrap())
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("failed to spawn cat");
let mut cat_stdin = cat.stdin.take().expect("failed to open stdin");
let mut cat_stdout = cat.stdout.take().expect("failed to open stdout");
spawn(move || {
cat_stdin.write_all(b"hello world").expect("failed to write to stdin");
});
let mut output = Vec::new();
cat_stdout.read_to_end(&mut output).expect("failed to read from stdout");
assert_eq!(output, b"hello world");
cat.wait().expect("failed to wait on cat");
Sourcepub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self
Set the stderr handle for the program. This is equivalent to Command::stderr()
. The
§Arguments
cfg
- The configuration for the stderr handle. This will usually be one of the following:Stdio::inherit()
- Inherit the current process’s stderr handleStdio::piped()
- Create a pipe to the child process’s stderr. This can be readStdio::null()
- Discard all output to stderr
Sourcepub fn spawn(&mut self) -> Result<Child>
pub fn spawn(&mut self) -> Result<Child>
Spawn the program as a child process. This is equivalent to Command::spawn()
.
Sourcepub fn output(&mut self) -> Result<Output>
pub fn output(&mut self) -> Result<Output>
Spawn the program as a child process and wait for it to complete, obtaining the
output and exit status. This is equivalent to Command::output()
.
Sourcepub fn status(&mut self) -> Result<ExitStatus>
pub fn status(&mut self) -> Result<ExitStatus>
Spawn the program as a child process and wait for it to complete, obtaining the
exit status. This is equivalent to Command::status()
.
Sourcepub fn set_program(&mut self, program: &OsStr)
pub fn set_program(&mut self, program: &OsStr)
Set the program name (argv[0]) to a new value.
§Arguments
name
- The new name for the program. This will be used as the first argument
Sourcepub fn get_cwd(&self) -> &Option<CString>
pub fn get_cwd(&self) -> &Option<CString>
Get the current working directory for the child process.
Sourcepub fn exec(&mut self, default: Stdio) -> Error
pub fn exec(&mut self, default: Stdio) -> Error
Execute the command as a new process, replacing the current process.
This function will not return.
§Arguments
default
- The default stdio to use if the child process does not specify.
Sourcepub fn get_program_cstr(&self) -> &CStr
pub fn get_program_cstr(&self) -> &CStr
Get the program name to use for the child process as a C string.
Sourcepub fn env_saw_path(&self) -> bool
pub fn env_saw_path(&self) -> bool
Get whether PATH has been affected by changes to the environment variables of this command.
Sourcepub fn program_is_path(&self) -> bool
pub fn program_is_path(&self) -> bool
Get whether the program (argv[0]) is a path, as opposed to a name.