profile
viewpoint

tmiasko/pyjags 8

PyJAGS: The Python Interface to JAGS

tmiasko/fsb-vorbis-extractor 3

FSB Vorbis Extractor

tmiasko/gabi 0

gobject-introspection ABI validator

tmiasko/rust 0

Empowering everyone to build reliable and efficient software.

issue openedtmiasko/shell-words

Proposal: fail on unquoted shell meta-characters

I'm proposing to introduce a new function akin to split that should either

  • Split the string in the exact the same way as the real shell would do.
  • Or, return an error.

That is, things like && should not be treated as literal strings because the shell wouldn't do so.

So, it should pass the following unit test specification:

// These commands are guaranteed to be interpreted in the same way as the real shell would do.
assert_eq!(split2("foo bar baz"), Ok(vec!["foo", "bar", "baz"]));
assert_eq!(split2("foo 'bar' baz"), Ok(vec!["foo", "bar", "baz"]));
assert_eq!(split2("foo '$bar' baz"), Ok(vec!["foo", "$bar", "baz"]));
assert_eq!(split2("foo '~/bar' baz"), Ok(vec!["foo", "~/bar", "baz"]));
assert_eq!(split2(r#"foo bar "&&" baz"#), Ok(vec!["foo", "bar", "&&", "baz"]));

// The following commands are complicated. We are unable to expand them in the exact same way as the shell would do.
// So, return an error instead. It is advised to run these commands in the actual shell (`sh -c`).
assert_eq!(split2("foo bar; baz"), Err(ParseError)); // more than one command
assert_eq!(split2("foo bar && baz"), Err(ParseError)); // more than one command
assert_eq!(split2("foo bar &"), Err(ParseError)); // background
assert_eq!(split2(r#"foo "$bar" baz"#), Err(ParseError)); // variable expanding
assert_eq!(split2("foo ~/bar baz"), Err(ParseError)); // tilde expanding
assert_eq!(split2("foo bar=~/baz"), Err(ParseError)); // tilde expanding (in bash, but not in the posix shell)
assert_eq!(split2("export foo=bar"), Err(ParseError)); // builtin used

Use-case: with this function, we would be able to implement an optimized shell_exec function, bypassing the real shell in simple cases.

fn shell_exec(command: &str) {
	let c = if let Some(args) = shell_words::split2(command) {
		// Fast path: no need to start the real shell.
		Command::new(&args[0]).args(&args[1..])
	} else {
		// Slow path: we need to start the shell for the complicated command.
		Command::new("sh").arg("-c").arg(command)
	};
	c.spawn().unwrap().wait().unwrap();
}

created time in a month

issue openedtmiasko/shell-words

Return position of unmatched quote

split does not return the place at which an error occurred. This makes it impossible for user interfaces to indicate the error location.

Please add a second function split2 that returns the UTF-8 index of the opening quote.

created time in a month

startedtmiasko/fsb-vorbis-extractor

started time in 3 months

startedtmiasko/arbtt-capture

started time in 3 months

more