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
- Host: GitHub
- URL: https://github.com/freaky/command-limits
- Owner: Freaky
- Created: 2022-06-09T16:43:33.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2022-06-13T17:04:53.000Z (almost 4 years ago)
- Last Synced: 2025-12-02T11:56:19.762Z (6 months ago)
- Language: Rust
- Size: 13.7 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
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(());
}
```