Struct MemFdExecutable

Source
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>

Source

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");
Source

pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self

Add an argument to the program. This is equivalent to Command::arg().

Source

pub fn args<I, S>(&mut self, args: I) -> &mut Self
where I: IntoIterator<Item = S>, S: AsRef<OsStr>,

Add multiple arguments to the program. This is equivalent to Command::args().

Source

pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self
where K: AsRef<OsStr>, V: AsRef<OsStr>,

Add an environment variable to the program. This is equivalent to Command::env().

Source

pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
where I: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>,

Add multiple environment variables to the program. This is equivalent to Command::envs().

Source

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().

Source

pub fn env_clear(&mut self) -> &mut Self

Clear all environment variables from the program. This is equivalent to Command::env_clear().

Source

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().

Source

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");
});
Source

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 handle
    • Stdio::piped() - Create a pipe to the child process’s stdout. This can be read
    • Stdio::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");
Source

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 handle
    • Stdio::piped() - Create a pipe to the child process’s stderr. This can be read
    • Stdio::null() - Discard all output to stderr
Source

pub fn spawn(&mut self) -> Result<Child>

Spawn the program as a child process. This is equivalent to Command::spawn().

Source

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().

Source

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().

Source

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
Source

pub fn get_cwd(&self) -> &Option<CString>

Get the current working directory for the child process.

Source

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.
Source

pub fn get_program_cstr(&self) -> &CStr

Get the program name to use for the child process as a C string.

Source

pub fn get_argv(&self) -> &Vec<CString>

Get the program argv to use for the child process.

Source

pub fn env_saw_path(&self) -> bool

Get whether PATH has been affected by changes to the environment variables of this command.

Source

pub fn program_is_path(&self) -> bool

Get whether the program (argv[0]) is a path, as opposed to a name.

Trait Implementations§

Source§

impl<'a> Debug for MemFdExecutable<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for MemFdExecutable<'a>

§

impl<'a> RefUnwindSafe for MemFdExecutable<'a>

§

impl<'a> Send for MemFdExecutable<'a>

§

impl<'a> Sync for MemFdExecutable<'a>

§

impl<'a> Unpin for MemFdExecutable<'a>

§

impl<'a> UnwindSafe for MemFdExecutable<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.