Skip to content

Commit 1426c50

Browse files
committed
Properly handle option escaping in yes command
1 parent 83b1d13 commit 1426c50

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

src/bin/yes.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
borrow::Cow,
3-
env,
3+
ffi::OsString,
44
io::{BufWriter, Write, stdout},
55
os::unix::ffi::OsStringExt,
66
};
@@ -10,7 +10,7 @@ const HELP: &[u8] = b"Usage: yes [STRING]...\n"; // TODO: properly generate this
1010

1111
use coreutils::{Exit, Result};
1212
use sap::{
13-
Argument::{Long, Short},
13+
Argument::{Long, Short, Value},
1414
Parser,
1515
};
1616

@@ -20,27 +20,35 @@ fn main() -> Result {
2020
// No point in locking stdout since we only use it once in this program
2121
let mut stdout = stdout();
2222

23+
let mut first_value: Option<Vec<u8>> = None;
24+
2325
if let Some(arg) = arg_parser.forward()? {
2426
match arg {
25-
Long("version") => stdout.write_all(VERSION)?,
26-
Long("help") => stdout.write_all(HELP)?,
27+
Long("version") => {
28+
stdout.write_all(VERSION)?;
29+
stdout.flush()?;
30+
31+
return Ok(());
32+
}
33+
Long("help") => {
34+
stdout.write_all(HELP)?;
35+
stdout.flush()?;
36+
37+
return Ok(());
38+
}
2739
Long(_) | Short(_) => return Err(Exit::ArgError(arg.into_error(None))),
28-
_ => {}
40+
Value(value) => first_value = Some(value.as_bytes().to_vec()),
2941
}
42+
}
3043

31-
stdout.flush()?;
44+
let mut args = arg_parser.into_inner();
3245

33-
return Ok(());
46+
if first_value.is_none() {
47+
first_value = args.next().map(OsString::into_vec);
3448
}
3549

36-
// We can easily avoid the overhead of utf-8 since this is unix anyway
37-
let mut args = env::args_os();
38-
args.next(); // Calling next once is actually more efficient than using skip, we need this to skip the program name itself
39-
4050
// We prepare the output so it doesn't need to go through the formatting each time
41-
let output: Cow<'_, [u8]> = if let Some(msg) = args.next() {
42-
let mut first = msg.into_vec(); // The first argument is always ready and we have a preallocated vec, we can just reuse it
43-
51+
let output: Cow<'_, [u8]> = if let Some(mut first) = first_value {
4452
for arg in args {
4553
first.push(b' '); // Manually put the space
4654
first.append(&mut arg.into_vec()); // Append will move the data efficiently from the other vector

0 commit comments

Comments
 (0)