diff --git a/src/uu/seq/src/seq.rs b/src/uu/seq/src/seq.rs index c90cdb262..4c050c2c7 100644 --- a/src/uu/seq/src/seq.rs +++ b/src/uu/seq/src/seq.rs @@ -40,7 +40,7 @@ const ARG_NUMBERS: &str = "numbers"; #[derive(Clone)] struct SeqOptions<'a> { separator: OsString, - terminator: String, + terminator: OsString, equal_width: bool, format: Option<&'a str>, } @@ -108,10 +108,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .get_one::(OPT_SEPARATOR) .map_or(OsString::from("\n"), |s| s.to_os_string()), terminator: matches - .get_one::(OPT_TERMINATOR) - .map(|s| s.as_str()) - .unwrap_or("\n") - .to_string(), + .get_one::(OPT_TERMINATOR) + .map_or(OsString::from("\n"), |s| s.to_os_string()), equal_width: matches.get_flag(OPT_EQUAL_WIDTH), format: matches.get_one::(OPT_FORMAT).map(|s| s.as_str()), }; @@ -235,7 +233,8 @@ pub fn uu_app() -> Command { Arg::new(OPT_TERMINATOR) .short('t') .long("terminator") - .help(translate!("seq-help-terminator")), + .help(translate!("seq-help-terminator")) + .value_parser(clap::value_parser!(OsString)), ) .arg( Arg::new(OPT_EQUAL_WIDTH) @@ -268,7 +267,7 @@ fn fast_print_seq( increment: u64, last: &BigUint, separator: &OsStr, - terminator: &str, + terminator: &OsStr, padding: usize, ) -> std::io::Result<()> { // Nothing to do, just return. @@ -321,7 +320,7 @@ fn fast_print_seq( } // Write the last number without separator, but with terminator. stdout.write_all(&buf[start..num_end])?; - write!(stdout, "{terminator}")?; + stdout.write_all(terminator.as_encoded_bytes())?; stdout.flush()?; Ok(()) } @@ -338,7 +337,7 @@ fn done_printing(next: &T, increment: &T, last: &T) -> boo fn print_seq( range: RangeFloat, separator: &OsStr, - terminator: &str, + terminator: &OsStr, format: &Format, fast_allowed: bool, padding: usize, // Used by fast path only @@ -383,7 +382,7 @@ fn print_seq( is_first_iteration = false; } if !is_first_iteration { - stdout.write_all(terminator.as_bytes())?; + stdout.write_all(terminator.as_encoded_bytes())?; } stdout.flush()?; Ok(()) diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 3308b4cb5..f82a6228f 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -251,6 +251,29 @@ fn test_separator_non_utf8() { } } +#[test] +#[cfg(target_os = "linux")] +fn test_terminator_non_utf8() { + use std::{ffi::OsString, os::unix::ffi::OsStringExt}; + + fn create_arg(prefix: &[u8]) -> OsString { + let terminator = [0xFF, 0xFE]; + OsString::from_vec([prefix, &terminator].concat()) + } + + let short = create_arg(b"-t"); + let long = create_arg(b"--terminator="); + let expected = [b'1', b'\n', b'2', 0xFF, 0xFE]; + + for arg in [short, long] { + new_ucmd!() + .arg(&arg) + .arg("2") + .succeeds() + .stdout_is_bytes(expected); + } +} + #[test] fn test_equalize_widths() { let args = ["-w", "--equal-width"];