An open API service indexing awesome lists of open source software.

https://github.com/freaky/command-limits

Build command lines that respect argument size limits
https://github.com/freaky/command-limits

Last synced: about 1 month ago
JSON representation

Build command lines that respect argument size limits

Awesome Lists containing this project

README

          

# command_limits

Detect and enforce platform argument/environment size limits for command execution.

## Synopsis

```rust
pub struct CommandLimits {
pub arg_size: NonZeroUsize,
pub individual_arg_size: Option,
pub arg_count: Option,
pub env_size: Option,
pub individual_env_size: Option,
pub env_count: Option,
}

pub enum Error {
InsufficientSpace,
TooMany,
TooLarge,
}

pub type Result = std::result::Result;

pub struct CommandBuilder { /* private */ }

impl CommandBuilder {
pub fn new(command: S) -> Result
where
S: AsRef;

pub fn new_capture_env(command: S) -> Result
where
S: AsRef;

pub fn with_limits(command: S, limits: CommandLimits) -> Result
where
S: AsRef;

pub fn capture_with_limits(command: S, limits: CommandLimits) -> Result
where
S: AsRef;

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

pub fn args(&mut self, args: &[S]) -> Result<&mut Self>
where
S: AsRef;

pub fn env(&mut self, key: K, value: V) -> Result<&mut Self>
where
K: AsRef,
V: AsRef;

pub fn env_remove(&mut self, key: K) -> &mut Self
where
K: AsRef;

pub fn inherit_env(&mut self) -> Result<&mut Self>;
pub fn capture_env(&mut self) -> Result<&mut Self>;
pub fn env_clear(&mut self) -> &mut Self;
pub fn into_command(&self) -> std::process::Command;
pub fn get_program(&self) -> &OsStr;
pub fn get_args(&self) -> &[OsString];
pub fn get_limits(&self) -> CommandLimits;
pub fn arg_size(&self) -> usize;
pub fn env_size(&self) -> usize;
}

impl From<&CommandBuilder> for std::process::Command;
```

## Description

`command_limits` provides a `CommandLimits` type specifying typical limits on the
size or number of command arguments and environment variables, and a `CommandBuilder`
which uses it to provide a fallible interface for specifying them.

This allows for the reliable creation of long command lines across different platforms,
without the need to shell out to `xargs(1)`.

## Example

Typical use is similar to that of `std::process::Command`, but with fallible methods
for specifying arguments and environment variables:

```rust
use command_limits::CommandBuilder;

let mut cmd = CommandBuilder::new("echo")?;
cmd.arg("hello, world")?.env("PATH", "/bin")?;
cmd.into_command().spawn()?;
```

By executing `arg()` or `args()` until `Error::TooMany` or `Error::InsufficientSpace`
is returned, an application can execute as long of a command as should be reasonably
expected to fit in the current environment.

`Error::TooLarge` indicates the argument or environment variable exceeds maximal limits
and cannot be specified even in principle.

Here we use `CommandBuilder` to echo the contents of a vec in as few calls as possible.

```rust
fn echo_vec(items: Vec) -> Result {
let base = CommandBuilder::new("/bin/echo")?;
let mut cmd = base.clone();

for arg in items {
match cmd.arg(arg) {
Ok(_) => continue,
Err(Error::TooLarge) => continue,
Err(_) => {
cmd.into_command().status()?;
cmd = base.clone();
}
}
}

cmd.into_command().status()?;
Ok(());
}
```